summaryrefslogtreecommitdiff
path: root/lib/pleroma/web/activity_pub/utils.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web/activity_pub/utils.ex')
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex139
1 files changed, 105 insertions, 34 deletions
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index cda106283..7b2bf8fa7 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -5,8 +5,28 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Ecto.{Changeset, UUID}
import Ecto.Query
+ def make_json_ld_header do
+ %{
+ "@context" => [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ %{
+ "manuallyApprovesFollowers" => "as:manuallyApprovesFollowers",
+ "sensitive" => "as:sensitive",
+ "Hashtag" => "as:Hashtag",
+ "ostatus" => "http://ostatus.org#",
+ "atomUri" => "ostatus:atomUri",
+ "inReplyToAtomUri" => "ostatus:inReplyToAtomUri",
+ "conversation" => "ostatus:conversation",
+ "toot" => "http://joinmastodon.org/ns#",
+ "Emoji" => "toot:Emoji"
+ }
+ ]
+ }
+ end
+
def make_date do
- DateTime.utc_now() |> DateTime.to_iso8601
+ DateTime.utc_now() |> DateTime.to_iso8601()
end
def generate_activity_id do
@@ -18,25 +38,43 @@ defmodule Pleroma.Web.ActivityPub.Utils do
end
def generate_object_id do
- Helpers.o_status_url(Endpoint, :object, UUID.generate)
+ Helpers.o_status_url(Endpoint, :object, UUID.generate())
end
def generate_id(type) do
- "#{Web.base_url()}/#{type}/#{UUID.generate}"
+ "#{Web.base_url()}/#{type}/#{UUID.generate()}"
+ end
+
+ def create_context(context) do
+ context = context || generate_id("contexts")
+ changeset = Object.context_mapping(context)
+
+ case Repo.insert(changeset) do
+ {:ok, object} ->
+ object
+
+ # This should be solved by an upsert, but it seems ecto
+ # has problems accessing the constraint inside the jsonb.
+ {:error, _} ->
+ Object.get_cached_by_ap_id(context)
+ end
end
@doc """
Enqueues an activity for federation if it's local
"""
def maybe_federate(%Activity{local: true} = activity) do
- priority = case activity.data["type"] do
- "Delete" -> 10
- "Create" -> 1
- _ -> 5
- end
+ priority =
+ case activity.data["type"] do
+ "Delete" -> 10
+ "Create" -> 1
+ _ -> 5
+ end
+
Pleroma.Web.Federator.enqueue(:publish, activity, priority)
:ok
end
+
def maybe_federate(_), do: :ok
@doc """
@@ -44,12 +82,17 @@ defmodule Pleroma.Web.ActivityPub.Utils do
also adds it to an included object
"""
def lazy_put_activity_defaults(map) do
- map = map
- |> Map.put_new_lazy("id", &generate_activity_id/0)
- |> Map.put_new_lazy("published", &make_date/0)
+ %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
+
+ map =
+ map
+ |> Map.put_new_lazy("id", &generate_activity_id/0)
+ |> Map.put_new_lazy("published", &make_date/0)
+ |> Map.put_new("context", context)
+ |> Map.put_new("context_id", context_id)
if is_map(map["object"]) do
- object = lazy_put_object_defaults(map["object"])
+ object = lazy_put_object_defaults(map["object"], map)
%{map | "object" => object}
else
map
@@ -59,20 +102,24 @@ defmodule Pleroma.Web.ActivityPub.Utils do
@doc """
Adds an id and published date if they aren't there.
"""
- def lazy_put_object_defaults(map) do
+ def lazy_put_object_defaults(map, activity \\ %{}) do
map
|> Map.put_new_lazy("id", &generate_object_id/0)
|> Map.put_new_lazy("published", &make_date/0)
+ |> Map.put_new("context", activity["context"])
+ |> Map.put_new("context_id", activity["context_id"])
end
@doc """
Inserts a full object if it is contained in an activity.
"""
- def insert_full_object(%{"object" => %{"type" => type} = object_data}) when is_map(object_data) and type in ["Note"] do
+ def insert_full_object(%{"object" => %{"type" => type} = object_data})
+ when is_map(object_data) and type in ["Note"] do
with {:ok, _} <- Object.create(object_data) do
:ok
end
end
+
def insert_full_object(_), do: :ok
def update_object_in_activities(%{data: %{"id" => id}} = object) do
@@ -81,7 +128,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do
# Alternatively, just don't do this and fetch the current object each time. Most
# could probably be taken from cache.
relevant_activities = Activity.all_by_object_ap_id(id)
- Enum.map(relevant_activities, fn (activity) ->
+
+ Enum.map(relevant_activities, fn activity ->
new_activity_data = activity.data |> Map.put("object", object.data)
changeset = Changeset.change(activity, data: new_activity_data)
Repo.update(changeset)
@@ -94,11 +142,20 @@ defmodule Pleroma.Web.ActivityPub.Utils do
Returns an existing like if a user already liked an object
"""
def get_existing_like(actor, %{data: %{"id" => id}}) do
- query = from activity in Activity,
- where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
- # this is to use the index
- where: fragment("coalesce((?)->'object'->>'id', (?)->>'object') = ?", activity.data, activity.data, ^id),
- where: fragment("(?)->>'type' = 'Like'", activity.data)
+ query =
+ from(
+ activity in Activity,
+ where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
+ # this is to use the index
+ where:
+ fragment(
+ "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
+ activity.data,
+ activity.data,
+ ^id
+ ),
+ where: fragment("(?)->>'type' = 'Like'", activity.data)
+ )
Repo.one(query)
end
@@ -117,10 +174,13 @@ defmodule Pleroma.Web.ActivityPub.Utils do
end
def update_element_in_object(property, element, object) do
- with new_data <- object.data |> Map.put("#{property}_count", length(element)) |> Map.put("#{property}s", element),
+ with new_data <-
+ object.data
+ |> Map.put("#{property}_count", length(element))
+ |> Map.put("#{property}s", element),
changeset <- Changeset.change(object, data: new_data),
{:ok, object} <- Repo.update(changeset),
- _ <- update_object_in_activities(object) do
+ _ <- update_object_in_activities(object) do
{:ok, object}
end
end
@@ -130,7 +190,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
end
def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
- with likes <- [actor | (object.data["likes"] || [])] |> Enum.uniq do
+ with likes <- [actor | object.data["likes"] || []] |> Enum.uniq() do
update_likes_in_object(likes, object)
end
end
@@ -158,13 +218,20 @@ defmodule Pleroma.Web.ActivityPub.Utils do
if activity_id, do: Map.put(data, "id", activity_id), else: data
end
- def fetch_latest_follow(%User{ap_id: follower_id},
- %User{ap_id: followed_id}) do
- query = from activity in Activity,
- where: fragment("? @> ?", activity.data, ^%{type: "Follow", actor: follower_id,
- object: followed_id}),
- order_by: [desc: :id],
- limit: 1
+ def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do
+ query =
+ from(
+ activity in Activity,
+ where:
+ fragment(
+ "? @> ?",
+ activity.data,
+ ^%{type: "Follow", actor: follower_id, object: followed_id}
+ ),
+ order_by: [desc: :id],
+ limit: 1
+ )
+
Repo.one(query)
end
@@ -173,7 +240,11 @@ defmodule Pleroma.Web.ActivityPub.Utils do
@doc """
Make announce activity data for the given actor and object
"""
- def make_announce_data(%User{ap_id: ap_id} = user, %Object{data: %{"id" => id}} = object, activity_id) do
+ def make_announce_data(
+ %User{ap_id: ap_id} = user,
+ %Object{data: %{"id" => id}} = object,
+ activity_id
+ ) do
data = %{
"type" => "Announce",
"actor" => ap_id,
@@ -187,7 +258,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
end
def add_announce_to_object(%Activity{data: %{"actor" => actor}}, object) do
- with announcements <- [actor | (object.data["announcements"] || [])] |> Enum.uniq do
+ with announcements <- [actor | object.data["announcements"] || []] |> Enum.uniq() do
update_element_in_object("announcement", announcements, object)
end
end
@@ -203,14 +274,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
}
end
-
#### Create-related helpers
def make_create_data(params, additional) do
published = params.published || make_date()
+
%{
"type" => "Create",
- "to" => params.to |> Enum.uniq,
+ "to" => params.to |> Enum.uniq(),
"actor" => params.actor.ap_id,
"object" => params.object,
"published" => published,