-defmodule Pleroma.Web.Push do
- use GenServer
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
- alias Pleroma.{Repo, User}
- alias Pleroma.Web.Push.Subscription
+defmodule Pleroma.Web.Push do
+ alias Pleroma.Web.Push.Impl
require Logger
- import Ecto.Query
- @types ["Create", "Follow", "Announce", "Like"]
+ def init do
+ unless enabled() do
+ Logger.warn("""
+ VAPID key pair is not found. If you wish to enabled web push, please run
- @gcm_api_key nil
-
- def start_link() do
- GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
- end
+ mix web_push.gen.keypair
- def init(:ok) do
- case Application.get_env(:web_push_encryption, :vapid_details) do
- nil ->
- Logger.error(
- "VAPID key pair is not found. Please, add VAPID configuration to config. Run `mix web_push.gen.keypair` mix task to create a key pair"
- )
-
- {:error, %{}}
-
- _ ->
- {:ok, %{}}
+ and add the resulting output to your configuration file.
+ """)
end
end
- def send(notification) do
- GenServer.cast(Pleroma.Web.Push, {:send, notification})
+ def vapid_config do
+ Application.get_env(:web_push_encryption, :vapid_details, [])
end
- def handle_cast(
- {:send, %{activity: %{data: %{"type" => type}}, user_id: user_id} = notification},
- state
- )
- when type in @types do
- actor = User.get_cached_by_ap_id(notification.activity.data["actor"])
- body = notification |> format(actor) |> Jason.encode!()
-
- Subscription
- |> where(user_id: ^user_id)
- |> Repo.all()
- |> Enum.each(fn record ->
- subscription = %{
- keys: %{
- p256dh: record.key_p256dh,
- auth: record.key_auth
- },
- endpoint: record.endpoint
- }
-
- case WebPushEncryption.send_web_push(body, subscription, @gcm_api_key) do
- {:ok, %{status_code: code}} when 400 <= code and code < 500 ->
- Logger.debug("Removing subscription record")
- Repo.delete!(record)
- :ok
-
- {:ok, %{status_code: code}} when 200 <= code and code < 300 ->
- :ok
-
- {:ok, %{status_code: code}} ->
- Logger.error("Web Push Nonification failed with code: #{code}")
- :error
-
- data ->
- Logger.error("Web Push Nonification failed with unknown error")
- IO.inspect(data)
- :error
- end
- end)
-
- {:noreply, state}
- end
-
- def handle_cast({:send, _}, state) do
- Logger.warn("Unknown notification type")
- {:noreply, state}
- end
-
- def format(%{activity: %{data: %{"type" => "Create"}}}, actor) do
- %{
- title: "New Mention",
- body: "@#{actor.nickname} has mentiond you",
- icon: get_avatar_url(actor)
- }
- end
-
- def format(%{activity: %{data: %{"type" => "Follow"}}}, actor) do
- %{
- title: "New Follower",
- body: "@#{actor.nickname} has followed you",
- icon: get_avatar_url(actor)
- }
- end
-
- def format(%{activity: %{data: %{"type" => "Announce"}}}, actor) do
- %{
- title: "New Announce",
- body: "@#{actor.nickname} has announced your post",
- icon: get_avatar_url(actor)
- }
- end
-
- def format(%{activity: %{data: %{"type" => "Like"}}}, actor) do
- %{
- title: "New Like",
- body: "@#{actor.nickname} has liked your post",
- icon: get_avatar_url(actor)
- }
- end
-
- def get_avatar_url(%{avatar: %{"type" => "Image", "url" => urls}}) do
- case List.first(urls) do
- %{"href" => url} -> url
- _ -> get_avatar_url(nil)
+ def enabled do
+ case vapid_config() do
+ [] -> false
+ list when is_list(list) -> true
+ _ -> false
end
end
- def get_avatar_url(_) do
- Pleroma.Web.Endpoint.static_url() <> "/images/avi.png"
- end
+ def send(notification),
+ do: PleromaJobQueue.enqueue(:web_push, Impl, [notification])
end