101 lines
2.7 KiB
Elixir
101 lines
2.7 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
|
|
belongs_to :referenced_activity, Clacks.Activity, type: FlakeId.Ecto.Type
|
|
|
|
timestamps()
|
|
end
|
|
|
|
def changeset(%__MODULE__{} = schema, attrs) do
|
|
schema
|
|
|> cast(attrs, [:type, :user_id, :activity_id, :referenced_activity_id])
|
|
|> validate_required([:type, :user_id, :activity_id])
|
|
|> validate_inclusion(:type, @valid_types)
|
|
end
|
|
|
|
@spec create(
|
|
type :: String.t(),
|
|
activity :: Activity.t(),
|
|
actor :: Actor.t(),
|
|
referenced_activity :: Activity.t() | nil
|
|
) ::
|
|
{: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, referenced_activity) do
|
|
changeset =
|
|
changeset(%__MODULE__{}, %{
|
|
type: type,
|
|
user_id: actor.user_id,
|
|
activity_id: activity.id,
|
|
referenced_activity_id: if(referenced_activity, do: referenced_activity.id, else: nil)
|
|
})
|
|
|
|
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, nil)
|
|
|
|
_ ->
|
|
: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, nil)
|
|
|
|
_ ->
|
|
: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: %Actor{local: true} = original_activity_actor} =
|
|
original_activity <-
|
|
Activity.get_by_object_ap_id(original_object_ap_id, "Create") do
|
|
create(
|
|
String.downcase(type),
|
|
activity,
|
|
original_activity_actor,
|
|
original_activity
|
|
)
|
|
else
|
|
_ ->
|
|
:ok
|
|
end
|
|
end
|
|
|
|
def process_notifications_for_incoming(_), do: :ok
|
|
end
|