90 lines
2.4 KiB
Elixir
90 lines
2.4 KiB
Elixir
defmodule Clacks.Notification do
|
|
use Ecto.Schema
|
|
import Ecto.Changeset
|
|
alias Clacks.{Activity, Actor, Repo}
|
|
|
|
@type t() :: %__MODULE__{}
|
|
|
|
@valid_types ["follow", "mention", "announce", "like"]
|
|
|
|
schema "notifications" do
|
|
field :type, :string
|
|
|
|
belongs_to :user, Clacks.User
|
|
belongs_to :activity, Clacks.Activity, type: FlakeId.Ecto.Type
|
|
|
|
timestamps()
|
|
end
|
|
|
|
def changeset(%__MODULE__{} = schema, attrs) do
|
|
schema
|
|
|> cast(attrs, [:type, :user_id, :activity_id])
|
|
|> validate_required([:type, :user_id])
|
|
|> validate_inclusion(:type, @valid_types)
|
|
end
|
|
|
|
@spec create(type :: String.t(), activity :: Activity.t(), actor :: Actor.t()) ::
|
|
{:ok, Notification.t()} | {:error, any()}
|
|
|
|
def create(type, _, _) when not (type in @valid_types) do
|
|
{:error, "invalid notification type '#{type}'"}
|
|
end
|
|
|
|
def create(type, activity, actor) do
|
|
changeset =
|
|
changeset(%__MODULE__{}, %{
|
|
type: type,
|
|
user_id: actor.user_id,
|
|
activity_id: activity.id
|
|
})
|
|
|
|
Repo.insert(changeset)
|
|
end
|
|
|
|
def process_notifications_for_incoming(
|
|
%Activity{
|
|
data: %{"type" => "Follow", "object" => followee_ap_id}
|
|
} = activity
|
|
) do
|
|
case Actor.get_cached_by_ap_id(followee_ap_id) do
|
|
%Actor{local: true} = followee ->
|
|
create("follow", activity, followee)
|
|
|
|
_ ->
|
|
:ok
|
|
end
|
|
end
|
|
|
|
def process_notifications_for_incoming(
|
|
%Activity{data: %{"type" => "Create", "object" => %{"type" => "Note", "tag" => tags}}} =
|
|
activity
|
|
) do
|
|
Enum.each(tags, fn %{"href" => mentioned_actor_id} ->
|
|
case Actor.get_cached_by_ap_id(mentioned_actor_id) do
|
|
%Actor{local: true} = mentioned_actor ->
|
|
create("mention", activity, mentioned_actor)
|
|
|
|
_ ->
|
|
:ok
|
|
end
|
|
end)
|
|
end
|
|
|
|
def process_notifications_for_incoming(
|
|
%Activity{data: %{"type" => type, "object" => original_object_ap_id}} = activity
|
|
)
|
|
when type in ["Announce", "Like"] do
|
|
with %Activity{local: true, actor: local_actor_id} <-
|
|
Activity.get_by_object_ap_id(original_object_ap_id),
|
|
%Actor{local: true} = original_activity_actor <-
|
|
Actor.get_cached_by_ap_id(local_actor_id) do
|
|
create(String.downcase(type), activity, original_activity_actor)
|
|
else
|
|
_ ->
|
|
:ok
|
|
end
|
|
end
|
|
|
|
def process_notifications_for_incoming(_), do: :ok
|
|
end
|