Handle follow activities

This commit is contained in:
Shadowfacts 2019-10-02 09:47:04 -04:00
parent 0d6fd68fb3
commit 2316c5d41d
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
3 changed files with 63 additions and 13 deletions

View File

@ -95,6 +95,17 @@ defmodule Clacks.ActivityPub do
} }
end end
@spec accept_follow(follow_activity :: map()) :: map()
def accept_follow(%{"type" => "Follow", "object" => followed} = follow_activity) do
%{
"@context" => @context,
"type" => "Accept",
"id" => activity_id(Ecto.UUID.generate()),
"actor" => followed,
"object" => follow_activity
}
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]

View File

@ -1,24 +1,53 @@
defmodule Clacks.Inbox do defmodule Clacks.Inbox do
alias Clacks.{Repo, Activity, Object, Actor} require Logger
alias Clacks.{Repo, Activity, Object, Actor, ActivityPub}
def handle_create(%{"type" => "Create", "object" => object, "actor" => actor} = activity) do
changeset = Object.changeset(%Object{}, %{data: object})
{:ok, _object} = Repo.insert(changeset)
defp store_activity(%{"actor" => actor} = activity, local \\ false) when is_binary(actor) do
changeset = changeset =
Activity.changeset(%Activity{}, %{ Activity.changeset(%Activity{}, %{
data: activity, data: activity,
local: false, local: local,
actor: actor actor: actor
}) })
{:ok, _activity} = Repo.insert(changeset) Repo.insert(changeset)
end end
def handle_follow(%{"type" => "Follow", "object" => followed_id, "actor" => follower}) def handle_create(%{"type" => "Create", "object" => object} = activity) do
changeset = Object.changeset(%Object{}, %{data: object})
{:ok, _object} = Repo.insert(changeset)
{:ok, _activity} = store_activity(activity)
end
@spec handle_follow(activity :: map()) :: :ok | {:error, reason :: any()}
def handle_follow(
%{"type" => "Follow", "object" => followed_id, "actor" => follower_id} = activity
)
when is_binary(followed_id) do when is_binary(followed_id) do
followed = Actor.get_by_ap_id(followed_id) followed = Actor.get_by_ap_id(followed_id)
changeset = Actor.changeset(followed, %{followers: [follower | followed.followers]}) follower = Actor.get_by_ap_id(follower_id)
{:ok, _followed} = Repo.update(changeset)
store_activity(activity)
changeset = Actor.changeset(followed, %{followers: [follower_id | followed.followers]})
case Repo.update(changeset) do
{:error, changeset} ->
Logger.error("Couldn't store Follow activity: #{inspect(changeset)}")
{:error, "Couldn't store Follow activity"}
{:ok, _followed} ->
accept = ActivityPub.accept_follow(activity)
case store_activity(accept, true) do
{:error, changeset} ->
Logger.error("Couldn't store Accept activity: #{inspect(changeset)}")
{:error, "Couldn't store Accept activity"}
{:ok, _accept} ->
ActivityPub.Federator.federate(accept, follower.data["inbox"])
end
end
end end
end end

View File

@ -1,4 +1,5 @@
defmodule ClacksWeb.InboxController do defmodule ClacksWeb.InboxController do
require Logger
use ClacksWeb, :controller use ClacksWeb, :controller
alias Clacks.Inbox alias Clacks.Inbox
@ -18,13 +19,22 @@ defmodule ClacksWeb.InboxController do
conn conn
|> put_status(200) |> put_status(200)
|> json(%{})
end end
def handle(conn, %{"type" => "Follow", "object" => object} = activity) when is_binary(object) do def handle(conn, %{"type" => "Follow", "object" => object} = activity) when is_binary(object) do
Inbox.handle_follow(activity) case Inbox.handle_follow(activity) do
:ok ->
conn conn
|> put_status(200) |> put_status(200)
{:error, reason} ->
Logger.error("Could not handle incoming follow: #{inspect(reason)}")
conn
|> put_status(500)
end
|> json(%{})
end end
# def handle(conn, _) do # def handle(conn, _) do