clacks/lib/clacks/inbox.ex

119 lines
3.6 KiB
Elixir
Raw Normal View History

2019-10-02 01:59:43 +00:00
defmodule Clacks.Inbox do
2019-10-02 13:47:04 +00:00
require Logger
alias Clacks.{Repo, Activity, Object, Actor, ActivityPub}
2019-10-02 01:59:43 +00:00
2020-04-26 22:55:44 +00:00
defp store_activity(%{"actor" => actor, "id" => ap_id} = activity, local \\ false)
when is_binary(actor) do
2019-10-02 01:59:43 +00:00
changeset =
2020-04-26 22:55:44 +00:00
Activity.changeset(Activity.get_cached_by_ap_id(ap_id) || %Activity{}, %{
2019-10-02 01:59:43 +00:00
data: activity,
2019-10-02 13:47:04 +00:00
local: local,
2019-10-02 01:59:43 +00:00
actor: actor
})
2020-04-26 22:55:44 +00:00
Repo.insert_or_update(changeset)
2019-10-02 13:47:04 +00:00
end
2019-10-02 14:28:06 +00:00
@spec handle(activity :: map()) :: :ok | {:error, reason :: any()}
def handle(%{"type" => "Create", "object" => object} = activity) do
2019-10-02 13:47:04 +00:00
changeset = Object.changeset(%Object{}, %{data: object})
2019-10-02 13:49:59 +00:00
case Repo.insert(changeset) do
{:error, changeset} ->
Logger.error("Couldn't store object: #{inspect(changeset)}")
{:error, "Couldn't store changeset"}
{:ok, _object} ->
case store_activity(activity) do
{:error, changeset} ->
Logger.error("Couldn't store Create activity: #{inspect(changeset)}")
{:error, "Couldn't store Create activity"}
{:ok, _activity} ->
:ok
end
end
2019-10-02 01:59:43 +00:00
end
2019-10-02 14:28:06 +00:00
def handle(%{"type" => "Follow", "object" => followed_id, "actor" => follower_id} = activity)
2019-10-02 01:59:43 +00:00
when is_binary(followed_id) do
followed = Actor.get_by_ap_id(followed_id)
2019-10-02 13:47:04 +00:00
follower = Actor.get_by_ap_id(follower_id)
store_activity(activity)
2020-04-26 20:25:48 +00:00
new_followers = [follower_id | followed.followers] |> Enum.uniq()
changeset = Actor.changeset(followed, %{followers: new_followers})
2019-10-02 13:47:04 +00:00
case Repo.update(changeset) do
{:error, changeset} ->
2020-04-26 22:55:44 +00:00
Logger.error("Couldn't store updated followers: #{inspect(changeset)}")
{:error, "Couldn't store updated followers"}
2019-10-02 13:47:04 +00:00
{: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
2019-10-02 01:59:43 +00:00
end
2019-10-02 14:28:06 +00:00
2020-04-26 22:55:44 +00:00
def handle(
%{
"type" => "Accept",
"actor" => followee_id,
"object" => %{"type" => "Follow", "id" => follow_activity_id, "actor" => follower_id}
} = activity
) do
followee = Actor.get_by_ap_id(followee_id)
follower = Actor.get_by_ap_id(follower_id)
store_activity(activity)
follow_activity = Activity.get_cached_by_ap_id(follow_activity_id)
changeset =
Activity.changeset(follow_activity, %{
data: %{follow_activity.data | "state" => "accepted"}
})
case Repo.update(changeset) do
{:error, changeset} ->
Logger.error("Couldn't store updated Follow activity: #{inspect(changeset)}")
{:error, "Couldn't store updated Follow activity"}
{:ok, _follow_activity} ->
new_followers = [follower_id | followee.followers] |> Enum.uniq()
changeset = Actor.changeset(followee, %{followers: new_followers})
case Repo.update(changeset) do
{:error, changeset} ->
Logger.error("Couldn't store updated followers: #{inspect(changeset)}")
{:error, "Couldn't store updated followers"}
{:ok, _followee} ->
:ok
end
end
end
2019-10-02 14:28:06 +00:00
# as a fallback, just store the activity
def handle(activity) do
case store_activity(activity) do
{:error, changeset} ->
Logger.error("Could not store activity: #{inspect(changeset)}")
{:error, "Could not store activity"}
{:ok, _activity} ->
:ok
end
end
2019-10-02 01:59:43 +00:00
end