logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

relay.ex (3307B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.ActivityPub.Relay do
  5. alias Pleroma.Activity
  6. alias Pleroma.User
  7. alias Pleroma.Web.ActivityPub.ActivityPub
  8. alias Pleroma.Web.ActivityPub.Visibility
  9. alias Pleroma.Web.CommonAPI
  10. require Logger
  11. @nickname "relay"
  12. @spec ap_id() :: String.t()
  13. def ap_id, do: "#{Pleroma.Web.Endpoint.url()}/#{@nickname}"
  14. @spec get_actor() :: User.t() | nil
  15. def get_actor, do: User.get_or_create_service_actor_by_ap_id(ap_id(), @nickname)
  16. @spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
  17. def follow(target_instance) do
  18. with %User{} = local_user <- get_actor(),
  19. {:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance),
  20. {:ok, _, _, activity} <- CommonAPI.follow(local_user, target_user) do
  21. Logger.info("relay: followed instance: #{target_instance}; id=#{activity.data["id"]}")
  22. {:ok, activity}
  23. else
  24. error -> format_error(error)
  25. end
  26. end
  27. @spec unfollow(String.t(), map()) :: {:ok, Activity.t()} | {:error, any()}
  28. def unfollow(target_instance, opts \\ %{}) do
  29. with %User{} = local_user <- get_actor(),
  30. {:ok, target_user} <- fetch_target_user(target_instance, opts),
  31. {:ok, activity} <- ActivityPub.unfollow(local_user, target_user) do
  32. case target_user.id do
  33. nil -> User.update_following_count(local_user)
  34. _ -> User.unfollow(local_user, target_user)
  35. end
  36. Logger.info("relay: unfollowed instance: #{target_instance}: id=#{activity.data["id"]}")
  37. {:ok, activity}
  38. else
  39. error -> format_error(error)
  40. end
  41. end
  42. defp fetch_target_user(ap_id, opts) do
  43. case {opts[:force], User.get_or_fetch_by_ap_id(ap_id)} do
  44. {_, {:ok, %User{} = user}} -> {:ok, user}
  45. {true, _} -> {:ok, %User{ap_id: ap_id}}
  46. {_, error} -> error
  47. end
  48. end
  49. @spec publish(any()) :: {:ok, Activity.t()} | {:error, any()}
  50. def publish(%Activity{data: %{"type" => "Create"}} = activity) do
  51. with %User{} = user <- get_actor(),
  52. true <- Visibility.public?(activity) do
  53. CommonAPI.repeat(activity.id, user)
  54. else
  55. error -> format_error(error)
  56. end
  57. end
  58. def publish(_), do: {:error, "Not implemented"}
  59. @spec list() :: {:ok, [%{actor: String.t(), followed_back: boolean()}]} | {:error, any()}
  60. def list do
  61. with %User{} = user <- get_actor() do
  62. accepted =
  63. user
  64. |> following()
  65. |> Enum.map(fn actor -> %{actor: actor, followed_back: true} end)
  66. without_accept =
  67. user
  68. |> Pleroma.Activity.following_requests_for_actor()
  69. |> Enum.map(fn activity -> %{actor: activity.data["object"], followed_back: false} end)
  70. |> Enum.uniq()
  71. {:ok, accepted ++ without_accept}
  72. else
  73. error -> format_error(error)
  74. end
  75. end
  76. @spec following() :: [String.t()]
  77. def following do
  78. get_actor()
  79. |> following()
  80. end
  81. defp following(user) do
  82. user
  83. |> User.following_ap_ids()
  84. |> Enum.uniq()
  85. end
  86. defp format_error({:error, error}), do: format_error(error)
  87. defp format_error(error) do
  88. Logger.error("error: #{inspect(error)}")
  89. {:error, error}
  90. end
  91. end