From 2876fed876045ded1d86812a550bd0feccd72226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sun, 2 Aug 2026 22:13:31 +0200 Subject: [PATCH] Embed notificaiton details for grouped move/reaction/chat/report notification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- changelog.d/grouped-notifs-embed.skip | 0 .../operations/notification_operation.ex | 21 +++++- .../mastodon_api/views/notification_view.ex | 65 ++++++++++++++++--- .../views/notification_view_test.exs | 35 ++++++++++ 4 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 changelog.d/grouped-notifs-embed.skip diff --git a/changelog.d/grouped-notifs-embed.skip b/changelog.d/grouped-notifs-embed.skip new file mode 100644 index 000000000..e69de29bb diff --git a/lib/pleroma/web/api_spec/operations/notification_operation.ex b/lib/pleroma/web/api_spec/operations/notification_operation.ex index 6c8f7d5e9..740f7645d 100644 --- a/lib/pleroma/web/api_spec/operations/notification_operation.ex +++ b/lib/pleroma/web/api_spec/operations/notification_operation.ex @@ -8,6 +8,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do alias Pleroma.Web.ApiSpec.Schemas.Account alias Pleroma.Web.ApiSpec.Schemas.ApiError alias Pleroma.Web.ApiSpec.Schemas.BooleanLike + alias Pleroma.Web.ApiSpec.Schemas.ChatMessage alias Pleroma.Web.ApiSpec.Schemas.Status alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope @@ -304,7 +305,25 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do page_max_id: %Schema{type: :string, nullable: true}, latest_page_notification_at: %Schema{type: :string, format: :"date-time", nullable: true}, sample_account_ids: %Schema{type: :array, items: %Schema{type: :string}}, - status_id: %Schema{type: :string, nullable: true} + status_id: %Schema{type: :string, nullable: true}, + target_id: %Schema{ + type: :string, + description: "ID of the target account for a move notification" + }, + emoji: %Schema{ + type: :string, + description: "Emoji used for an emoji reaction notification" + }, + emoji_url: %Schema{ + type: :string, + nullable: true, + description: "URL of the custom emoji used for an emoji reaction notification" + }, + chat_message: ChatMessage, + report: %Schema{ + type: :object, + description: "Report embedded in a report notification" + } }, required: [ :group_key, diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex index 33d4b2924..eadfac4a0 100644 --- a/lib/pleroma/web/mastodon_api/views/notification_view.ex +++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex @@ -101,13 +101,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do |> Enum.filter(& &1) |> Enum.uniq_by(& &1[:id]) - actors = + accounts = notification_groups |> List.flatten() - |> notification_actors() + |> notification_accounts() %{ - accounts: AccountView.render("index.json", %{users: actors, for: reading_user}), + accounts: AccountView.render("index.json", %{users: accounts, for: reading_user}), statuses: statuses, notification_groups: Enum.map( @@ -191,7 +191,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do defp render_group( [%Notification{} = notification | _] = notifications, - _reading_user, + reading_user, grouped_types, notification_group_counts, notification_group_bounds, @@ -237,13 +237,49 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do response end - if status_activity do - Map.put(response, :status_id, to_string(status_activity.id)) - else - response + response = + if status_activity do + Map.put(response, :status_id, to_string(status_activity.id)) + else + response + end + + put_group_details(response, notification, reading_user) + end + + defp put_group_details(response, %Notification{type: "move", activity: activity}, _reading_user) do + case User.get_cached_by_ap_id(activity.data["target"]) do + %User{id: id} -> Map.put(response, :target_id, to_string(id)) + _ -> response end end + defp put_group_details( + response, + %Notification{type: "pleroma:emoji_reaction", activity: activity}, + _reading_user + ) do + put_emoji(response, activity) + end + + defp put_group_details( + response, + %Notification{type: "pleroma:chat_mention", activity: activity}, + reading_user + ) do + put_chat_message(response, activity, reading_user, %{}) + end + + defp put_group_details( + response, + %Notification{type: "pleroma:report", activity: activity}, + _reading_user + ) do + put_report(response, activity) + end + + defp put_group_details(response, _notification, _reading_user), do: response + defp status_activity_for_group([%Notification{} = notification | _], grouped_types) do status_activity_for(notification, grouped_types) end @@ -287,6 +323,19 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do |> Enum.uniq_by(& &1.id) end + defp notification_accounts(notifications) do + move_targets = + notifications + |> Enum.filter(&(&1.type == "move")) + |> Enum.map(&User.get_cached_by_ap_id(&1.activity.data["target"])) + |> Enum.filter(& &1) + + notifications + |> notification_actors() + |> Kernel.++(move_targets) + |> Enum.uniq_by(& &1.id) + end + defp put_emoji(response, activity) do response |> Map.put(:emoji, activity.data["content"]) diff --git a/test/pleroma/web/mastodon_api/views/notification_view_test.exs b/test/pleroma/web/mastodon_api/views/notification_view_test.exs index 2d0801589..e6fb31e28 100644 --- a/test/pleroma/web/mastodon_api/views/notification_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/notification_view_test.exs @@ -65,6 +65,15 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], recipient, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{ + notifications: [notification], + for: recipient + }) + + assert [group] = grouped.notification_groups + assert group.chat_message == expected.chat_message end test "Mention notification" do @@ -182,6 +191,16 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], follower, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{ + notifications: [notification], + for: follower + }) + + assert [group] = grouped.notification_groups + assert group.target_id == new_user.id + assert Enum.any?(grouped.accounts, &(&1.id == new_user.id)) end test "EmojiReact notification" do @@ -210,6 +229,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], user, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{notifications: [notification], for: user}) + + assert [group] = grouped.notification_groups + assert group.emoji == expected.emoji + assert group.emoji_url == expected.emoji_url end test "EmojiReact custom emoji notification" do @@ -295,6 +321,15 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], moderator_user, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{ + notifications: [notification], + for: moderator_user + }) + + assert [group] = grouped.notification_groups + assert group.report == expected.report end test "Edit notification" do