diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/healthcheck.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/marker.ex | 45 | ||||
| -rw-r--r-- | lib/pleroma/notification.ex | 84 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 25 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/builder.ex | 24 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/object_validator.ex | 11 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex | 81 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/side_effects.ex | 12 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 23 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 6 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/account_view.ex | 29 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/marker_view.ex | 5 | ||||
| -rw-r--r-- | lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/push/impl.ex | 9 | 
14 files changed, 275 insertions, 83 deletions
| diff --git a/lib/pleroma/healthcheck.ex b/lib/pleroma/healthcheck.ex index 8f7f43ec2..92ce83cb7 100644 --- a/lib/pleroma/healthcheck.ex +++ b/lib/pleroma/healthcheck.ex @@ -29,7 +29,7 @@ defmodule Pleroma.Healthcheck do    @spec system_info() :: t()    def system_info do      %Healthcheck{ -      memory_used: Float.round(:erlang.memory(:total) / 1024 / 1024, 2) +      memory_used: Float.round(:recon_alloc.memory(:allocated) / 1024 / 1024, 2)      }      |> assign_db_info()      |> assign_job_queue_stats() diff --git a/lib/pleroma/marker.ex b/lib/pleroma/marker.ex index 443927392..4d82860f5 100644 --- a/lib/pleroma/marker.ex +++ b/lib/pleroma/marker.ex @@ -9,24 +9,34 @@ defmodule Pleroma.Marker do    import Ecto.Query    alias Ecto.Multi +  alias Pleroma.Notification    alias Pleroma.Repo    alias Pleroma.User +  alias __MODULE__    @timelines ["notifications"] +  @type t :: %__MODULE__{}    schema "markers" do      field(:last_read_id, :string, default: "")      field(:timeline, :string, default: "")      field(:lock_version, :integer, default: 0) +    field(:unread_count, :integer, default: 0, virtual: true)      belongs_to(:user, User, type: FlakeId.Ecto.CompatType)      timestamps()    end +  @doc "Gets markers by user and timeline." +  @spec get_markers(User.t(), list(String)) :: list(t())    def get_markers(user, timelines \\ []) do -    Repo.all(get_query(user, timelines)) +    user +    |> get_query(timelines) +    |> unread_count_query() +    |> Repo.all()    end +  @spec upsert(User.t(), map()) :: {:ok | :error, any()}    def upsert(%User{} = user, attrs) do      attrs      |> Map.take(@timelines) @@ -45,6 +55,27 @@ defmodule Pleroma.Marker do      |> Repo.transaction()    end +  @spec multi_set_last_read_id(Multi.t(), User.t(), String.t()) :: Multi.t() +  def multi_set_last_read_id(multi, %User{} = user, "notifications") do +    multi +    |> Multi.run(:counters, fn _repo, _changes -> +      {:ok, %{last_read_id: Repo.one(Notification.last_read_query(user))}} +    end) +    |> Multi.insert( +      :marker, +      fn %{counters: attrs} -> +        %Marker{timeline: "notifications", user_id: user.id} +        |> struct(attrs) +        |> Ecto.Changeset.change() +      end, +      returning: true, +      on_conflict: {:replace, [:last_read_id]}, +      conflict_target: [:user_id, :timeline] +    ) +  end + +  def multi_set_last_read_id(multi, _, _), do: multi +    defp get_marker(user, timeline) do      case Repo.find_resource(get_query(user, timeline)) do        {:ok, marker} -> %__MODULE__{marker | user: user} @@ -71,4 +102,16 @@ defmodule Pleroma.Marker do      |> by_user_id(user.id)      |> by_timeline(timelines)    end + +  defp unread_count_query(query) do +    from( +      q in query, +      left_join: n in "notifications", +      on: n.user_id == q.user_id and n.seen == false, +      group_by: [:id], +      select_merge: %{ +        unread_count: fragment("count(?)", n.id) +      } +    ) +  end  end diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 98289af08..8aa9ed2d4 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -5,8 +5,10 @@  defmodule Pleroma.Notification do    use Ecto.Schema +  alias Ecto.Multi    alias Pleroma.Activity    alias Pleroma.FollowingRelationship +  alias Pleroma.Marker    alias Pleroma.Notification    alias Pleroma.Object    alias Pleroma.Pagination @@ -34,11 +36,30 @@ defmodule Pleroma.Notification do      timestamps()    end +  @spec unread_notifications_count(User.t()) :: integer() +  def unread_notifications_count(%User{id: user_id}) do +    from(q in __MODULE__, +      where: q.user_id == ^user_id and q.seen == false +    ) +    |> Repo.aggregate(:count, :id) +  end +    def changeset(%Notification{} = notification, attrs) do      notification      |> cast(attrs, [:seen])    end +  @spec last_read_query(User.t()) :: Ecto.Queryable.t() +  def last_read_query(user) do +    from(q in Pleroma.Notification, +      where: q.user_id == ^user.id, +      where: q.seen == true, +      select: type(q.id, :string), +      limit: 1, +      order_by: [desc: :id] +    ) +  end +    defp for_user_query_ap_id_opts(user, opts) do      ap_id_relationships =        [:block] ++ @@ -185,25 +206,23 @@ defmodule Pleroma.Notification do      |> Repo.all()    end -  def set_read_up_to(%{id: user_id} = _user, id) do +  def set_read_up_to(%{id: user_id} = user, id) do      query =        from(          n in Notification,          where: n.user_id == ^user_id,          where: n.id <= ^id,          where: n.seen == false, -        update: [ -          set: [ -            seen: true, -            updated_at: ^NaiveDateTime.utc_now() -          ] -        ],          # Ideally we would preload object and activities here          # but Ecto does not support preloads in update_all          select: n.id        ) -    {_, notification_ids} = Repo.update_all(query, []) +    {:ok, %{ids: {_, notification_ids}}} = +      Multi.new() +      |> Multi.update_all(:ids, query, set: [seen: true, updated_at: NaiveDateTime.utc_now()]) +      |> Marker.multi_set_last_read_id(user, "notifications") +      |> Repo.transaction()      Notification      |> where([n], n.id in ^notification_ids) @@ -220,11 +239,18 @@ defmodule Pleroma.Notification do      |> Repo.all()    end +  @spec read_one(User.t(), String.t()) :: +          {:ok, Notification.t()} | {:error, Ecto.Changeset.t()} | nil    def read_one(%User{} = user, notification_id) do      with {:ok, %Notification{} = notification} <- get(user, notification_id) do -      notification -      |> changeset(%{seen: true}) -      |> Repo.update() +      Multi.new() +      |> Multi.update(:update, changeset(notification, %{seen: true})) +      |> Marker.multi_set_last_read_id(user, "notifications") +      |> Repo.transaction() +      |> case do +        {:ok, %{update: notification}} -> {:ok, notification} +        {:error, :update, changeset, _} -> {:error, changeset} +      end      end    end @@ -316,8 +342,11 @@ defmodule Pleroma.Notification do    # TODO move to sql, too.    def create_notification(%Activity{} = activity, %User{} = user, do_send \\ true) do      unless skip?(activity, user) do -      notification = %Notification{user_id: user.id, activity: activity} -      {:ok, notification} = Repo.insert(notification) +      {:ok, %{notification: notification}} = +        Multi.new() +        |> Multi.insert(:notification, %Notification{user_id: user.id, activity: activity}) +        |> Marker.multi_set_last_read_id(user, "notifications") +        |> Repo.transaction()        if do_send do          Streamer.stream(["user", "user:notification"], notification) @@ -339,13 +368,7 @@ defmodule Pleroma.Notification do    def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only)        when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do -    potential_receiver_ap_ids = -      [] -      |> Utils.maybe_notify_to_recipients(activity) -      |> Utils.maybe_notify_mentioned_recipients(activity) -      |> Utils.maybe_notify_subscribers(activity) -      |> Utils.maybe_notify_followers(activity) -      |> Enum.uniq() +    potential_receiver_ap_ids = get_potential_receiver_ap_ids(activity)      potential_receivers = User.get_users_from_set(potential_receiver_ap_ids, local_only) @@ -363,6 +386,27 @@ defmodule Pleroma.Notification do    def get_notified_from_activity(_, _local_only), do: {[], []} +  # For some activities, only notify the author of the object +  def get_potential_receiver_ap_ids(%{data: %{"type" => type, "object" => object_id}}) +      when type in ~w{Like Announce EmojiReact} do +    case Object.get_cached_by_ap_id(object_id) do +      %Object{data: %{"actor" => actor}} -> +        [actor] + +      _ -> +        [] +    end +  end + +  def get_potential_receiver_ap_ids(activity) do +    [] +    |> Utils.maybe_notify_to_recipients(activity) +    |> Utils.maybe_notify_mentioned_recipients(activity) +    |> Utils.maybe_notify_subscribers(activity) +    |> Utils.maybe_notify_followers(activity) +    |> Enum.uniq() +  end +    @doc "Filters out AP IDs domain-blocking and not following the activity's actor"    def exclude_domain_blocker_ap_ids(ap_ids, activity, preloaded_users \\ []) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 5abeb94c6..4955243ab 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -356,31 +356,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      end    end -  @spec react_with_emoji(User.t(), Object.t(), String.t(), keyword()) :: -          {:ok, Activity.t(), Object.t()} | {:error, any()} -  def react_with_emoji(user, object, emoji, options \\ []) do -    with {:ok, result} <- -           Repo.transaction(fn -> do_react_with_emoji(user, object, emoji, options) end) do -      result -    end -  end - -  defp do_react_with_emoji(user, object, emoji, options) do -    with local <- Keyword.get(options, :local, true), -         activity_id <- Keyword.get(options, :activity_id, nil), -         true <- Pleroma.Emoji.is_unicode_emoji?(emoji), -         reaction_data <- make_emoji_reaction_data(user, object, emoji, activity_id), -         {:ok, activity} <- insert(reaction_data, local), -         {:ok, object} <- add_emoji_reaction_to_object(activity, object), -         _ <- notify_and_stream(activity), -         :ok <- maybe_federate(activity) do -      {:ok, activity, object} -    else -      false -> {:error, false} -      {:error, error} -> Repo.rollback(error) -    end -  end -    @spec announce(User.t(), Object.t(), String.t() | nil, boolean(), boolean()) ::            {:ok, Activity.t(), Object.t()} | {:error, any()}    def announce( diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index b0f447e28..922a444a9 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -10,6 +10,18 @@ defmodule Pleroma.Web.ActivityPub.Builder do    alias Pleroma.Web.ActivityPub.Utils    alias Pleroma.Web.ActivityPub.Visibility +  @spec emoji_react(User.t(), Object.t(), String.t()) :: {:ok, map(), keyword()} +  def emoji_react(actor, object, emoji) do +    with {:ok, data, meta} <- object_action(actor, object) do +      data = +        data +        |> Map.put("content", emoji) +        |> Map.put("type", "EmojiReact") + +      {:ok, data, meta} +    end +  end +    @spec undo(User.t(), Activity.t()) :: {:ok, map(), keyword()}    def undo(actor, object) do      {:ok, @@ -52,6 +64,17 @@ defmodule Pleroma.Web.ActivityPub.Builder do    @spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}    def like(actor, object) do +    with {:ok, data, meta} <- object_action(actor, object) do +      data = +        data +        |> Map.put("type", "Like") + +      {:ok, data, meta} +    end +  end + +  @spec object_action(User.t(), Object.t()) :: {:ok, map(), keyword()} +  defp object_action(actor, object) do      object_actor = User.get_cached_by_ap_id(object.data["actor"])      # Address the actor of the object, and our actor's follower collection if the post is public. @@ -73,7 +96,6 @@ defmodule Pleroma.Web.ActivityPub.Builder do       %{         "id" => Utils.generate_activity_id(),         "actor" => actor.ap_id, -       "type" => "Like",         "object" => object.data["id"],         "to" => to,         "cc" => cc, diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index 4782cd8f3..549e5e761 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -12,6 +12,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do    alias Pleroma.Object    alias Pleroma.User    alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator +  alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator    alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator    alias Pleroma.Web.ActivityPub.ObjectValidators.Types    alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator @@ -47,6 +48,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do      end    end +  def validate(%{"type" => "EmojiReact"} = object, meta) do +    with {:ok, object} <- +           object +           |> EmojiReactValidator.cast_and_validate() +           |> Ecto.Changeset.apply_action(:insert) do +      object = stringify_keys(object |> Map.from_struct()) +      {:ok, object, meta} +    end +  end +    def stringify_keys(%{__struct__: _} = object) do      object      |> Map.from_struct() diff --git a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex new file mode 100644 index 000000000..e87519c59 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex @@ -0,0 +1,81 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do +  use Ecto.Schema + +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.ObjectValidators.Types + +  import Ecto.Changeset +  import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + +  @primary_key false + +  embedded_schema do +    field(:id, Types.ObjectID, primary_key: true) +    field(:type, :string) +    field(:object, Types.ObjectID) +    field(:actor, Types.ObjectID) +    field(:context, :string) +    field(:content, :string) +    field(:to, {:array, :string}, default: []) +    field(:cc, {:array, :string}, default: []) +  end + +  def cast_and_validate(data) do +    data +    |> cast_data() +    |> validate_data() +  end + +  def cast_data(data) do +    %__MODULE__{} +    |> changeset(data) +  end + +  def changeset(struct, data) do +    struct +    |> cast(data, __schema__(:fields)) +    |> fix_after_cast() +  end + +  def fix_after_cast(cng) do +    cng +    |> fix_context() +  end + +  def fix_context(cng) do +    object = get_field(cng, :object) + +    with nil <- get_field(cng, :context), +         %Object{data: %{"context" => context}} <- Object.get_cached_by_ap_id(object) do +      cng +      |> put_change(:context, context) +    else +      _ -> +        cng +    end +  end + +  def validate_emoji(cng) do +    content = get_field(cng, :content) + +    if Pleroma.Emoji.is_unicode_emoji?(content) do +      cng +    else +      cng +      |> add_error(:content, "must be a single character emoji") +    end +  end + +  def validate_data(data_cng) do +    data_cng +    |> validate_inclusion(:type, ["EmojiReact"]) +    |> validate_required([:id, :type, :object, :actor, :context, :to, :cc, :content]) +    |> validate_actor_presence() +    |> validate_object_presence() +    |> validate_emoji() +  end +end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 5049cb54e..bfc2ab845 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -35,6 +35,18 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do    end    # Tasks this handles: +  # - Add reaction to object +  # - Set up notification +  def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do +    reacted_object = Object.get_by_ap_id(object.data["object"]) +    Utils.add_emoji_reaction_to_object(object, reacted_object) + +    Notification.create_notifications(object) + +    {:ok, object, meta} +  end + +  # Tasks this handles:    # - Delete and unpins the create activity    # - Replace object with Tombstone    # - Set up notification diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 26b5bda0e..be7b57f13 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -656,7 +656,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      |> handle_incoming(options)    end -  def handle_incoming(%{"type" => "Like"} = data, _options) do +  def handle_incoming(%{"type" => type} = data, _options) when type in ["Like", "EmojiReact"] do      with :ok <- ObjectValidator.fetch_actor_and_object(data),           {:ok, activity, _meta} <-             Pipeline.common_pipeline(data, local: false) do @@ -667,27 +667,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do    end    def handle_incoming( -        %{ -          "type" => "EmojiReact", -          "object" => object_id, -          "actor" => _actor, -          "id" => id, -          "content" => emoji -        } = data, -        _options -      ) do -    with actor <- Containment.get_actor(data), -         {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor), -         {:ok, object} <- get_obj_helper(object_id), -         {:ok, activity, _object} <- -           ActivityPub.react_with_emoji(actor, object, emoji, activity_id: id, local: false) do -      {:ok, activity} -    else -      _e -> :error -    end -  end - -  def handle_incoming(          %{"type" => "Announce", "object" => object_id, "actor" => _actor, "id" => id} = data,          _options        ) do diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 1e6bbbab7..c538a634f 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -191,8 +191,10 @@ defmodule Pleroma.Web.CommonAPI do    def react_with_emoji(id, user, emoji) do      with %Activity{} = activity <- Activity.get_by_id(id), -         object <- Object.normalize(activity) do -      ActivityPub.react_with_emoji(user, object, emoji) +         object <- Object.normalize(activity), +         {:ok, emoji_react, _} <- Builder.emoji_react(user, object, emoji), +         {:ok, activity, _} <- Pipeline.common_pipeline(emoji_react, local: true) do +      {:ok, activity}      else        _ ->          {:error, dgettext("errors", "Could not add reaction emoji")} diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index b4b61e74c..420bd586f 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -36,9 +36,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do    end    def render("show.json", %{user: user} = opts) do -    if User.visible_for?(user, opts[:for]), -      do: do_render("show.json", opts), -      else: %{} +    if User.visible_for?(user, opts[:for]) do +      do_render("show.json", opts) +    else +      %{} +    end    end    def render("mention.json", %{user: user}) do @@ -221,7 +223,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do        fields: user.fields,        bot: bot,        source: %{ -        note: (user.bio || "") |> String.replace(~r(<br */?>), "\n") |> Pleroma.HTML.strip_tags(), +        note: prepare_user_bio(user),          sensitive: false,          fields: user.raw_fields,          pleroma: %{ @@ -253,8 +255,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do      |> maybe_put_follow_requests_count(user, opts[:for])      |> maybe_put_allow_following_move(user, opts[:for])      |> maybe_put_unread_conversation_count(user, opts[:for]) +    |> maybe_put_unread_notification_count(user, opts[:for])    end +  defp prepare_user_bio(%User{bio: ""}), do: "" + +  defp prepare_user_bio(%User{bio: bio}) when is_binary(bio) do +    bio |> String.replace(~r(<br */?>), "\n") |> Pleroma.HTML.strip_tags() +  end + +  defp prepare_user_bio(_), do: "" +    defp username_from_nickname(string) when is_binary(string) do      hd(String.split(string, "@"))    end @@ -350,6 +361,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do    defp maybe_put_unread_conversation_count(data, _, _), do: data +  defp maybe_put_unread_notification_count(data, %User{id: user_id}, %User{id: user_id} = user) do +    Kernel.put_in( +      data, +      [:pleroma, :unread_notifications_count], +      Pleroma.Notification.unread_notifications_count(user) +    ) +  end + +  defp maybe_put_unread_notification_count(data, _, _), do: data +    defp image_url(%{"url" => [%{"href" => href} | _]}), do: href    defp image_url(_), do: nil  end diff --git a/lib/pleroma/web/mastodon_api/views/marker_view.ex b/lib/pleroma/web/mastodon_api/views/marker_view.ex index 9705b7a91..21d535d54 100644 --- a/lib/pleroma/web/mastodon_api/views/marker_view.ex +++ b/lib/pleroma/web/mastodon_api/views/marker_view.ex @@ -11,7 +11,10 @@ defmodule Pleroma.Web.MastodonAPI.MarkerView do         %{           last_read_id: m.last_read_id,           version: m.lock_version, -         updated_at: NaiveDateTime.to_iso8601(m.updated_at) +         updated_at: NaiveDateTime.to_iso8601(m.updated_at), +         pleroma: %{ +           unread_count: m.unread_count +         }         }}      end)    end diff --git a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex index 4aa5c1dd8..8bc77b75e 100644 --- a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex @@ -86,7 +86,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do    end    def react_with_emoji(%{assigns: %{user: user}} = conn, %{"id" => activity_id, "emoji" => emoji}) do -    with {:ok, _activity, _object} <- CommonAPI.react_with_emoji(activity_id, user, emoji), +    with {:ok, _activity} <- CommonAPI.react_with_emoji(activity_id, user, emoji),           activity <- Activity.get_by_id(activity_id) do        conn        |> put_view(StatusView) diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex index a9f893f7b..691725702 100644 --- a/lib/pleroma/web/push/impl.ex +++ b/lib/pleroma/web/push/impl.ex @@ -106,14 +106,13 @@ defmodule Pleroma.Web.Push.Impl do    def build_content(          %{ -          activity: %{data: %{"directMessage" => true}},            user: %{notification_settings: %{privacy_option: true}} -        }, -        actor, +        } = notification, +        _actor,          _object, -        _mastodon_type +        mastodon_type        ) do -    %{title: "New Direct Message", body: "@#{actor.nickname}"} +    %{body: format_title(notification, mastodon_type)}    end    def build_content(notification, actor, object, mastodon_type) do | 
