diff --git a/lib/pleroma/migration_helper.ex b/lib/pleroma/migration_helper.ex new file mode 100644 index 000000000..e6346aff1 --- /dev/null +++ b/lib/pleroma/migration_helper.ex @@ -0,0 +1,85 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.MigrationHelper do + alias Pleroma.User + alias Pleroma.Object + alias Pleroma.Notification + alias Pleroma.Repo + + import Ecto.Query + + def fill_in_notification_types do + query = + from(n in Pleroma.Notification, + where: is_nil(n.type), + preload: :activity + ) + + query + |> Repo.all() + |> Enum.each(fn notification -> + type = + notification.activity + |> type_from_activity() + + notification + |> Notification.changeset(%{type: type}) + |> Repo.update() + end) + end + + # This is copied over from Notifications to keep this stable. + defp type_from_activity(%{data: %{"type" => type}} = activity) do + case type do + "Follow" -> + accepted_function = fn activity -> + with %User{} = follower <- User.get_by_ap_id(activity.data["actor"]), + %User{} = followed <- User.get_by_ap_id(activity.data["object"]) do + Pleroma.FollowingRelationship.following?(follower, followed) + end + end + + if accepted_function.(activity) do + "follow" + else + "follow_request" + end + + "Announce" -> + "reblog" + + "Like" -> + "favourite" + + "Move" -> + "move" + + "EmojiReact" -> + "pleroma:emoji_reaction" + + # Compatibility with old reactions + "EmojiReaction" -> + "pleroma:emoji_reaction" + + "Create" -> + activity + |> type_from_activity_object() + + t -> + raise "No notification type for activity type #{t}" + end + end + + defp type_from_activity_object(%{data: %{"type" => "Create", "object" => %{}}}), do: "mention" + + defp type_from_activity_object(%{data: %{"type" => "Create"}} = activity) do + object = Object.get_by_ap_id(activity.data["object"]) + + case object && object.data["type"] do + "ChatMessage" -> "pleroma:chat_mention" + _ -> "mention" + end + end +end diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 5c8994e35..682a26912 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -40,26 +40,6 @@ defmodule Pleroma.Notification do timestamps() end - def fill_in_notification_types do - query = - from(n in __MODULE__, - where: is_nil(n.type), - preload: :activity - ) - - query - |> Repo.all() - |> Enum.each(fn notification -> - type = - notification.activity - |> type_from_activity(no_cachex: true) - - notification - |> changeset(%{type: type}) - |> Repo.update() - end) - end - def update_notification_type(user, activity) do with %__MODULE__{} = notification <- Repo.get_by(__MODULE__, user_id: user.id, activity_id: activity.id) do @@ -371,23 +351,10 @@ defmodule Pleroma.Notification do {:ok, notifications} end - defp type_from_activity(%{data: %{"type" => type}} = activity, opts \\ []) do + defp type_from_activity(%{data: %{"type" => type}} = activity) do case type do "Follow" -> - accepted_function = - if Keyword.get(opts, :no_cachex, false) do - # A special function to make this usable in a migration. - fn activity -> - with %User{} = follower <- User.get_by_ap_id(activity.data["actor"]), - %User{} = followed <- User.get_by_ap_id(activity.data["object"]) do - Pleroma.FollowingRelationship.following?(follower, followed) - end - end - else - &Activity.follow_accepted?/1 - end - - if accepted_function.(activity) do + if Activity.follow_accepted?(activity) do "follow" else "follow_request" diff --git a/priv/repo/migrations/20200602125218_backfill_notification_types.exs b/priv/repo/migrations/20200602125218_backfill_notification_types.exs index 493c0280c..58943fad0 100644 --- a/priv/repo/migrations/20200602125218_backfill_notification_types.exs +++ b/priv/repo/migrations/20200602125218_backfill_notification_types.exs @@ -2,7 +2,7 @@ defmodule Pleroma.Repo.Migrations.BackfillNotificationTypes do use Ecto.Migration def up do - Pleroma.Notification.fill_in_notification_types() + Pleroma.MigrationHelper.fill_in_notification_types() end def down do diff --git a/test/migration_helper_test.exs b/test/migration_helper_test.exs new file mode 100644 index 000000000..1c8173987 --- /dev/null +++ b/test/migration_helper_test.exs @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.MigrationHelperTest do + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.MigrationHelper + alias Pleroma.Notification + alias Pleroma.Repo + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + describe "fill_in_notification_types" do + test "it fills in missing notification types" do + user = insert(:user) + other_user = insert(:user) + + {:ok, post} = CommonAPI.post(user, %{status: "yeah, @#{other_user.nickname}"}) + {:ok, chat} = CommonAPI.post_chat_message(user, other_user, "yo") + {:ok, react} = CommonAPI.react_with_emoji(post.id, other_user, "☕") + {:ok, like} = CommonAPI.favorite(other_user, post.id) + {:ok, react_2} = CommonAPI.react_with_emoji(post.id, other_user, "☕") + + data = + react_2.data + |> Map.put("type", "EmojiReaction") + + {:ok, react_2} = + react_2 + |> Activity.change(%{data: data}) + |> Repo.update() + + assert {5, nil} = Repo.update_all(Notification, set: [type: nil]) + + MigrationHelper.fill_in_notification_types() + + assert %{type: "mention"} = + Repo.get_by(Notification, user_id: other_user.id, activity_id: post.id) + + assert %{type: "favourite"} = + Repo.get_by(Notification, user_id: user.id, activity_id: like.id) + + assert %{type: "pleroma:emoji_reaction"} = + Repo.get_by(Notification, user_id: user.id, activity_id: react.id) + + assert %{type: "pleroma:emoji_reaction"} = + Repo.get_by(Notification, user_id: user.id, activity_id: react_2.id) + + assert %{type: "pleroma:chat_mention"} = + Repo.get_by(Notification, user_id: other_user.id, activity_id: chat.id) + end + end +end diff --git a/test/notification_test.exs b/test/notification_test.exs index f2115a29e..b9bbdceca 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.NotificationTest do import Pleroma.Factory import Mock - alias Pleroma.Activity alias Pleroma.FollowingRelationship alias Pleroma.Notification alias Pleroma.Repo @@ -22,47 +21,6 @@ defmodule Pleroma.NotificationTest do alias Pleroma.Web.Push alias Pleroma.Web.Streamer - describe "fill_in_notification_types" do - test "it fills in missing notification types" do - user = insert(:user) - other_user = insert(:user) - - {:ok, post} = CommonAPI.post(user, %{status: "yeah, @#{other_user.nickname}"}) - {:ok, chat} = CommonAPI.post_chat_message(user, other_user, "yo") - {:ok, react} = CommonAPI.react_with_emoji(post.id, other_user, "☕") - {:ok, like} = CommonAPI.favorite(other_user, post.id) - {:ok, react_2} = CommonAPI.react_with_emoji(post.id, other_user, "☕") - - data = - react_2.data - |> Map.put("type", "EmojiReaction") - - {:ok, react_2} = - react_2 - |> Activity.change(%{data: data}) - |> Repo.update() - - assert {5, nil} = Repo.update_all(Notification, set: [type: nil]) - - Notification.fill_in_notification_types() - - assert %{type: "mention"} = - Repo.get_by(Notification, user_id: other_user.id, activity_id: post.id) - - assert %{type: "favourite"} = - Repo.get_by(Notification, user_id: user.id, activity_id: like.id) - - assert %{type: "pleroma:emoji_reaction"} = - Repo.get_by(Notification, user_id: user.id, activity_id: react.id) - - assert %{type: "pleroma:emoji_reaction"} = - Repo.get_by(Notification, user_id: user.id, activity_id: react_2.id) - - assert %{type: "pleroma:chat_mention"} = - Repo.get_by(Notification, user_id: other_user.id, activity_id: chat.id) - end - end - describe "create_notifications" do test "creates a notification for an emoji reaction" do user = insert(:user)