Add AP followers endpoint
This commit is contained in:
parent
091a275b22
commit
7c03d2627f
|
@ -27,8 +27,8 @@ defmodule Clacks.Actor do
|
||||||
|> validate_required([:ap_id, :nickname, :local, :data])
|
|> validate_required([:ap_id, :nickname, :local, :data])
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_by_nickanme(nickname :: String.t()) :: t() | nil
|
@spec get_by_nickname(nickname :: String.t()) :: t() | nil
|
||||||
def get_by_nickanme(nickname) do
|
def get_by_nickname(nickname) do
|
||||||
Repo.one(from a in __MODULE__, where: a.nickname == ^nickname)
|
Repo.one(from a in __MODULE__, where: a.nickname == ^nickname)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,28 @@
|
||||||
defmodule ClacksWeb.ActorController do
|
defmodule ClacksWeb.ActorController do
|
||||||
use ClacksWeb, :controller
|
use ClacksWeb, :controller
|
||||||
alias Clacks.{Repo, Actor}
|
alias Clacks.Actor
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
def get(conn, %{"nickname" => nickname}) do
|
@context "https://www.w3.org/ns/activitystreams"
|
||||||
case Actor.get_by_nickanme(nickname) do
|
|
||||||
|
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)
|
||||||
|
|> halt()
|
||||||
|
|
||||||
|
actor ->
|
||||||
|
assign(conn, :actor, actor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_actor(conn, _opts), do: conn
|
||||||
|
|
||||||
|
def get(conn, _params) do
|
||||||
|
case conn.assigns[:actor] do
|
||||||
%Actor{local: true, data: data} ->
|
%Actor{local: true, data: data} ->
|
||||||
conn
|
conn
|
||||||
|> put_resp_header("content-type", "application/activity+json")
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|
@ -13,10 +31,56 @@ defmodule ClacksWeb.ActorController do
|
||||||
%Actor{local: false, ap_id: ap_id} ->
|
%Actor{local: false, ap_id: ap_id} ->
|
||||||
conn
|
conn
|
||||||
|> redirect(external: ap_id)
|
|> redirect(external: ap_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
_ ->
|
def followers(conn, %{"page" => page}) do
|
||||||
conn
|
{page, _} = Integer.parse(page)
|
||||||
|> put_status(404)
|
|
||||||
|
followers = conn.assigns[:actor].followers
|
||||||
|
|
||||||
|
data =
|
||||||
|
collection_page(conn, followers, page)
|
||||||
|
|> Map.put("@context", @context)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|
|> json(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def followers(conn, _params) do
|
||||||
|
%Actor{followers: followers} = conn.assigns[:actor]
|
||||||
|
|
||||||
|
data = %{
|
||||||
|
"@context" => @context,
|
||||||
|
"type" => "OrderedCollection",
|
||||||
|
"id" => current_url(conn, %{}),
|
||||||
|
"totalItems" => length(followers),
|
||||||
|
"first" => collection_page(conn, followers, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|
|> json(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp collection_page(conn, collection, page) do
|
||||||
|
chunks = Enum.chunk_every(collection, 20)
|
||||||
|
# page is 1 indexed, so subtract 1 to get the current chunk
|
||||||
|
current_chunk = Enum.at(chunks, page - 1)
|
||||||
|
|
||||||
|
data = %{
|
||||||
|
"type" => "OrderedCollectionPage",
|
||||||
|
"totalItems" => length(collection),
|
||||||
|
"partOf" => current_url(conn, %{}),
|
||||||
|
"id" => current_url(conn, %{page: page}),
|
||||||
|
"orderedItems" => current_chunk || []
|
||||||
|
}
|
||||||
|
|
||||||
|
if page < length(chunks) do
|
||||||
|
Map.put(data, "next", current_url(conn, %{page: page + 1}))
|
||||||
|
else
|
||||||
|
data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ defmodule ClacksWeb.WebFingerController do
|
||||||
|
|
||||||
def get(conn, %{"resource" => resource}) do
|
def get(conn, %{"resource" => resource}) do
|
||||||
with [_, nickname] <- Regex.run(@acct_regex, resource),
|
with [_, nickname] <- Regex.run(@acct_regex, resource),
|
||||||
%Actor{local: true} = actor <- Actor.get_by_nickanme(nickname) do
|
%Actor{local: true} = actor <- Actor.get_by_nickname(nickname) do
|
||||||
url = Application.get_env(:clacks, ClacksWeb.Endpoint)[:url]
|
url = Application.get_env(:clacks, ClacksWeb.Endpoint)[:url]
|
||||||
host = url[:host]
|
host = url[:host]
|
||||||
port = url[:port]
|
port = url[:port]
|
||||||
|
|
|
@ -21,7 +21,9 @@ defmodule ClacksWeb.Router do
|
||||||
pipe_through :activitypub
|
pipe_through :activitypub
|
||||||
|
|
||||||
get "/objects/:id", ObjectsController, :get
|
get "/objects/:id", ObjectsController, :get
|
||||||
|
|
||||||
get "/users/:nickname", ActorController, :get
|
get "/users/:nickname", ActorController, :get
|
||||||
|
get "/users/:nickname/followers", ActorController, :followers
|
||||||
|
|
||||||
post "/inbox", InboxController, :shared
|
post "/inbox", InboxController, :shared
|
||||||
post "/users/:nickname/inbox", InboxController, :user_specific
|
post "/users/:nickname/inbox", InboxController, :user_specific
|
||||||
|
|
Loading…
Reference in New Issue