Merge branch 'develop' into refactor/subscription
[akkoma] / lib / pleroma / web / federator / publisher.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.Federator.Publisher do
6 alias Pleroma.Activity
7 alias Pleroma.Config
8 alias Pleroma.User
9 alias Pleroma.Web.Federator.RetryQueue
10
11 require Logger
12
13 @moduledoc """
14 Defines the contract used by federation implementations to publish messages to
15 their peers.
16 """
17
18 @doc """
19 Determine whether an activity can be relayed using the federation module.
20 """
21 @callback is_representable?(Pleroma.Activity.t()) :: boolean()
22
23 @doc """
24 Relays an activity to a specified peer, determined by the parameters. The
25 parameters used are controlled by the federation module.
26 """
27 @callback publish_one(Map.t()) :: {:ok, Map.t()} | {:error, any()}
28
29 @doc """
30 Enqueue publishing a single activity.
31 """
32 @spec enqueue_one(module(), Map.t()) :: :ok
33 def enqueue_one(module, %{} = params),
34 do: PleromaJobQueue.enqueue(:federator_outgoing, __MODULE__, [:publish_one, module, params])
35
36 @spec perform(atom(), module(), any()) :: {:ok, any()} | {:error, any()}
37 def perform(:publish_one, module, params) do
38 case apply(module, :publish_one, [params]) do
39 {:ok, _} ->
40 :ok
41
42 {:error, _e} ->
43 RetryQueue.enqueue(params, module)
44 end
45 end
46
47 def perform(type, _, _) do
48 Logger.debug("Unknown task: #{type}")
49 {:error, "Don't know what to do with this"}
50 end
51
52 @doc """
53 Relays an activity to all specified peers.
54 """
55 @callback publish(User.t(), Activity.t()) :: :ok | {:error, any()}
56
57 @spec publish(User.t(), Activity.t()) :: :ok
58 def publish(%User{} = user, %Activity{} = activity) do
59 Config.get([:instance, :federation_publisher_modules])
60 |> Enum.each(fn module ->
61 if module.is_representable?(activity) do
62 Logger.info("Publishing #{activity.data["id"]} using #{inspect(module)}")
63 module.publish(user, activity)
64 end
65 end)
66
67 :ok
68 end
69
70 @doc """
71 Gathers links used by an outgoing federation module for WebFinger output.
72 """
73 @callback gather_webfinger_links(User.t()) :: list()
74
75 @spec gather_webfinger_links(User.t()) :: list()
76 def gather_webfinger_links(%User{} = user) do
77 Config.get([:instance, :federation_publisher_modules])
78 |> Enum.reduce([], fn module, links ->
79 links ++ module.gather_webfinger_links(user)
80 end)
81 end
82
83 @doc """
84 Gathers nodeinfo protocol names supported by the federation module.
85 """
86 @callback gather_nodeinfo_protocol_names() :: list()
87
88 @spec gather_nodeinfo_protocol_names() :: list()
89 def gather_nodeinfo_protocol_names do
90 Config.get([:instance, :federation_publisher_modules])
91 |> Enum.reduce([], fn module, links ->
92 links ++ module.gather_nodeinfo_protocol_names()
93 end)
94 end
95 end