Browse Source

Notifications: Make notifications save their type.

1570-levenshtein-distance-user-search
lain 4 years ago
parent
commit
805ab86933
8 changed files with 90 additions and 27 deletions
  1. +7
    -4
      lib/pleroma/following_relationship.ex
  2. +59
    -2
      lib/pleroma/notification.ex
  3. +3
    -0
      lib/pleroma/web/activity_pub/transmogrifier.ex
  4. +1
    -0
      lib/pleroma/web/api_spec/operations/notification_operation.ex
  5. +1
    -0
      lib/pleroma/web/common_api/common_api.ex
  6. +2
    -18
      lib/pleroma/web/mastodon_api/views/notification_view.ex
  7. +9
    -0
      priv/repo/migrations/20200602094828_add_type_to_notifications.exs
  8. +8
    -3
      test/notification_test.exs

+ 7
- 4
lib/pleroma/following_relationship.ex View File

@@ -62,10 +62,13 @@ defmodule Pleroma.FollowingRelationship do
follow(follower, following, state)

following_relationship ->
following_relationship
|> cast(%{state: state}, [:state])
|> validate_required([:state])
|> Repo.update()
{:ok, relationship} =
following_relationship
|> cast(%{state: state}, [:state])
|> validate_required([:state])
|> Repo.update()

{:ok, relationship}
end
end



+ 59
- 2
lib/pleroma/notification.ex View File

@@ -30,12 +30,26 @@ defmodule Pleroma.Notification do

schema "notifications" do
field(:seen, :boolean, default: false)
field(:type, :string)
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType)

timestamps()
end

def update_notification_type(user, activity) do
with %__MODULE__{} = notification <-
Repo.get_by(__MODULE__, user_id: user.id, activity_id: activity.id) do
type =
activity
|> type_from_activity()

notification
|> changeset(%{type: type})
|> Repo.update()
end
end

@spec unread_notifications_count(User.t()) :: integer()
def unread_notifications_count(%User{id: user_id}) do
from(q in __MODULE__,
@@ -46,7 +60,7 @@ defmodule Pleroma.Notification do

def changeset(%Notification{} = notification, attrs) do
notification
|> cast(attrs, [:seen])
|> cast(attrs, [:seen, :type])
end

@spec last_read_query(User.t()) :: Ecto.Queryable.t()
@@ -330,12 +344,55 @@ defmodule Pleroma.Notification do
{:ok, notifications}
end

defp type_from_activity(%{data: %{"type" => type}} = activity) do
case type do
"Follow" ->
if Activity.follow_accepted?(activity) do
"follow"
else
"follow_request"
end

"Announce" ->
"reblog"

"Like" ->
"favourite"

"Move" ->
"move"

"EmojiReact" ->
"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"}} = activity) do
object = Object.normalize(activity, false)

case object.data["type"] do
"ChatMessage" -> "pleroma:chat_mention"
_ -> "mention"
end
end

# TODO move to sql, too.
def create_notification(%Activity{} = activity, %User{} = user, do_send \\ true) do
unless skip?(activity, user) do
{:ok, %{notification: notification}} =
Multi.new()
|> Multi.insert(:notification, %Notification{user_id: user.id, activity: activity})
|> Multi.insert(:notification, %Notification{
user_id: user.id,
activity: activity,
type: type_from_activity(activity)
})
|> Marker.multi_set_last_read_id(user, "notifications")
|> Repo.transaction()



+ 3
- 0
lib/pleroma/web/activity_pub/transmogrifier.ex View File

@@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Activity
alias Pleroma.EarmarkRenderer
alias Pleroma.FollowingRelationship
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.Repo
@@ -595,6 +596,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
User.update_follower_count(followed)
User.update_following_count(follower)

Notification.update_notification_type(followed, follow_activity)

ActivityPub.accept(%{
to: follow_activity.data["to"],
type: "Accept",


+ 1
- 0
lib/pleroma/web/api_spec/operations/notification_operation.ex View File

@@ -185,6 +185,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
"mention",
"poll",
"pleroma:emoji_reaction",
"pleroma:chat_mention",
"move",
"follow_request"
],


+ 1
- 0
lib/pleroma/web/common_api/common_api.ex View File

@@ -121,6 +121,7 @@ defmodule Pleroma.Web.CommonAPI do
object: follow_activity.data["id"],
type: "Accept"
}) do
Notification.update_notification_type(followed, follow_activity)
{:ok, follower}
end
end


+ 2
- 18
lib/pleroma/web/mastodon_api/views/notification_view.ex View File

@@ -81,22 +81,6 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
end
end

# This returns the notification type by activity, but both chats and statuses
# are in "Create" activities.
mastodon_type =
case Activity.mastodon_notification_type(activity) do
"mention" ->
object = Object.normalize(activity)

case object do
%{data: %{"type" => "ChatMessage"}} -> "pleroma:chat_mention"
_ -> "mention"
end

type ->
type
end

# Note: :relationships contain user mutes (needed for :muted flag in :status)
status_render_opts = %{relationships: opts[:relationships]}

@@ -107,7 +91,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
) do
response = %{
id: to_string(notification.id),
type: mastodon_type,
type: notification.type,
created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
account: account,
pleroma: %{
@@ -115,7 +99,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
}
}

case mastodon_type do
case notification.type do
"mention" ->
put_status(response, activity, reading_user, status_render_opts)



+ 9
- 0
priv/repo/migrations/20200602094828_add_type_to_notifications.exs View File

@@ -0,0 +1,9 @@
defmodule Pleroma.Repo.Migrations.AddTypeToNotifications do
use Ecto.Migration

def change do
alter table(:notifications) do
add(:type, :string)
end
end
end

+ 8
- 3
test/notification_test.exs View File

@@ -31,6 +31,7 @@ defmodule Pleroma.NotificationTest do
{:ok, [notification]} = Notification.create_notifications(activity)

assert notification.user_id == user.id
assert notification.type == "pleroma:emoji_reaction"
end

test "notifies someone when they are directly addressed" do
@@ -48,6 +49,7 @@ defmodule Pleroma.NotificationTest do
notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
assert notified_ids == [other_user.id, third_user.id]
assert notification.activity_id == activity.id
assert notification.type == "mention"
assert other_notification.activity_id == activity.id

assert [%Pleroma.Marker{unread_count: 2}] =
@@ -335,9 +337,12 @@ defmodule Pleroma.NotificationTest do
# After request is accepted, the same notification is rendered with type "follow":
assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)

notification_id = notification.id
assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
assert %{type: "follow"} = NotificationView.render("show.json", render_opts)
notification =
Repo.get(Notification, notification.id)
|> Repo.preload(:activity)

assert %{type: "follow"} =
NotificationView.render("show.json", notification: notification, for: followed_user)
end

test "it doesn't create a notification for follow-unfollow-follow chains" do


Loading…
Cancel
Save