MastodonAPI: Support poll notification

This commit is contained in:
Alex Gleason 2021-07-17 20:35:35 -05:00
commit 0114754db2
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
14 changed files with 262 additions and 21 deletions

View file

@ -72,6 +72,7 @@ defmodule Pleroma.Notification do
pleroma:emoji_reaction
pleroma:report
reblog
poll
}
def changeset(%Notification{} = notification, attrs) do
@ -379,7 +380,7 @@ defmodule Pleroma.Notification do
notifications =
Enum.map(potential_receivers, fn user ->
do_send = do_send && user in enabled_receivers
create_notification(activity, user, do_send)
create_notification(activity, user, do_send: do_send)
end)
|> Enum.reject(&is_nil/1)
@ -435,15 +436,18 @@ defmodule Pleroma.Notification do
end
# TODO move to sql, too.
def create_notification(%Activity{} = activity, %User{} = user, do_send \\ true) do
unless skip?(activity, user) do
def create_notification(%Activity{} = activity, %User{} = user, opts \\ []) do
do_send = Keyword.get(opts, :do_send, true)
type = Keyword.get(opts, :type, type_from_activity(activity))
unless skip?(activity, user, opts) do
{:ok, %{notification: notification}} =
Multi.new()
|> Multi.insert(:notification, %Notification{
user_id: user.id,
activity: activity,
seen: mark_as_read?(activity, user),
type: type_from_activity(activity)
type: type
})
|> Marker.multi_set_last_read_id(user, "notifications")
|> Repo.transaction()
@ -457,6 +461,26 @@ defmodule Pleroma.Notification do
end
end
def create_poll_notifications(%Activity{} = activity) do
with %Object{data: %{"type" => "Question", "actor" => actor} = data} <-
Object.normalize(activity) do
voters =
case data do
%{"voters" => voters} when is_list(voters) -> voters
_ -> []
end
notifications =
Enum.map([actor | voters], fn ap_id ->
with %User{} = user <- User.get_by_ap_id(ap_id) do
create_notification(activity, user, type: "poll")
end
end)
{:ok, notifications}
end
end
@doc """
Returns a tuple with 2 elements:
{notification-enabled receivers, currently disabled receivers (blocking / [thread] muting)}
@ -572,8 +596,10 @@ defmodule Pleroma.Notification do
Enum.uniq(ap_ids) -- thread_muter_ap_ids
end
@spec skip?(Activity.t(), User.t()) :: boolean()
def skip?(%Activity{} = activity, %User{} = user) do
def skip?(activity, user, opts \\ [])
@spec skip?(Activity.t(), User.t(), Keyword.t()) :: boolean()
def skip?(%Activity{} = activity, %User{} = user, opts) do
[
:self,
:invisible,
@ -581,17 +607,21 @@ defmodule Pleroma.Notification do
:recently_followed,
:filtered
]
|> Enum.find(&skip?(&1, activity, user))
|> Enum.find(&skip?(&1, activity, user, opts))
end
def skip?(_, _), do: false
def skip?(_activity, _user, _opts), do: false
@spec skip?(atom(), Activity.t(), User.t()) :: boolean()
def skip?(:self, %Activity{} = activity, %User{} = user) do
activity.data["actor"] == user.ap_id
@spec skip?(atom(), Activity.t(), User.t(), Keyword.t()) :: boolean()
def skip?(:self, %Activity{} = activity, %User{} = user, opts) do
cond do
opts[:type] == "poll" -> false
activity.data["actor"] == user.ap_id -> true
true -> false
end
end
def skip?(:invisible, %Activity{} = activity, _) do
def skip?(:invisible, %Activity{} = activity, _user, _opts) do
actor = activity.data["actor"]
user = User.get_cached_by_ap_id(actor)
User.invisible?(user)
@ -600,7 +630,8 @@ defmodule Pleroma.Notification do
def skip?(
:block_from_strangers,
%Activity{} = activity,
%User{notification_settings: %{block_from_strangers: true}} = user
%User{notification_settings: %{block_from_strangers: true}} = user,
_opts
) do
actor = activity.data["actor"]
follower = User.get_cached_by_ap_id(actor)
@ -608,7 +639,12 @@ defmodule Pleroma.Notification do
end
# To do: consider defining recency in hours and checking FollowingRelationship with a single SQL
def skip?(:recently_followed, %Activity{data: %{"type" => "Follow"}} = activity, %User{} = user) do
def skip?(
:recently_followed,
%Activity{data: %{"type" => "Follow"}} = activity,
%User{} = user,
_opts
) do
actor = activity.data["actor"]
Notification.for_user(user)
@ -618,9 +654,10 @@ defmodule Pleroma.Notification do
end)
end
def skip?(:filtered, %{data: %{"type" => type}}, _) when type in ["Follow", "Move"], do: false
def skip?(:filtered, %{data: %{"type" => type}}, _user, _opts) when type in ["Follow", "Move"],
do: false
def skip?(:filtered, activity, user) do
def skip?(:filtered, activity, user, _opts) do
object = Object.normalize(activity, fetch: false)
cond do
@ -638,7 +675,7 @@ defmodule Pleroma.Notification do
end
end
def skip?(_, _, _), do: false
def skip?(_type, _activity, _user, _opts), do: false
def mark_as_read?(activity, target_user) do
user = Activity.user_actor(activity)