Merge branch 'docs/otp-tuning' into 'develop'
[akkoma] / lib / pleroma / web / mastodon_api / views / notification_view.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.NotificationView do
6 use Pleroma.Web, :view
7
8 alias Pleroma.Activity
9 alias Pleroma.Chat.MessageReference
10 alias Pleroma.Notification
11 alias Pleroma.Object
12 alias Pleroma.User
13 alias Pleroma.UserRelationship
14 alias Pleroma.Web.CommonAPI
15 alias Pleroma.Web.MastodonAPI.AccountView
16 alias Pleroma.Web.MastodonAPI.NotificationView
17 alias Pleroma.Web.MastodonAPI.StatusView
18 alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
19
20 @parent_types ~w{Like Announce EmojiReact}
21
22 def render("index.json", %{notifications: notifications, for: reading_user} = opts) do
23 activities = Enum.map(notifications, & &1.activity)
24
25 parent_activities =
26 activities
27 |> Enum.filter(fn
28 %{data: %{"type" => type}} ->
29 type in @parent_types
30 end)
31 |> Enum.map(& &1.data["object"])
32 |> Activity.create_by_object_ap_id()
33 |> Activity.with_preloaded_object(:left)
34 |> Pleroma.Repo.all()
35
36 relationships_opt =
37 cond do
38 Map.has_key?(opts, :relationships) ->
39 opts[:relationships]
40
41 is_nil(reading_user) ->
42 UserRelationship.view_relationships_option(nil, [])
43
44 true ->
45 move_activities_targets =
46 activities
47 |> Enum.filter(&(&1.data["type"] == "Move"))
48 |> Enum.map(&User.get_cached_by_ap_id(&1.data["target"]))
49 |> Enum.filter(& &1)
50
51 actors =
52 activities
53 |> Enum.map(fn a -> User.get_cached_by_ap_id(a.data["actor"]) end)
54 |> Enum.filter(& &1)
55 |> Kernel.++(move_activities_targets)
56
57 UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes)
58 end
59
60 opts =
61 opts
62 |> Map.put(:parent_activities, parent_activities)
63 |> Map.put(:relationships, relationships_opt)
64
65 safe_render_many(notifications, NotificationView, "show.json", opts)
66 end
67
68 def render(
69 "show.json",
70 %{
71 notification: %Notification{activity: activity} = notification,
72 for: reading_user
73 } = opts
74 ) do
75 actor = User.get_cached_by_ap_id(activity.data["actor"])
76
77 parent_activity_fn = fn ->
78 if opts[:parent_activities] do
79 Activity.Queries.find_by_object_ap_id(opts[:parent_activities], activity.data["object"])
80 else
81 Activity.get_create_by_object_ap_id(activity.data["object"])
82 end
83 end
84
85 # Note: :relationships contain user mutes (needed for :muted flag in :status)
86 status_render_opts = %{relationships: opts[:relationships]}
87 account = AccountView.render("show.json", %{user: actor, for: reading_user})
88
89 response = %{
90 id: to_string(notification.id),
91 type: notification.type,
92 created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
93 account: account,
94 pleroma: %{
95 is_muted: User.mutes?(reading_user, actor),
96 is_seen: notification.seen
97 }
98 }
99
100 case notification.type do
101 "mention" ->
102 put_status(response, activity, reading_user, status_render_opts)
103
104 "favourite" ->
105 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
106
107 "reblog" ->
108 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
109
110 "move" ->
111 put_target(response, activity, reading_user, %{})
112
113 "pleroma:emoji_reaction" ->
114 response
115 |> put_status(parent_activity_fn.(), reading_user, status_render_opts)
116 |> put_emoji(activity)
117
118 "pleroma:chat_mention" ->
119 put_chat_message(response, activity, reading_user, status_render_opts)
120
121 type when type in ["follow", "follow_request"] ->
122 response
123 end
124 end
125
126 defp put_emoji(response, activity) do
127 Map.put(response, :emoji, activity.data["content"])
128 end
129
130 defp put_chat_message(response, activity, reading_user, opts) do
131 object = Object.normalize(activity)
132 author = User.get_cached_by_ap_id(object.data["actor"])
133 chat = Pleroma.Chat.get(reading_user.id, author.ap_id)
134 cm_ref = MessageReference.for_chat_and_object(chat, object)
135 render_opts = Map.merge(opts, %{for: reading_user, chat_message_reference: cm_ref})
136 chat_message_render = MessageReferenceView.render("show.json", render_opts)
137
138 Map.put(response, :chat_message, chat_message_render)
139 end
140
141 defp put_status(response, activity, reading_user, opts) do
142 status_render_opts = Map.merge(opts, %{activity: activity, for: reading_user})
143 status_render = StatusView.render("show.json", status_render_opts)
144
145 Map.put(response, :status, status_render)
146 end
147
148 defp put_target(response, activity, reading_user, opts) do
149 target_user = User.get_cached_by_ap_id(activity.data["target"])
150 target_render_opts = Map.merge(opts, %{user: target_user, for: reading_user})
151 target_render = AccountView.render("show.json", target_render_opts)
152
153 Map.put(response, :target, target_render)
154 end
155 end