X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fstreamer.ex;h=6aac472dcdefbc6486d0d0151a477b1eb1b146b7;hb=4dfb40a5467f6206b2793bdafbd82a7ae4ee04bf;hp=3a7b9174322a72c8b68d720dd69830ac852e69ab;hpb=87dee3902ad84599479f4e4a6b3109551651fb71;p=akkoma diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 3a7b91743..6aac472dc 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -1,13 +1,19 @@ defmodule Pleroma.Web.Streamer do use GenServer require Logger - import Plug.Conn + alias Pleroma.{User, Notification} + + def init(args) do + {:ok, args} + end def start_link do spawn(fn -> - Process.sleep(1000 * 30) # 30 seconds + # 30 seconds + Process.sleep(1000 * 30) GenServer.cast(__MODULE__, %{action: :ping}) end) + GenServer.start_link(__MODULE__, %{}, name: __MODULE__) end @@ -25,52 +31,128 @@ defmodule Pleroma.Web.Streamer do def handle_cast(%{action: :ping}, topics) do Map.values(topics) - |> List.flatten - |> Enum.each(fn (socket) -> + |> List.flatten() + |> Enum.each(fn socket -> Logger.debug("Sending keepalive ping") - send socket.transport_pid, {:text, ""} + send(socket.transport_pid, {:text, ""}) end) + spawn(fn -> - Process.sleep(1000 * 30) # 30 seconds + # 30 seconds + Process.sleep(1000 * 30) GenServer.cast(__MODULE__, %{action: :ping}) end) + + {:noreply, topics} + end + + def handle_cast(%{action: :stream, topic: "direct", item: item}, topics) do + recipient_topics = + User.get_recipients_from_activity(item) + |> Enum.map(fn %{id: id} -> "direct:#{id}" end) + + Enum.each(recipient_topics || [], fn user_topic -> + Logger.debug("Trying to push direct message to #{user_topic}\n\n") + push_to_socket(topics, user_topic, item) + end) + + {:noreply, topics} + end + + def handle_cast(%{action: :stream, topic: "user", item: %Notification{} = item}, topics) do + topic = "user:#{item.user_id}" + + Enum.each(topics[topic] || [], fn socket -> + json = + %{ + event: "notification", + payload: + Pleroma.Web.MastodonAPI.MastodonAPIController.render_notification( + socket.assigns["user"], + item + ) + |> Jason.encode!() + } + |> Jason.encode!() + + send(socket.transport_pid, {:text, json}) + end) + + {:noreply, topics} + end + + def handle_cast(%{action: :stream, topic: "user", item: item}, topics) do + Logger.debug("Trying to push to users") + + recipient_topics = + User.get_recipients_from_activity(item) + |> Enum.map(fn %{id: id} -> "user:#{id}" end) + + Enum.each(recipient_topics, fn topic -> + push_to_socket(topics, topic, item) + end) + {:noreply, topics} end def handle_cast(%{action: :stream, topic: topic, item: item}, topics) do Logger.debug("Trying to push to #{topic}") Logger.debug("Pushing item to #{topic}") - Enum.each(topics[topic] || [], fn (socket) -> - json = %{ - event: "update", - payload: Pleroma.Web.MastodonAPI.StatusView.render("status.json", activity: item) |> Poison.encode! - } |> Poison.encode! - - send socket.transport_pid, {:text, json} - end) + push_to_socket(topics, topic, item) {:noreply, topics} end def handle_cast(%{action: :add, topic: topic, socket: socket}, sockets) do + topic = internal_topic(topic, socket) sockets_for_topic = sockets[topic] || [] sockets_for_topic = Enum.uniq([socket | sockets_for_topic]) sockets = Map.put(sockets, topic, sockets_for_topic) Logger.debug("Got new conn for #{topic}") - IO.inspect(sockets) {:noreply, sockets} end def handle_cast(%{action: :remove, topic: topic, socket: socket}, sockets) do + topic = internal_topic(topic, socket) sockets_for_topic = sockets[topic] || [] sockets_for_topic = List.delete(sockets_for_topic, socket) sockets = Map.put(sockets, topic, sockets_for_topic) Logger.debug("Removed conn for #{topic}") - IO.inspect(sockets) {:noreply, sockets} end def handle_cast(m, state) do - IO.inspect("Unknown: #{inspect(m)}, #{inspect(state)}") + Logger.info("Unknown: #{inspect(m)}, #{inspect(state)}") {:noreply, state} end + + 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. + user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id) + blocks = user.info["blocks"] || [] + + unless item.actor in blocks do + json = + %{ + event: "update", + payload: + Pleroma.Web.MastodonAPI.StatusView.render( + "status.json", + activity: item, + for: user + ) + |> Jason.encode!() + } + |> Jason.encode!() + + send(socket.transport_pid, {:text, json}) + end + end) + end + + defp internal_topic(topic, socket) when topic in ~w[user, direct] do + "#{topic}:#{socket.assigns[:user].id}" + end + + defp internal_topic(topic, _), do: topic end