defmodule Mobilizon.Web.Cache.ActivityPub do @moduledoc """ ActivityPub related cache. """ alias Mobilizon.{Actors, Discussions, Events, Posts, Resources, Todos, Tombstone} alias Mobilizon.Actors.Actor, as: ActorModel alias Mobilizon.Actors.Member alias Mobilizon.Discussions.{Comment, Discussion} alias Mobilizon.Events.Event alias Mobilizon.Federation.ActivityPub.{Actor, Relay} alias Mobilizon.Posts.Post alias Mobilizon.Resources.Resource alias Mobilizon.Todos.{Todo, TodoList} alias Mobilizon.Web.Endpoint alias Mobilizon.Web.Router.Helpers, as: Routes @cache :activity_pub @doc """ Gets a actor by username and eventually domain. """ @spec get_actor_by_name(String.t()) :: {:commit, ActorModel.t()} | {:ignore, nil} def get_actor_by_name(name) do Cachex.fetch(@cache, "actor_" <> name, &do_get_actor/1) end @spec do_get_actor(String.t()) :: {:commit, Actor.t()} | {:ignore, nil} defp do_get_actor("actor_" <> name) do case Actor.find_or_make_actor_from_nickname(name) do {:ok, %ActorModel{suspended: false} = actor} -> {:commit, actor} {:ok, %ActorModel{}} -> {:ignore, nil} {:error, _err} -> {:ignore, nil} end end @doc """ Gets a local actor by username. """ @spec get_local_actor_by_name(String.t()) :: {:commit, ActorModel.t()} | {:ignore, nil} def get_local_actor_by_name(name) do Cachex.fetch(@cache, "local_actor_" <> name, fn "local_actor_" <> name -> case Actors.get_local_actor_by_name(name) do %ActorModel{suspended: false} = actor -> {:commit, actor} {:ok, %ActorModel{}} -> {:ignore, nil} nil -> {:ignore, nil} end end) end @doc """ Gets a public event by its UUID, with all associations loaded. """ @spec get_public_event_by_uuid_with_preload(String.t()) :: {:commit, Event.t()} | {:ignore, nil} def get_public_event_by_uuid_with_preload(uuid) do Cachex.fetch(@cache, "event_" <> uuid, fn "event_" <> uuid -> case Events.get_public_event_by_uuid_with_preload(uuid) do %Event{} = event -> {:commit, event} nil -> with url <- Routes.page_url(Endpoint, :event, uuid), %Tombstone{} = tomstone <- Tombstone.find_tombstone(url) do tomstone else _ -> {:ignore, nil} end end end) end @doc """ Gets a comment by its UUID, with all associations loaded. """ @spec get_comment_by_uuid_with_preload(String.t()) :: {:commit, Comment.t()} | {:ignore, nil} def get_comment_by_uuid_with_preload(uuid) do Cachex.fetch(@cache, "comment_" <> uuid, fn "comment_" <> uuid -> case Discussions.get_comment_from_uuid_with_preload(uuid) do %Comment{} = comment -> {:commit, comment} nil -> {:ignore, nil} end end) end @doc """ Gets a resource by its UUID, with all associations loaded. """ @spec get_resource_by_uuid_with_preload(String.t()) :: {:commit, Resource.t()} | {:ignore, nil} def get_resource_by_uuid_with_preload(uuid) do Cachex.fetch(@cache, "resource_" <> uuid, fn "resource_" <> uuid -> case Resources.get_resource_with_preloads(uuid) do %Resource{} = resource -> {:commit, resource} nil -> {:ignore, nil} end end) end @doc """ Gets a post by its slug, with all associations loaded. """ @spec get_post_by_slug_with_preload(String.t()) :: {:commit, Post.t()} | {:ignore, nil} def get_post_by_slug_with_preload(slug) do Cachex.fetch(@cache, "post_" <> slug, fn "post_" <> slug -> case Posts.get_post_by_slug_with_preloads(slug) do %Post{} = post -> {:commit, post} nil -> {:ignore, nil} end end) end @doc """ Gets a discussion by its slug, with all associations loaded. """ @spec get_discussion_by_slug_with_preload(String.t()) :: {:commit, Discussion.t()} | {:ignore, nil} def get_discussion_by_slug_with_preload(slug) do Cachex.fetch(@cache, "discussion_" <> slug, fn "discussion_" <> slug -> case Discussions.get_discussion_by_slug(slug) do %Discussion{} = discussion -> {:commit, discussion} nil -> {:ignore, nil} end end) end @doc """ Gets a todo list by its UUID, with all associations loaded. """ @spec get_todo_list_by_uuid_with_preload(String.t()) :: {:commit, TodoList.t()} | {:ignore, nil} def get_todo_list_by_uuid_with_preload(uuid) do Cachex.fetch(@cache, "todo_list_" <> uuid, fn "todo_list_" <> uuid -> case Todos.get_todo_list(uuid) do %TodoList{} = todo_list -> {:commit, todo_list} nil -> {:ignore, nil} end end) end @doc """ Gets a todo by its UUID, with all associations loaded. """ @spec get_todo_by_uuid_with_preload(String.t()) :: {:commit, Todo.t()} | {:ignore, nil} def get_todo_by_uuid_with_preload(uuid) do Cachex.fetch(@cache, "todo_" <> uuid, fn "todo_" <> uuid -> case Todos.get_todo(uuid) do %Todo{} = todo -> {:commit, todo} nil -> {:ignore, nil} end end) end @doc """ Gets a member by its UUID, with all associations loaded. """ @spec get_member_by_uuid_with_preload(String.t()) :: {:commit, Member.t()} | {:ignore, nil} def get_member_by_uuid_with_preload(uuid) do Cachex.fetch(@cache, "member_" <> uuid, fn "member_" <> uuid -> case Actors.get_member(uuid) do %Member{} = member -> {:commit, member} nil -> {:ignore, nil} end end) end @doc """ Gets a relay. """ @spec get_relay :: {:commit, ActorModel.t()} | {:ignore, nil} def get_relay do Cachex.fetch(@cache, "relay_actor", &Relay.get_actor/0) end end