Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into remake-remodel-dms
[akkoma] / lib / pleroma / web / activity_pub / builder.ex
1 defmodule Pleroma.Web.ActivityPub.Builder do
2 @moduledoc """
3 This module builds the objects. Meant to be used for creating local objects.
4
5 This module encodes our addressing policies and general shape of our objects.
6 """
7
8 alias Pleroma.Emoji
9 alias Pleroma.Object
10 alias Pleroma.User
11 alias Pleroma.Web.ActivityPub.Utils
12 alias Pleroma.Web.ActivityPub.Visibility
13
14 @spec delete(User.t(), String.t()) :: {:ok, map(), keyword()}
15 def delete(actor, object_id) do
16 object = Object.normalize(object_id, false)
17
18 user = !object && User.get_cached_by_ap_id(object_id)
19
20 to =
21 case {object, user} do
22 {%Object{}, _} ->
23 # We are deleting an object, address everyone who was originally mentioned
24 (object.data["to"] || []) ++ (object.data["cc"] || [])
25
26 {_, %User{follower_address: follower_address}} ->
27 # We are deleting a user, address the followers of that user
28 [follower_address]
29 end
30
31 {:ok,
32 %{
33 "id" => Utils.generate_activity_id(),
34 "actor" => actor.ap_id,
35 "object" => object_id,
36 "to" => to,
37 "type" => "Delete"
38 }, []}
39 end
40
41 def create(actor, object, recipients) do
42 {:ok,
43 %{
44 "id" => Utils.generate_activity_id(),
45 "actor" => actor.ap_id,
46 "to" => recipients,
47 "object" => object,
48 "type" => "Create",
49 "published" => DateTime.utc_now() |> DateTime.to_iso8601()
50 }, []}
51 end
52
53 def chat_message(actor, recipient, content, opts \\ []) do
54 basic = %{
55 "id" => Utils.generate_object_id(),
56 "actor" => actor.ap_id,
57 "type" => "ChatMessage",
58 "to" => [recipient],
59 "content" => content,
60 "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
61 "emoji" => Emoji.Formatter.get_emoji_map(content)
62 }
63
64 case opts[:attachment] do
65 %Object{data: attachment_data} ->
66 {
67 :ok,
68 Map.put(basic, "attachment", attachment_data),
69 []
70 }
71
72 _ ->
73 {:ok, basic, []}
74 end
75 end
76
77 @spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}
78 def like(actor, object) do
79 object_actor = User.get_cached_by_ap_id(object.data["actor"])
80
81 # Address the actor of the object, and our actor's follower collection if the post is public.
82 to =
83 if Visibility.is_public?(object) do
84 [actor.follower_address, object.data["actor"]]
85 else
86 [object.data["actor"]]
87 end
88
89 # CC everyone who's been addressed in the object, except ourself and the object actor's
90 # follower collection
91 cc =
92 (object.data["to"] ++ (object.data["cc"] || []))
93 |> List.delete(actor.ap_id)
94 |> List.delete(object_actor.follower_address)
95
96 {:ok,
97 %{
98 "id" => Utils.generate_activity_id(),
99 "actor" => actor.ap_id,
100 "type" => "Like",
101 "object" => object.data["id"],
102 "to" => to,
103 "cc" => cc,
104 "context" => object.data["context"]
105 }, []}
106 end
107 end