defmodule GitGud.Federation.ActorJSON do
@moduledoc """
Renders an `Actor` as ActivityStreams + ForgeFed JSON-LD.
Output content type:
application/activity+json
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
Spec contexts:
* `https://www.w3.org/ns/activitystreams` — base AP
* `https://w3id.org/security/v1` — public key
* `https://forgefed.org/ns` — repo extensions
"""
alias GitGud.Federation.Actor
@context [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
"https://forgefed.org/ns"
]
def render(%Actor{} = actor) do
%{
"@context" => @context,
"id" => actor.actor_url,
"type" => actor.actor_type,
"preferredUsername" => actor.preferred_username,
"name" => actor.name,
"summary" => actor.summary,
"inbox" => actor.inbox_url,
"outbox" => actor.outbox_url,
"followers" => actor.followers_url,
"following" => actor.following_url,
"endpoints" => endpoints(actor),
"publicKey" => %{
"id" => actor.public_key_id,
"owner" => actor.actor_url,
"publicKeyPem" => actor.public_key_pem
}
}
|> Map.merge(extras_for(actor))
|> drop_nils()
end
# ForgeFed extension: Group actors advertise their `repositories`
# collection so remote clients can enumerate without scraping HTML.
defp extras_for(%Actor{actor_type: "Group", actor_url: url}),
do: %{"repositories" => url <> "/repositories"}
defp extras_for(_), do: %{}
defp endpoints(%Actor{shared_inbox_url: nil}), do: nil
defp endpoints(%Actor{shared_inbox_url: u}), do: %{"sharedInbox" => u}
defp drop_nils(map) do
map
|> Enum.reject(fn {_, v} -> is_nil(v) end)
|> Map.new()
end
end
1.8 KiB · text
5af55d9