Add unfollowing remote users
This commit is contained in:
parent
e194f0fc07
commit
2636b5eabf
|
@ -132,6 +132,19 @@ defmodule Clacks.ActivityPub do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec undo_follow(actor :: String.t(), follow_activity :: map()) :: map()
|
||||||
|
def undo_follow(actor, %{"object" => followee} = follow_activity) do
|
||||||
|
%{
|
||||||
|
"@context" => @context,
|
||||||
|
"type" => "Undo",
|
||||||
|
"id" => activity_id(Ecto.UUID.generate()),
|
||||||
|
"actor" => actor,
|
||||||
|
"object" => follow_activity,
|
||||||
|
"to" => [followee],
|
||||||
|
"cc" => []
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
@spec object_id(id :: String.t()) :: String.t()
|
@spec object_id(id :: String.t()) :: String.t()
|
||||||
def object_id(id) do
|
def object_id(id) do
|
||||||
url = Application.get_env(:clacks, ClacksWeb.Endpoint)[:url]
|
url = Application.get_env(:clacks, ClacksWeb.Endpoint)[:url]
|
||||||
|
|
|
@ -67,7 +67,7 @@ defmodule Clacks.ActivityPub.Federator do
|
||||||
@public in activity["to"] or @public in activity["cc"] ->
|
@public in activity["to"] or @public in activity["cc"] ->
|
||||||
shared_inbox_for(actor)
|
shared_inbox_for(actor)
|
||||||
|
|
||||||
actor.data["followers"] in activity["to"] or actor.data["followers"] in activity["cc"] ->
|
actor["followers"] in activity["to"] or actor["followers"] in activity["cc"] ->
|
||||||
shared_inbox_for(actor)
|
shared_inbox_for(actor)
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
|
|
|
@ -73,7 +73,6 @@ defmodule Clacks.Inbox do
|
||||||
} = activity
|
} = activity
|
||||||
) do
|
) do
|
||||||
followee = Actor.get_by_ap_id(followee_id)
|
followee = Actor.get_by_ap_id(followee_id)
|
||||||
follower = Actor.get_by_ap_id(follower_id)
|
|
||||||
|
|
||||||
store_activity(activity)
|
store_activity(activity)
|
||||||
|
|
||||||
|
@ -106,6 +105,8 @@ defmodule Clacks.Inbox do
|
||||||
|
|
||||||
# as a fallback, just store the activity
|
# as a fallback, just store the activity
|
||||||
def handle(activity) do
|
def handle(activity) do
|
||||||
|
Logger.debug("Unhandled activity: #{inspect(activity)}")
|
||||||
|
|
||||||
case store_activity(activity) do
|
case store_activity(activity) do
|
||||||
{:error, changeset} ->
|
{:error, changeset} ->
|
||||||
Logger.error("Could not store activity: #{inspect(changeset)}")
|
Logger.error("Could not store activity: #{inspect(changeset)}")
|
||||||
|
|
|
@ -54,7 +54,7 @@ defmodule Clacks.Object do
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec fetch(ap_id :: String.t(), synthesize_create :: boolean(), return :: :object | :activity) ::
|
@spec fetch(ap_id :: String.t(), synthesize_create :: boolean(), return :: :object | :activity) ::
|
||||||
t() | nil
|
t() | Activity.t() | nil
|
||||||
def fetch(ap_id, synthesize_create \\ true, return \\ :object) do
|
def fetch(ap_id, synthesize_create \\ true, return \\ :object) do
|
||||||
case Clacks.ActivityPub.Fetcher.fetch_object(ap_id) do
|
case Clacks.ActivityPub.Fetcher.fetch_object(ap_id) do
|
||||||
nil ->
|
nil ->
|
||||||
|
|
|
@ -174,6 +174,40 @@ defmodule ClacksWeb.FrontendController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unfollow(conn, %{"id" => id}) do
|
||||||
|
current_user = conn.assigns[:user] |> Repo.preload(:actor)
|
||||||
|
|
||||||
|
case Repo.get(Actor, id) do
|
||||||
|
nil ->
|
||||||
|
resp(conn, 404, "Not Found")
|
||||||
|
|
||||||
|
followee ->
|
||||||
|
unless current_user.actor.ap_id in followee.followers do
|
||||||
|
redirect(conn, to: ClacksWeb.FrontendView.local_actor_link(followee))
|
||||||
|
else
|
||||||
|
new_followers = List.delete(followee.followers, current_user.actor.ap_id)
|
||||||
|
changeset = Actor.changeset(followee, %{followers: new_followers})
|
||||||
|
{:ok, followee} = Repo.update(changeset)
|
||||||
|
|
||||||
|
follow_activity = follow_activity(current_user.actor, followee)
|
||||||
|
|
||||||
|
changeset =
|
||||||
|
Activity.changeset(follow_activity, %{
|
||||||
|
data: %{follow_activity.data | "state" => "unfollowed"}
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, follow_activity} = Repo.update(changeset)
|
||||||
|
|
||||||
|
undo_follow = ActivityPub.undo_follow(current_user.actor.ap_id, follow_activity.data)
|
||||||
|
ActivityPub.Helper.save_and_federate(undo_follow, current_user.actor)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Unfollowed")
|
||||||
|
|> redirect(to: ClacksWeb.FrontendView.local_actor_link(followee))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def search(conn, %{"q" => q}) when is_binary(q) do
|
def search(conn, %{"q" => q}) when is_binary(q) do
|
||||||
current_user = conn.assigns[:user]
|
current_user = conn.assigns[:user]
|
||||||
|
|
||||||
|
@ -258,23 +292,31 @@ defmodule ClacksWeb.FrontendController do
|
||||||
ActivityPub.note(current_user.actor.ap_id, content)
|
ActivityPub.note(current_user.actor.ap_id, content)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec following_state(follower :: Actor.t(), followee :: Actor.t()) :: boolean()
|
@spec follow_activity(follower :: Actor.t(), followee :: Actor.t()) :: map()
|
||||||
defp following_state(follower, followee) do
|
def follow_activity(follower, followee) do
|
||||||
|
# todo: get latest
|
||||||
query =
|
query =
|
||||||
Activity
|
Activity
|
||||||
|> where([a], fragment("?->>'type'", a.data) == "Follow")
|
|> where([a], fragment("?->>'type'", a.data) == "Follow")
|
||||||
|> where([a], fragment("?->>'actor'", a.data) == ^follower.ap_id)
|
|> where([a], fragment("?->>'actor'", a.data) == ^follower.ap_id)
|
||||||
|> where([a], fragment("?->>'object'", a.data) == ^followee.ap_id)
|
|> where([a], fragment("?->>'object'", a.data) == ^followee.ap_id)
|
||||||
|
|> order_by(desc: :inserted_at)
|
||||||
|
|> limit(1)
|
||||||
|
|
||||||
case Repo.one(query) do
|
Repo.one(query)
|
||||||
nil ->
|
end
|
||||||
:not_following
|
|
||||||
|
|
||||||
|
@spec following_state(follower :: Actor.t(), followee :: Actor.t()) :: boolean()
|
||||||
|
defp following_state(follower, followee) do
|
||||||
|
case follow_activity(follower, followee) do
|
||||||
%Activity{data: %{"state" => "pending"}} ->
|
%Activity{data: %{"state" => "pending"}} ->
|
||||||
:pending
|
:pending
|
||||||
|
|
||||||
%Activity{data: %{"state" => "accepted"}} ->
|
%Activity{data: %{"state" => "accepted"}} ->
|
||||||
:following
|
:following
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:not_following
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue