MastoAPI: Add streaming for lists.
authoreal <eal@waifu.club>
Wed, 30 May 2018 13:33:37 +0000 (16:33 +0300)
committereal <eal@waifu.club>
Wed, 30 May 2018 13:48:59 +0000 (16:48 +0300)
lib/pleroma/list.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/mastodon_api/mastodon_socket.ex
lib/pleroma/web/streamer.ex
priv/repo/migrations/20180530123448_add_list_follow_index.exs [new file with mode: 0644]
test/list_test.exs

index 9d0b9285bf9e7070b81d28c25fccd21e2b1b0bca..53d98665bf3014561d8643f8dd17c710950aee62 100644 (file)
@@ -1,7 +1,7 @@
 defmodule Pleroma.List do
   use Ecto.Schema
   import Ecto.{Changeset, Query}
-  alias Pleroma.{User, Repo}
+  alias Pleroma.{User, Repo, Activity}
 
   schema "lists" do
     belongs_to(:user, Pleroma.User)
@@ -56,6 +56,19 @@ defmodule Pleroma.List do
     {:ok, Repo.all(q)}
   end
 
+  # Get lists the activity should be streamed to.
+  def get_lists_from_activity(%Activity{actor: ap_id}) do
+    actor = User.get_cached_by_ap_id(ap_id)
+
+    query =
+      from(
+        l in Pleroma.List,
+        where: fragment("? && ?", l.following, ^[actor.follower_address])
+      )
+
+    Repo.all(query)
+  end
+
   def rename(%Pleroma.List{} = list, title) do
     list
     |> title_changeset(%{title: title})
index 4e0be5ba2802143daa32350b2d971ccc6111e650..91e851d5416d10a1b95f202c47411b549cbc6e1d 100644 (file)
@@ -57,6 +57,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
     if activity.data["type"] in ["Create", "Announce"] do
       Pleroma.Web.Streamer.stream("user", activity)
+      Pleroma.Web.Streamer.stream("list", activity)
 
       if Enum.member?(activity.data["to"], public) do
         Pleroma.Web.Streamer.stream("public", activity)
index 080f62b313ac4128f0a017d60f2c3d0bb6d4c373..46648c366ccf1d29400eba1d1708f853941fe558 100644 (file)
@@ -15,10 +15,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonSocket do
     with token when not is_nil(token) <- params["access_token"],
          %Token{user_id: user_id} <- Repo.get_by(Token, token: token),
          %User{} = user <- Repo.get(User, user_id),
-         stream when stream in ["public", "public:local", "user", "direct"] <- params["stream"] do
+         stream when stream in ["public", "public:local", "user", "direct", "list"] <-
+           params["stream"] do
+      topic = if stream == "list", do: "list:#{params["list"]}", else: stream
+
       socket =
         socket
-        |> assign(:topic, params["stream"])
+        |> assign(:topic, topic)
         |> assign(:user, user)
 
       Pleroma.Web.Streamer.add_socket(params["stream"], socket)
index 6ed9035fb5d6414e9b0e04a8d86c08e99ff417e7..0c9e954854a6ca49f581a69ffa8a59b13a29ac75 100644 (file)
@@ -59,6 +59,19 @@ defmodule Pleroma.Web.Streamer do
     {:noreply, topics}
   end
 
+  def handle_cast(%{action: :stream, topic: "list", item: item}, topics) do
+    recipient_topics =
+      Pleroma.List.get_lists_from_activity(item)
+      |> Enum.map(fn %{id: id} -> "list:#{id}" end)
+
+    Enum.each(recipient_topics || [], fn list_topic ->
+      Logger.debug("Trying to push message to #{list_topic}\n\n")
+      push_to_socket(topics, list_topic, item)
+    end)
+
+    {:noreply, topics}
+  end
+
   def handle_cast(%{action: :stream, topic: "user", item: %Notification{} = item}, topics) do
     topic = "user:#{item.user_id}"
 
diff --git a/priv/repo/migrations/20180530123448_add_list_follow_index.exs b/priv/repo/migrations/20180530123448_add_list_follow_index.exs
new file mode 100644 (file)
index 0000000..d6603e9
--- /dev/null
@@ -0,0 +1,7 @@
+defmodule Pleroma.Repo.Migrations.AddListFollowIndex do
+  use Ecto.Migration
+
+  def change do
+    create index(:lists, [:following])
+  end
+end
index ced01209380e837e12454063bc6dbe63ef154b9d..da3b88024d13233c079d23ce3bdbd5b7b15bad5d 100644 (file)
@@ -74,4 +74,20 @@ defmodule Pleroma.ListTest do
     assert list_two in lists
     refute list_three in lists
   end
+
+  test "getting all lists the user is a member of" do
+    user = insert(:user)
+    other_user = insert(:user)
+    {:ok, list_one} = Pleroma.List.create("title", user)
+    {:ok, list_two} = Pleroma.List.create("other title", user)
+    {:ok, list_three} = Pleroma.List.create("third title", other_user)
+    {:ok, list_one} = Pleroma.List.follow(list_one, other_user)
+    {:ok, list_two} = Pleroma.List.follow(list_two, other_user)
+    {:ok, list_three} = Pleroma.List.follow(list_three, user)
+
+    lists = Pleroma.List.get_lists_from_activity(%Pleroma.Activity{actor: other_user.ap_id})
+    assert list_one in lists
+    assert list_two in lists
+    refute list_three in lists
+  end
 end