1 defmodule Pleroma.Web.ActivityPub.Builder do
3 This module builds the objects. Meant to be used for creating local objects.
5 This module encodes our addressing policies and general shape of our objects.
11 alias Pleroma.Web.ActivityPub.Relay
12 alias Pleroma.Web.ActivityPub.Utils
13 alias Pleroma.Web.ActivityPub.Visibility
15 require Pleroma.Constants
17 @spec emoji_react(User.t(), Object.t(), String.t()) :: {:ok, map(), keyword()}
18 def emoji_react(actor, object, emoji) do
19 with {:ok, data, meta} <- object_action(actor, object) do
22 |> Map.put("content", emoji)
23 |> Map.put("type", "EmojiReact")
29 @spec undo(User.t(), Activity.t()) :: {:ok, map(), keyword()}
30 def undo(actor, object) do
33 "id" => Utils.generate_activity_id(),
34 "actor" => actor.ap_id,
36 "object" => object.data["id"],
37 "to" => object.data["to"] || [],
38 "cc" => object.data["cc"] || []
42 @spec delete(User.t(), String.t()) :: {:ok, map(), keyword()}
43 def delete(actor, object_id) do
44 object = Object.normalize(object_id, false)
46 user = !object && User.get_cached_by_ap_id(object_id)
49 case {object, user} do
51 # We are deleting an object, address everyone who was originally mentioned
52 (object.data["to"] || []) ++ (object.data["cc"] || [])
54 {_, %User{follower_address: follower_address}} ->
55 # We are deleting a user, address the followers of that user
61 "id" => Utils.generate_activity_id(),
62 "actor" => actor.ap_id,
63 "object" => object_id,
69 def create(actor, object, recipients) do
72 "id" => Utils.generate_activity_id(),
73 "actor" => actor.ap_id,
77 "published" => DateTime.utc_now() |> DateTime.to_iso8601()
81 def chat_message(actor, recipient, content, opts \\ []) do
83 "id" => Utils.generate_object_id(),
84 "actor" => actor.ap_id,
85 "type" => "ChatMessage",
88 "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
89 "emoji" => Emoji.Formatter.get_emoji_map(content)
92 case opts[:attachment] do
93 %Object{data: attachment_data} ->
96 Map.put(basic, "attachment", attachment_data),
105 @spec tombstone(String.t(), String.t()) :: {:ok, map(), keyword()}
106 def tombstone(actor, id) do
111 "type" => "Tombstone"
115 @spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}
116 def like(actor, object) do
117 with {:ok, data, meta} <- object_action(actor, object) do
120 |> Map.put("type", "Like")
126 @spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()}
127 def announce(actor, object, options \\ []) do
128 public? = Keyword.get(options, :public, false)
132 actor.ap_id == Relay.relay_ap_id() ->
133 [actor.follower_address]
136 [actor.follower_address, object.data["actor"], Pleroma.Constants.as_public()]
139 [actor.follower_address, object.data["actor"]]
144 "id" => Utils.generate_activity_id(),
145 "actor" => actor.ap_id,
146 "object" => object.data["id"],
148 "context" => object.data["context"],
149 "type" => "Announce",
150 "published" => Utils.make_date()
154 @spec object_action(User.t(), Object.t()) :: {:ok, map(), keyword()}
155 defp object_action(actor, object) do
156 object_actor = User.get_cached_by_ap_id(object.data["actor"])
158 # Address the actor of the object, and our actor's follower collection if the post is public.
160 if Visibility.is_public?(object) do
161 [actor.follower_address, object.data["actor"]]
163 [object.data["actor"]]
166 # CC everyone who's been addressed in the object, except ourself and the object actor's
167 # follower collection
169 (object.data["to"] ++ (object.data["cc"] || []))
170 |> List.delete(actor.ap_id)
171 |> List.delete(object_actor.follower_address)
175 "id" => Utils.generate_activity_id(),
176 "actor" => actor.ap_id,
177 "object" => object.data["id"],
180 "context" => object.data["context"]