implemented remote users unfollow me. untested.

This commit is contained in:
Moon Man 2024-09-03 11:39:54 +00:00
parent cd26855661
commit cb138abc08
3 changed files with 35 additions and 2 deletions

View File

@ -1,11 +1,35 @@
defmodule Vonbraun.ActivityPub.Handler.Undo do defmodule Vonbraun.ActivityPub.Handler.Undo do
@behaviour Vonbraun.ActivityPub.HandlerBehaviour @behaviour Vonbraun.ActivityPub.HandlerBehaviour
require Logger
alias Vonbraun.Ecto.Schema.Actor
alias Vonbraun.ActivityPub.Object
import Vonbraun.ActivityPub.Handler.Accept, only: [extract_follow_object_actor: 1]
@verb "Undo" @verb "Undo"
def type, do: @verb def type, do: @verb
# Lots of different kinds of things can be undone. # Lots of different kinds of things can be undone.
def handle(%{"type" => @verb, "actor" => actor_id, "object" => object = %{"type" => "Follow"}}) do
with {:actor, {:ok, follow_actor_id}} <- {:actor, extract_follow_object_actor(object)},
{:match, true} <- {:match, follow_actor_id == Object.my_id()},
{:asked, {:ok, %Actor{:following_state => nil}}} <-
{:asked, Actor.remove_follower(actor_id)} do
{:ok, :removed_follower}
else
{:asked, {:error, error}} ->
{:error, error}
{:match, false} ->
{:ok, :unauthorized}
{:actor, {:error, _error}} ->
{:ok, :unauthorized}
end
end
def handle(%{"type" => @verb}, %{}) do def handle(%{"type" => @verb}, %{}) do
{:ok, :unknown} {:ok, :unknown}
end end

View File

@ -1,5 +1,5 @@
defmodule Vonbraun.ActivityPub.HandlerBehaviour do defmodule Vonbraun.ActivityPub.HandlerBehaviour do
@callback type() :: String.t() @callback type() :: String.t()
@callback handle(activity :: map(), actor_object :: map()) :: @callback handle(activity :: map(), actor_object :: map()) ::
:ok | {:ok, atom()} | {:error, any()} {:ok, atom()} | {:error, any()}
end end

View File

@ -49,6 +49,11 @@ defmodule Vonbraun.Ecto.Schema.Actor do
end end
end end
@doc """
Mark a remote actor as following me, or pending follow, depending on if
approval of followers is enabled. Tries to intelligently ignore repeat and
spam follows.
"""
@spec maybe_add_follower(String.t()) :: {:ok, __MODULE__.t()} | {:error, Changeset.t()} @spec maybe_add_follower(String.t()) :: {:ok, __MODULE__.t()} | {:error, Changeset.t()}
def maybe_add_follower(id) when is_binary(id) do def maybe_add_follower(id) when is_binary(id) do
with {:actor, {:ok, actor = %{:follows_me_state => follows_me_state, :blocked => blocked?}}} <- with {:actor, {:ok, actor = %{:follows_me_state => follows_me_state, :blocked => blocked?}}} <-
@ -79,6 +84,9 @@ defmodule Vonbraun.Ecto.Schema.Actor do
end end
end end
@doc """
Mark a remote actor as no longer following me.
"""
@spec remove_follower(String.t()) :: {:ok, __MODULE__.t() | nil} | {:error, Changeset.t()} @spec remove_follower(String.t()) :: {:ok, __MODULE__.t() | nil} | {:error, Changeset.t()}
def remove_follower(id) when is_binary(id) do def remove_follower(id) when is_binary(id) do
case Repo.get(__MODULE__, id) do case Repo.get(__MODULE__, id) do
@ -86,10 +94,11 @@ defmodule Vonbraun.Ecto.Schema.Actor do
{:ok, nil} {:ok, nil}
actor = %{:follows_me_state => follows_me_state} -> actor = %{:follows_me_state => follows_me_state} ->
if follows_me_state == "accepted" do if follows_me_state in ["accepted", "pending"] do
changeset(actor, %{follows_me_state: nil, follows_me_ts: DateTime.now!("Etc/UTC")}) changeset(actor, %{follows_me_state: nil, follows_me_ts: DateTime.now!("Etc/UTC")})
|> Repo.update() |> Repo.update()
else else
# nil or rejected already.
{:ok, actor} {:ok, actor}
end end
end end