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