Add `is_seen` to MastoAPI notifications, extract rendering logic into separate Notifi...
authoreugenijm <eugenijm@protonmail.com>
Thu, 14 Mar 2019 18:39:58 +0000 (21:39 +0300)
committereugenijm <eugenijm@protonmail.com>
Thu, 14 Mar 2019 22:35:48 +0000 (01:35 +0300)
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/views/notification_view.ex [new file with mode: 0644]
lib/pleroma/web/streamer.ex
test/web/mastodon_api/notification_view_test.exs [new file with mode: 0644]

index e578f707e0a081073a94483bb82109840b623cbf..265bf837efd6fff2a3fb351a31a700434ae4c6c1 100644 (file)
@@ -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 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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)
diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex
new file mode 100644 (file)
index 0000000..27e9cab
--- /dev/null
@@ -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
index aec11a79f6ba2ff016416ea853502fd4896951c5..5850a9579decd78bba61b9d92b0e43f01215d27a 100644 (file)
@@ -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 @@ defmodule Pleroma.Web.Streamer do
         %{
           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!()
diff --git a/test/web/mastodon_api/notification_view_test.exs b/test/web/mastodon_api/notification_view_test.exs
new file mode 100644 (file)
index 0000000..b826a7e
--- /dev/null
@@ -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