2019-09-28 22:30:55 +00:00
|
|
|
defmodule Clacks.Object do
|
2019-09-30 20:52:50 +00:00
|
|
|
require Logger
|
2019-09-28 22:30:55 +00:00
|
|
|
use Ecto.Schema
|
2019-09-29 01:57:11 +00:00
|
|
|
import Ecto.Changeset
|
2019-09-30 20:52:50 +00:00
|
|
|
alias Clacks.Repo
|
|
|
|
import Ecto.Query
|
2019-09-28 22:30:55 +00:00
|
|
|
|
|
|
|
@type t() :: %__MODULE__{}
|
|
|
|
|
|
|
|
schema "objects" do
|
|
|
|
field :data, :map
|
|
|
|
|
|
|
|
timestamps()
|
|
|
|
end
|
2019-09-29 01:57:11 +00:00
|
|
|
|
|
|
|
def changeset(%__MODULE__{} = schema, attrs) do
|
|
|
|
schema
|
|
|
|
|> cast(attrs, [:data])
|
|
|
|
|> validate_required([:data])
|
|
|
|
end
|
2019-09-30 20:52:50 +00:00
|
|
|
|
|
|
|
@spec get_by_ap_id(
|
|
|
|
ap_id :: String.t(),
|
|
|
|
force_refetch :: boolean(),
|
|
|
|
synthesize_create :: boolean()
|
|
|
|
) :: t() | nil
|
2019-09-30 21:02:03 +00:00
|
|
|
def get_by_ap_id(ap_id, force_refetch \\ false, synthesize_create \\ true) do
|
2019-09-30 20:52:50 +00:00
|
|
|
if force_refetch do
|
|
|
|
fetch(ap_id, synthesize_create)
|
|
|
|
else
|
|
|
|
get_cached_by_ap_id(ap_id) || fetch(ap_id, synthesize_create)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
@spec get_cached_by_ap_id(ap_id :: String.t()) :: t() | nil
|
2019-09-30 21:02:03 +00:00
|
|
|
def get_cached_by_ap_id(ap_id) do
|
2019-09-30 20:52:50 +00:00
|
|
|
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
|
2019-09-30 21:02:03 +00:00
|
|
|
def fetch(ap_id, synthesize_create \\ true) do
|
2019-09-30 20:52:50 +00:00
|
|
|
case Clacks.ActivityPub.Fetcher.fetch_object(ap_id) do
|
|
|
|
nil ->
|
|
|
|
nil
|
|
|
|
|
|
|
|
data ->
|
|
|
|
existing = get_cached_by_ap_id(data["id"])
|
|
|
|
|
|
|
|
changeset =
|
|
|
|
changeset(existing || %__MODULE__{}, %{
|
|
|
|
data: data
|
|
|
|
})
|
|
|
|
|
|
|
|
case Repo.insert_or_update(changeset) do
|
|
|
|
{:ok, object} ->
|
2019-09-30 21:02:03 +00:00
|
|
|
actor = data["actor"] || data["attributedTo"]
|
|
|
|
_ = Clacks.Actor.get_by_ap_id(actor)
|
|
|
|
|
2019-09-30 20:52:50 +00:00
|
|
|
if synthesize_create do
|
|
|
|
create = Clacks.ActivityPub.synthesized_create(data)
|
|
|
|
|
|
|
|
changeset =
|
|
|
|
Clacks.Activity.changeset(%Clacks.Activity{}, %{
|
|
|
|
data: create,
|
|
|
|
local: false,
|
2019-09-30 21:02:03 +00:00
|
|
|
actor: actor
|
2019-09-30 20:52:50 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
{:ok, _create} = Repo.insert_or_update(changeset)
|
|
|
|
end
|
|
|
|
|
|
|
|
object
|
|
|
|
|
|
|
|
{:error, changeset} ->
|
|
|
|
Logger.error("Couldn't store remote object #{ap_id}: #{inspect(changeset)}")
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-09-28 22:30:55 +00:00
|
|
|
end
|