Add is_seen to MastoAPI notifications, extract rendering logic into separate NotificationView, add tests
				
					
				
			This commit is contained in:
		
							parent
							
								
									59333f2d56
								
							
						
					
					
						commit
						100413bf2c
					
				
					 4 changed files with 179 additions and 50 deletions
				
			
		| 
						 | 
				
			
			@ -22,6 +22,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
 | 
			
		|||
  alias Pleroma.Web.MastodonAPI.ListView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.MastodonAPI
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.MastodonView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.NotificationView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.ReportView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.StatusView
 | 
			
		||||
  alias Pleroma.Web.MediaProxy
 | 
			
		||||
| 
						 | 
				
			
			@ -503,19 +504,17 @@ def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
 | 
			
		|||
  def notifications(%{assigns: %{user: user}} = conn, params) do
 | 
			
		||||
    notifications = Notification.for_user(user, params)
 | 
			
		||||
 | 
			
		||||
    result =
 | 
			
		||||
      notifications
 | 
			
		||||
      |> Enum.map(fn x -> render_notification(user, x) end)
 | 
			
		||||
      |> Enum.filter(& &1)
 | 
			
		||||
 | 
			
		||||
    conn
 | 
			
		||||
    |> add_link_headers(:notifications, notifications)
 | 
			
		||||
    |> json(result)
 | 
			
		||||
    |> put_view(NotificationView)
 | 
			
		||||
    |> render("index.json", %{notifications: notifications, for: user})
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_notification(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do
 | 
			
		||||
    with {:ok, notification} <- Notification.get(user, id) do
 | 
			
		||||
      json(conn, render_notification(user, notification))
 | 
			
		||||
      conn
 | 
			
		||||
      |> put_view(NotificationView)
 | 
			
		||||
      |> render("show.json", %{notification: notification, for: user})
 | 
			
		||||
    else
 | 
			
		||||
      {:error, reason} ->
 | 
			
		||||
        conn
 | 
			
		||||
| 
						 | 
				
			
			@ -1309,45 +1308,6 @@ def empty_object(conn, _) do
 | 
			
		|||
    json(conn, %{})
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def render_notification(user, %{id: id, activity: activity, inserted_at: created_at} = _params) do
 | 
			
		||||
    actor = User.get_cached_by_ap_id(activity.data["actor"])
 | 
			
		||||
    parent_activity = Activity.get_create_by_object_ap_id(activity.data["object"])
 | 
			
		||||
    mastodon_type = Activity.mastodon_notification_type(activity)
 | 
			
		||||
 | 
			
		||||
    response = %{
 | 
			
		||||
      id: to_string(id),
 | 
			
		||||
      type: mastodon_type,
 | 
			
		||||
      created_at: CommonAPI.Utils.to_masto_date(created_at),
 | 
			
		||||
      account: AccountView.render("account.json", %{user: actor, for: user})
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case mastodon_type do
 | 
			
		||||
      "mention" ->
 | 
			
		||||
        response
 | 
			
		||||
        |> Map.merge(%{
 | 
			
		||||
          status: StatusView.render("status.json", %{activity: activity, for: user})
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      "favourite" ->
 | 
			
		||||
        response
 | 
			
		||||
        |> Map.merge(%{
 | 
			
		||||
          status: StatusView.render("status.json", %{activity: parent_activity, for: user})
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      "reblog" ->
 | 
			
		||||
        response
 | 
			
		||||
        |> Map.merge(%{
 | 
			
		||||
          status: StatusView.render("status.json", %{activity: parent_activity, for: user})
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      "follow" ->
 | 
			
		||||
        response
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        nil
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_filters(%{assigns: %{user: user}} = conn, _) do
 | 
			
		||||
    filters = Filter.get_filters(user)
 | 
			
		||||
    res = FilterView.render("filters.json", filters: filters)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										64
									
								
								lib/pleroma/web/mastodon_api/views/notification_view.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								lib/pleroma/web/mastodon_api/views/notification_view.ex
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
# Pleroma: A lightweight social networking server
 | 
			
		||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
 | 
			
		||||
# SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 | 
			
		||||
defmodule Pleroma.Web.MastodonAPI.NotificationView do
 | 
			
		||||
  use Pleroma.Web, :view
 | 
			
		||||
 | 
			
		||||
  alias Pleroma.Activity
 | 
			
		||||
  alias Pleroma.Notification
 | 
			
		||||
  alias Pleroma.User
 | 
			
		||||
  alias Pleroma.Web.CommonAPI
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.AccountView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.NotificationView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.StatusView
 | 
			
		||||
 | 
			
		||||
  def render("index.json", %{notifications: notifications, for: user}) do
 | 
			
		||||
    render_many(notifications, NotificationView, "show.json", %{for: user})
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def render("show.json", %{
 | 
			
		||||
        notification: %Notification{activity: activity} = notification,
 | 
			
		||||
        for: user
 | 
			
		||||
      }) do
 | 
			
		||||
    actor = User.get_cached_by_ap_id(activity.data["actor"])
 | 
			
		||||
    parent_activity = Activity.get_create_by_object_ap_id(activity.data["object"])
 | 
			
		||||
    mastodon_type = Activity.mastodon_notification_type(activity)
 | 
			
		||||
 | 
			
		||||
    response = %{
 | 
			
		||||
      id: to_string(notification.id),
 | 
			
		||||
      type: mastodon_type,
 | 
			
		||||
      created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
 | 
			
		||||
      account: AccountView.render("account.json", %{user: actor, for: user}),
 | 
			
		||||
      pleroma: %{
 | 
			
		||||
        is_seen: notification.seen
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case mastodon_type do
 | 
			
		||||
      "mention" ->
 | 
			
		||||
        response
 | 
			
		||||
        |> Map.merge(%{
 | 
			
		||||
          status: StatusView.render("status.json", %{activity: activity, for: user})
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      "favourite" ->
 | 
			
		||||
        response
 | 
			
		||||
        |> Map.merge(%{
 | 
			
		||||
          status: StatusView.render("status.json", %{activity: parent_activity, for: user})
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      "reblog" ->
 | 
			
		||||
        response
 | 
			
		||||
        |> Map.merge(%{
 | 
			
		||||
          status: StatusView.render("status.json", %{activity: parent_activity, for: user})
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      "follow" ->
 | 
			
		||||
        response
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        nil
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ defmodule Pleroma.Web.Streamer do
 | 
			
		|||
  alias Pleroma.Repo
 | 
			
		||||
  alias Pleroma.User
 | 
			
		||||
  alias Pleroma.Web.ActivityPub.Visibility
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.NotificationView
 | 
			
		||||
 | 
			
		||||
  @keepalive_interval :timer.seconds(30)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -106,10 +107,10 @@ def handle_cast(%{action: :stream, topic: "user", item: %Notification{} = item},
 | 
			
		|||
        %{
 | 
			
		||||
          event: "notification",
 | 
			
		||||
          payload:
 | 
			
		||||
            Pleroma.Web.MastodonAPI.MastodonAPIController.render_notification(
 | 
			
		||||
              socket.assigns["user"],
 | 
			
		||||
              item
 | 
			
		||||
            )
 | 
			
		||||
            NotificationView.render("show.json", %{
 | 
			
		||||
              notification: item,
 | 
			
		||||
              for: socket.assigns["user"]
 | 
			
		||||
            })
 | 
			
		||||
            |> Jason.encode!()
 | 
			
		||||
        }
 | 
			
		||||
        |> Jason.encode!()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										104
									
								
								test/web/mastodon_api/notification_view_test.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								test/web/mastodon_api/notification_view_test.exs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,104 @@
 | 
			
		|||
# Pleroma: A lightweight social networking server
 | 
			
		||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
 | 
			
		||||
# SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 | 
			
		||||
defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
 | 
			
		||||
  use Pleroma.DataCase
 | 
			
		||||
 | 
			
		||||
  alias Pleroma.Activity
 | 
			
		||||
  alias Pleroma.Notification
 | 
			
		||||
  alias Pleroma.Repo
 | 
			
		||||
  alias Pleroma.User
 | 
			
		||||
  alias Pleroma.Web.CommonAPI
 | 
			
		||||
  alias Pleroma.Web.CommonAPI.Utils
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.AccountView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.NotificationView
 | 
			
		||||
  alias Pleroma.Web.MastodonAPI.StatusView
 | 
			
		||||
  import Pleroma.Factory
 | 
			
		||||
 | 
			
		||||
  test "Mention notification" do
 | 
			
		||||
    user = insert(:user)
 | 
			
		||||
    mentioned_user = insert(:user)
 | 
			
		||||
    {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{mentioned_user.nickname}"})
 | 
			
		||||
    {:ok, [notification]} = Notification.create_notifications(activity)
 | 
			
		||||
    user = Repo.get(User, user.id)
 | 
			
		||||
 | 
			
		||||
    expected = %{
 | 
			
		||||
      id: to_string(notification.id),
 | 
			
		||||
      pleroma: %{is_seen: false},
 | 
			
		||||
      type: "mention",
 | 
			
		||||
      account: AccountView.render("account.json", %{user: user, for: mentioned_user}),
 | 
			
		||||
      status: StatusView.render("status.json", %{activity: activity, for: mentioned_user}),
 | 
			
		||||
      created_at: Utils.to_masto_date(notification.inserted_at)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result =
 | 
			
		||||
      NotificationView.render("index.json", %{notifications: [notification], for: mentioned_user})
 | 
			
		||||
 | 
			
		||||
    assert [expected] == result
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  test "Favourite notification" do
 | 
			
		||||
    user = insert(:user)
 | 
			
		||||
    another_user = insert(:user)
 | 
			
		||||
    {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
 | 
			
		||||
    {:ok, favorite_activity, _object} = CommonAPI.favorite(create_activity.id, another_user)
 | 
			
		||||
    {:ok, [notification]} = Notification.create_notifications(favorite_activity)
 | 
			
		||||
    create_activity = Repo.get(Activity, create_activity.id)
 | 
			
		||||
 | 
			
		||||
    expected = %{
 | 
			
		||||
      id: to_string(notification.id),
 | 
			
		||||
      pleroma: %{is_seen: false},
 | 
			
		||||
      type: "favourite",
 | 
			
		||||
      account: AccountView.render("account.json", %{user: another_user, for: user}),
 | 
			
		||||
      status: StatusView.render("status.json", %{activity: create_activity, for: user}),
 | 
			
		||||
      created_at: Utils.to_masto_date(notification.inserted_at)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result = NotificationView.render("index.json", %{notifications: [notification], for: user})
 | 
			
		||||
 | 
			
		||||
    assert [expected] == result
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  test "Reblog notification" do
 | 
			
		||||
    user = insert(:user)
 | 
			
		||||
    another_user = insert(:user)
 | 
			
		||||
    {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
 | 
			
		||||
    {:ok, reblog_activity, _object} = CommonAPI.repeat(create_activity.id, another_user)
 | 
			
		||||
    {:ok, [notification]} = Notification.create_notifications(reblog_activity)
 | 
			
		||||
    reblog_activity = Repo.get(Activity, create_activity.id)
 | 
			
		||||
 | 
			
		||||
    expected = %{
 | 
			
		||||
      id: to_string(notification.id),
 | 
			
		||||
      pleroma: %{is_seen: false},
 | 
			
		||||
      type: "reblog",
 | 
			
		||||
      account: AccountView.render("account.json", %{user: another_user, for: user}),
 | 
			
		||||
      status: StatusView.render("status.json", %{activity: reblog_activity, for: user}),
 | 
			
		||||
      created_at: Utils.to_masto_date(notification.inserted_at)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result = NotificationView.render("index.json", %{notifications: [notification], for: user})
 | 
			
		||||
 | 
			
		||||
    assert [expected] == result
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  test "Follow notification" do
 | 
			
		||||
    follower = insert(:user)
 | 
			
		||||
    followed = insert(:user)
 | 
			
		||||
    {:ok, follower, followed, _activity} = CommonAPI.follow(follower, followed)
 | 
			
		||||
    notification = Notification |> Repo.one() |> Repo.preload(:activity)
 | 
			
		||||
 | 
			
		||||
    expected = %{
 | 
			
		||||
      id: to_string(notification.id),
 | 
			
		||||
      pleroma: %{is_seen: false},
 | 
			
		||||
      type: "follow",
 | 
			
		||||
      account: AccountView.render("account.json", %{user: follower, for: followed}),
 | 
			
		||||
      created_at: Utils.to_masto_date(notification.inserted_at)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result =
 | 
			
		||||
      NotificationView.render("index.json", %{notifications: [notification], for: followed})
 | 
			
		||||
 | 
			
		||||
    assert [expected] == result
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
		Reference in a new issue