1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.MastodonAPI.NotificationView do
9 alias Pleroma.Chat.MessageReference
10 alias Pleroma.Notification
13 alias Pleroma.UserRelationship
14 alias Pleroma.Web.AdminAPI.Report
15 alias Pleroma.Web.AdminAPI.ReportView
16 alias Pleroma.Web.CommonAPI
17 alias Pleroma.Web.MastodonAPI.AccountView
18 alias Pleroma.Web.MastodonAPI.NotificationView
19 alias Pleroma.Web.MastodonAPI.StatusView
20 alias Pleroma.Web.MediaProxy
21 alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
23 defp object_id_for(%{data: %{"object" => %{"id" => id}}}) when is_binary(id), do: id
25 defp object_id_for(%{data: %{"object" => id}}) when is_binary(id), do: id
27 @parent_types ~w{Like Announce EmojiReact Update}
29 def render("index.json", %{notifications: notifications, for: reading_user} = opts) do
30 activities = Enum.map(notifications, & &1.activity)
35 %{data: %{"type" => type}} ->
38 |> Enum.map(&object_id_for/1)
39 |> Activity.create_by_object_ap_id()
40 |> Activity.with_preloaded_object(:left)
45 Map.has_key?(opts, :relationships) ->
48 is_nil(reading_user) ->
49 UserRelationship.view_relationships_option(nil, [])
52 move_activities_targets =
54 |> Enum.filter(&(&1.data["type"] == "Move"))
55 |> Enum.map(&User.get_cached_by_ap_id(&1.data["target"]))
60 |> Enum.map(fn a -> User.get_cached_by_ap_id(a.data["actor"]) end)
62 |> Kernel.++(move_activities_targets)
64 UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes)
69 |> Map.put(:parent_activities, parent_activities)
70 |> Map.put(:relationships, relationships_opt)
72 safe_render_many(notifications, NotificationView, "show.json", opts)
78 notification: %Notification{activity: activity} = notification,
82 actor = User.get_cached_by_ap_id(activity.data["actor"])
84 parent_activity_fn = fn ->
85 if opts[:parent_activities] do
86 Activity.Queries.find_by_object_ap_id(opts[:parent_activities], object_id_for(activity))
88 Activity.get_create_by_object_ap_id(object_id_for(activity))
92 # Note: :relationships contain user mutes (needed for :muted flag in :status)
93 status_render_opts = %{relationships: opts[:relationships]}
94 account = AccountView.render("show.json", %{user: actor, for: reading_user})
97 id: to_string(notification.id),
98 type: notification.type,
99 created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
102 is_muted: User.mutes?(reading_user, actor),
103 is_seen: notification.seen
107 case notification.type do
109 put_status(response, activity, reading_user, status_render_opts)
112 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
115 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
118 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
121 put_target(response, activity, reading_user, %{})
124 put_status(response, activity, reading_user, status_render_opts)
126 "pleroma:emoji_reaction" ->
128 |> put_status(parent_activity_fn.(), reading_user, status_render_opts)
129 |> put_emoji(activity)
131 "pleroma:chat_mention" ->
132 put_chat_message(response, activity, reading_user, status_render_opts)
135 put_report(response, activity)
137 type when type in ["follow", "follow_request"] ->
142 defp put_report(response, activity) do
143 report_render = ReportView.render("show.json", Report.extract_report_info(activity))
145 Map.put(response, :report, report_render)
148 defp put_emoji(response, activity) do
150 |> Map.put(:emoji, activity.data["content"])
151 |> Map.put(:emoji_url, MediaProxy.url(Pleroma.Emoji.emoji_url(activity.data)))
154 defp put_chat_message(response, activity, reading_user, opts) do
155 object = Object.normalize(activity, fetch: false)
156 author = User.get_cached_by_ap_id(object.data["actor"])
157 chat = Pleroma.Chat.get(reading_user.id, author.ap_id)
158 cm_ref = MessageReference.for_chat_and_object(chat, object)
159 render_opts = Map.merge(opts, %{for: reading_user, chat_message_reference: cm_ref})
160 chat_message_render = MessageReferenceView.render("show.json", render_opts)
162 Map.put(response, :chat_message, chat_message_render)
165 defp put_status(response, activity, reading_user, opts) do
166 status_render_opts = Map.merge(opts, %{activity: activity, for: reading_user})
167 status_render = StatusView.render("show.json", status_render_opts)
169 Map.put(response, :status, status_render)
172 defp put_target(response, activity, reading_user, opts) do
173 target_user = User.get_cached_by_ap_id(activity.data["target"])
174 target_render_opts = Map.merge(opts, %{user: target_user, for: reading_user})
175 target_render = AccountView.render("show.json", target_render_opts)
177 Map.put(response, :target, target_render)