From 7548cbe40cfeddb8fa85894a2e5d07970920d5c4 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 30 Sep 2019 17:02:03 -0400 Subject: [PATCH] Add activity getting/fetching --- lib/clacks/activity.ex | 48 +++++++++++++++++++++++++++++++ lib/clacks/activitypub.ex | 1 - lib/clacks/activitypub/fetcher.ex | 5 ++++ lib/clacks/actor.ex | 6 ++-- lib/clacks/object.ex | 12 ++++---- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/lib/clacks/activity.ex b/lib/clacks/activity.ex index 6128e3a..105ded7 100644 --- a/lib/clacks/activity.ex +++ b/lib/clacks/activity.ex @@ -1,6 +1,9 @@ defmodule Clacks.Activity do + require Logger use Ecto.Schema import Ecto.Changeset + alias Clacks.Repo + import Ecto.Query @type t() :: %__MODULE__{} @@ -21,4 +24,49 @@ defmodule Clacks.Activity do |> cast(attrs, [:data, :local, :actor]) |> validate_required([:data, :local, :actor]) end + + @spec get_by_ap_id(ap_id :: String.t(), force_refetch :: boolean()) :: t() | nil + def get_by_ap_id(ap_id, force_refetch \\ false) do + if force_refetch do + fetch(ap_id) + else + get_cached_by_ap_id(ap_id) || fetch(ap_id) + end + end + + @spec get_cached_by_ap_id(ap_id :: String.t()) :: t() | nil + def get_cached_by_ap_id(ap_id) do + Repo.one(from a in __MODULE__, where: fragment("?->>'id'", a.data) == ^ap_id) + end + + @spec fetch(ap_id :: String.t()) :: t() | nil + def fetch(ap_id) do + case Clacks.ActivityPub.Fetcher.fetch_activity(ap_id) do + nil -> + nil + + data -> + actor = data["actor"] || data["attributedTo"] + + existing = get_cached_by_ap_id(data["id"]) + + changeset = + changeset(existing || %__MODULE__{}, %{ + data: data, + local: false, + actor: actor + }) + + case Repo.insert_or_update(changeset) do + {:ok, activity} -> + _ = Clacks.Actor.get_by_ap_id(actor) + + activity + + {:error, changeset} -> + Logger.error("Couldn't store remote activity #{ap_id}: #{inspect(changeset)}") + nil + end + end + end end diff --git a/lib/clacks/activitypub.ex b/lib/clacks/activitypub.ex index bd83de6..16853fb 100644 --- a/lib/clacks/activitypub.ex +++ b/lib/clacks/activitypub.ex @@ -63,7 +63,6 @@ defmodule Clacks.ActivityPub do "@context" => @context, "type" => "Create", "object" => object, - # Mastodon doesn't include 'actor' in notes "actor" => object["actor"] || object["attributedTo"], "to" => object["to"], "cc" => object["cc"] diff --git a/lib/clacks/activitypub/fetcher.ex b/lib/clacks/activitypub/fetcher.ex index af61a29..0389b2b 100644 --- a/lib/clacks/activitypub/fetcher.ex +++ b/lib/clacks/activitypub/fetcher.ex @@ -28,6 +28,11 @@ defmodule Clacks.ActivityPub.Fetcher do end end + @spec fetch_activity(id :: String.t()) :: map() | nil + def fetch_activity(id) do + fetch_object(id) + end + @spec fetch(uri :: String.t()) :: map() | nil defp fetch(uri) do Logger.debug("Attempting to fetch AP object at #{uri}") diff --git a/lib/clacks/actor.ex b/lib/clacks/actor.ex index 99bf1d5..204176b 100644 --- a/lib/clacks/actor.ex +++ b/lib/clacks/actor.ex @@ -27,7 +27,7 @@ defmodule Clacks.Actor do end @spec get_by_ap_id(ap_id :: String.t(), force_refetch :: boolean()) :: t() | nil - def get_by_ap_id(ap_id, force_refetch \\ false) when is_binary(ap_id) do + def get_by_ap_id(ap_id, force_refetch \\ false) do if force_refetch do fetch(ap_id) else @@ -36,12 +36,12 @@ defmodule Clacks.Actor do end @spec get_cached_by_ap_id(ap_id :: String.t()) :: t() | nil - def get_cached_by_ap_id(ap_id) when is_binary(ap_id) do + def get_cached_by_ap_id(ap_id) do Repo.one(from a in __MODULE__, where: a.ap_id == ^ap_id) end @spec fetch(ap_id :: String.t()) :: t() | nil - def fetch(ap_id) when is_binary(ap_id) do + def fetch(ap_id) do case Clacks.ActivityPub.Fetcher.fetch_actor(ap_id) do nil -> nil diff --git a/lib/clacks/object.ex b/lib/clacks/object.ex index 2a1faa9..e110714 100644 --- a/lib/clacks/object.ex +++ b/lib/clacks/object.ex @@ -24,8 +24,7 @@ defmodule Clacks.Object do force_refetch :: boolean(), synthesize_create :: boolean() ) :: t() | nil - def get_by_ap_id(ap_id, force_refetch \\ false, synthesize_create \\ true) - when is_binary(ap_id) do + def get_by_ap_id(ap_id, force_refetch \\ false, synthesize_create \\ true) do if force_refetch do fetch(ap_id, synthesize_create) else @@ -34,12 +33,12 @@ defmodule Clacks.Object do end @spec get_cached_by_ap_id(ap_id :: String.t()) :: t() | nil - def get_cached_by_ap_id(ap_id) when is_binary(ap_id) do + def get_cached_by_ap_id(ap_id) do Repo.one(from o in __MODULE__, where: fragment("?->>'id'", o.data) == ^ap_id) end @spec fetch(ap_id :: String.t(), synthesize_create :: boolean()) :: t() | nil - def fetch(ap_id, synthesize_create \\ true) when is_binary(ap_id) do + def fetch(ap_id, synthesize_create \\ true) do case Clacks.ActivityPub.Fetcher.fetch_object(ap_id) do nil -> nil @@ -54,6 +53,9 @@ defmodule Clacks.Object do case Repo.insert_or_update(changeset) do {:ok, object} -> + actor = data["actor"] || data["attributedTo"] + _ = Clacks.Actor.get_by_ap_id(actor) + if synthesize_create do create = Clacks.ActivityPub.synthesized_create(data) @@ -61,7 +63,7 @@ defmodule Clacks.Object do Clacks.Activity.changeset(%Clacks.Activity{}, %{ data: create, local: false, - actor: data["actor"] + actor: actor }) {:ok, _create} = Repo.insert_or_update(changeset)