This commit is contained in:
Moon Man 2024-09-03 16:17:16 +00:00
parent 185b480b12
commit 347083cc5a
5 changed files with 77 additions and 9 deletions

View File

@ -23,12 +23,12 @@ defmodule Vonbraun.ActivityPub.Handler.Accept do
{:ok, actor_id}
else
_ ->
{:error, :notfound}
{:error, :not_found}
end
end
def extract_follow_object_actor(_) do
{:error, :notfound}
{:error, :not_found}
end
# Lots of kinds of things can be accepted but for right now only follows.

View File

@ -51,12 +51,16 @@ defmodule Vonbraun.ActivityPub.Object do
}
end
def my_follow_activity_id(to_follow_id) when is_binary(to_follow_id),
do:
"https://#{Application.fetch_env!(:vonbraun, :domain)}/id/follow:#{URI.encode(to_follow_id)}"
@spec create_actor_activity_id(String.t(), String.t()) :: String.t()
def create_actor_activity_id(actor_id, verb) when is_binary(actor_id) and is_binary(verb) do
"https://#{Application.fetch_env!(:vonbraun, :domain)}/id/#{URI.encode(verb)}:#{URI.encode(actor_id)}"
end
def follow_activity(to_follow_id) when is_binary(to_follow_id),
do: activity("Follow", my_follow_activity_id(to_follow_id), to_follow_id, to: to_follow_id)
do:
activity("Follow", create_actor_activity_id(to_follow_id, "follow"), to_follow_id,
to: to_follow_id
)
def accept_follow_activity(followee_id, activity_id, type \\ :accept)
when is_binary(followee_id) and is_binary(activity_id) and type in [:accept, :reject] do
@ -74,7 +78,7 @@ defmodule Vonbraun.ActivityPub.Object do
}
accept_activity_id =
"https://#{Application.fetch_env!(:vonbraun, :domain)}/id/follow-reply:#{URI.encode(followee_id)}"
create_actor_activity_id(followee_id, "follow-reply")
activity(activity_type, accept_activity_id, object, to: followee_id)
end

View File

@ -86,6 +86,6 @@ defmodule Vonbraun.ActivityPubReq do
end
def extract_actor_inbox(%{}) do
{:error, :notfound}
{:error, :not_found}
end
end

View File

@ -58,7 +58,49 @@ defmodule Vonbraun.Control do
end
end
def unfollow(id) when is_binary(id) do
def unfollow(followee_actor_id) when is_binary(followee_actor_id) do
with {:actor, {:ok, actor}} <- {:actor, ActivityPubReq.get_cached_actor(followee_actor_id)},
{:inbox, {:ok, raw_inbox}} <- {:inbox, ActivityPubReq.extract_actor_inbox(actor)},
{:parse_inbox, inbox = %URI{}} <- {:parse_inbox, URI.parse(raw_inbox)},
{:state, {:ok, %Actor{}}} <-
{:state, Actor.remove_followee(followee_actor_id)} do
object = Object.follow_activity(followee_actor_id)
activity_id = Object.create_actor_activity_id(followee_actor_id, "unfollow")
activity = Object.activity("Undo", activity_id, object)
payload = Jason.encode!(activity)
case ActivityPubReq.post(inbox, payload) do
{:ok, %{:status => status, :body => body}} when status >= 200 and status <= 299 ->
Logger.debug(inspect(body))
Logger.info("Unfollow request sent successfully, now it's up to the remote server.")
:ok
{:ok, %{:status => status, :body => body}} ->
Logger.debug(inspect(body))
Logger.warning("Got a status of: #{status}, probably not good.")
{:error, {:status, status}}
{:error, error} ->
Logger.error("Failed to send unfollow request: #{inspect(error)}")
{:error, {:post, error}}
end
else
{:inbox, {:error, _}} ->
Logger.warning("Actor had an invalid inbox.")
{:error, :invalid_inbox}
{:actor, {:error, error}} ->
Logger.warning("Failed to query remote actor: #{inspect(error)}")
{:error, {:actor, error}}
{:state, error = {:error, :not_following}} ->
Logger.warning("Not following user.")
error
{:state, {:error, error}} ->
Logger.error("Unexpected error: #{inspect(error)}")
{:error, error}
end
end
def post_note(content, public?, to \\ [])

View File

@ -181,6 +181,28 @@ defmodule Vonbraun.Ecto.Schema.Actor do
end
end
@spec remove_followee(String.t()) :: {:ok, __MODULE__.t()} | {:error, any()}
@doc """
Mark a remote actor as no longer being followed.
"""
def remove_followee(id) when is_binary(id) do
case Repo.get(__MODULE__, id) do
nil ->
{:error, :not_following}
actor = %__MODULE__{:following_state => following_state}
when following_state in ["accepted", "pending"] ->
now = DateTime.now!("Etc/UTC")
changeset(actor, %{following_state: nil, following_ts: now})
|> Repo.update()
%__MODULE__{:following_state => following_state}
when following_state == "rejected" or is_nil(following_state) ->
{:error, :not_following}
end
end
@spec get_my_followers() :: list(String.t())
def get_my_followers() do
query =