clacks/lib/clacks_web/controllers/outbox_controller.ex

77 lines
1.9 KiB
Elixir

defmodule ClacksWeb.OutboxController do
use ClacksWeb, :controller
alias Clacks.{Repo, Actor, Activity}
import Ecto.Query
@context "https://www.w3.org/ns/activitystreams"
@outbox_types ["Create", "Announce"]
plug :get_actor
defp get_actor(%Plug.Conn{path_params: %{"nickname" => nickname}} = conn, _opts) do
case Actor.get_by_nickname(nickname) do
nil ->
conn
|> put_status(404)
%Actor{local: false} ->
conn
|> put_status(404)
actor ->
assign(conn, :actor, actor)
end
end
def outbox(conn, params) when params == %{} do
actor = conn.assigns[:actor]
activities = Repo.all(outbox_query(params, actor))
data = %{
"@context" => @context,
"type" => "OrderedCollection",
"id" => current_url(conn, %{}),
"first" => outbox_page(conn, params, activities)
}
conn
|> put_resp_header("content-type", "application/activity+json")
|> json(data)
end
def outbox(conn, params) do
actor = conn.assigns[:actor]
activities = Repo.all(outbox_query(params, actor))
data =
outbox_page(conn, params, activities)
|> Map.put("@context", @context)
conn
|> put_resp_header("content-type", "application/activity+json")
|> json(data)
end
defp outbox_query(params, %Actor{ap_id: ap_id}) do
Activity
|> where([a], a.actor == ^ap_id)
|> where([a], fragment("?->>'type'", a.data) in @outbox_types)
|> Clacks.Paginator.paginate(params)
|> limit(^Map.get(params, "limit", 20))
end
defp outbox_page(conn, pagination_params, activities) do
last_id = List.last(activities).id
%{
"type" => "OrderedColletionPage",
"partOf" => current_url(conn, %{}),
"id" => current_url(conn, pagination_params),
"next" => current_url(conn, %{max_id: last_id}),
"orderedItems" => Enum.map(activities, & &1.data)
}
end
end