Merge remote-tracking branch 'pleroma/develop' into feature/disable-account
[akkoma] / lib / pleroma / web / streamer.ex
index 4de7608e4c683d789cbf80779101136739770c4d..133decfc43972daacfd985c5d7350f6eaad4abe8 100644 (file)
@@ -5,12 +5,14 @@
 defmodule Pleroma.Web.Streamer do
   use GenServer
   require Logger
-  alias Pleroma.User
-  alias Pleroma.Notification
   alias Pleroma.Activity
+  alias Pleroma.Conversation.Participation
+  alias Pleroma.Notification
   alias Pleroma.Object
-  alias Pleroma.Repo
+  alias Pleroma.User
   alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.ActivityPub.Visibility
+  alias Pleroma.Web.MastodonAPI.NotificationView
 
   @keepalive_interval :timer.seconds(30)
 
@@ -70,19 +72,28 @@ defmodule Pleroma.Web.Streamer do
     {:noreply, topics}
   end
 
+  def handle_cast(%{action: :stream, topic: "participation", item: participation}, topics) do
+    user_topic = "direct:#{participation.user_id}"
+    Logger.debug("Trying to push a conversation participation to #{user_topic}\n\n")
+
+    push_to_socket(topics, user_topic, participation)
+
+    {:noreply, topics}
+  end
+
   def handle_cast(%{action: :stream, topic: "list", item: item}, topics) do
     # filter the recipient list if the activity is not public, see #270.
     recipient_lists =
-      case ActivityPub.is_public?(item) do
+      case Visibility.is_public?(item) do
         true ->
           Pleroma.List.get_lists_from_activity(item)
 
         _ ->
           Pleroma.List.get_lists_from_activity(item)
           |> Enum.filter(fn list ->
-            owner = Repo.get(User, list.user_id)
+            owner = User.get_cached_by_id(list.user_id)
 
-            ActivityPub.visible_for_user?(item, owner)
+            Visibility.visible_for_user?(item, owner)
           end)
       end
 
@@ -106,10 +117,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!()
@@ -191,16 +202,33 @@ defmodule Pleroma.Web.Streamer do
     |> Jason.encode!()
   end
 
+  def represent_conversation(%Participation{} = participation) do
+    %{
+      event: "conversation",
+      payload:
+        Pleroma.Web.MastodonAPI.ConversationView.render("participation.json", %{
+          participation: participation,
+          user: participation.user
+        })
+        |> Jason.encode!()
+    }
+    |> Jason.encode!()
+  end
+
   def push_to_socket(topics, topic, %Activity{data: %{"type" => "Announce"}} = item) do
     Enum.each(topics[topic] || [], fn socket ->
       # Get the current user so we have up-to-date blocks etc.
       if socket.assigns[:user] do
         user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
         blocks = user.info.blocks || []
+        mutes = user.info.mutes || []
+        reblog_mutes = user.info.muted_reblogs || []
 
-        parent = Object.normalize(item.data["object"])
+        parent = Object.normalize(item)
 
-        unless is_nil(parent) or item.actor in blocks or parent.data["actor"] in blocks do
+        unless is_nil(parent) or item.actor in blocks or item.actor in mutes or
+                 item.actor in reblog_mutes or not ActivityPub.contain_activity(item, user) or
+                 parent.data["actor"] in blocks or parent.data["actor"] in mutes do
           send(socket.transport_pid, {:text, represent_update(item, user)})
         end
       else
@@ -209,23 +237,35 @@ defmodule Pleroma.Web.Streamer do
     end)
   end
 
-  def push_to_socket(topics, topic, %Activity{id: id, data: %{"type" => "Delete"}}) do
+  def push_to_socket(topics, topic, %Participation{} = participation) do
+    Enum.each(topics[topic] || [], fn socket ->
+      send(socket.transport_pid, {:text, represent_conversation(participation)})
+    end)
+  end
+
+  def push_to_socket(topics, topic, %Activity{
+        data: %{"type" => "Delete", "deleted_activity_id" => deleted_activity_id}
+      }) do
     Enum.each(topics[topic] || [], fn socket ->
       send(
         socket.transport_pid,
-        {:text, %{event: "delete", payload: to_string(id)} |> Jason.encode!()}
+        {:text, %{event: "delete", payload: to_string(deleted_activity_id)} |> Jason.encode!()}
       )
     end)
   end
 
+  def push_to_socket(_topics, _topic, %Activity{data: %{"type" => "Delete"}}), do: :noop
+
   def push_to_socket(topics, topic, item) do
     Enum.each(topics[topic] || [], fn socket ->
       # Get the current user so we have up-to-date blocks etc.
       if socket.assigns[:user] do
         user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
         blocks = user.info.blocks || []
+        mutes = user.info.mutes || []
 
-        unless item.actor in blocks do
+        unless item.actor in blocks or item.actor in mutes or
+                 not ActivityPub.contain_activity(item, user) do
           send(socket.transport_pid, {:text, represent_update(item, user)})
         end
       else