stuff
This commit is contained in:
parent
97cf080d14
commit
de9afad553
|
@ -0,0 +1,4 @@
|
||||||
|
# Used by "mix format"
|
||||||
|
[
|
||||||
|
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||||
|
]
|
|
@ -0,0 +1,26 @@
|
||||||
|
# The directory Mix will write compiled artifacts to.
|
||||||
|
/_build/
|
||||||
|
|
||||||
|
# If you run "mix test --cover", coverage assets end up here.
|
||||||
|
/cover/
|
||||||
|
|
||||||
|
# The directory Mix downloads your dependencies sources to.
|
||||||
|
/deps/
|
||||||
|
|
||||||
|
# Where third-party dependencies like ExDoc output generated docs.
|
||||||
|
/doc/
|
||||||
|
|
||||||
|
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||||
|
/.fetch
|
||||||
|
|
||||||
|
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||||
|
erl_crash.dump
|
||||||
|
|
||||||
|
# Also ignore archive artifacts (built via "mix archive.build").
|
||||||
|
*.ez
|
||||||
|
|
||||||
|
# Ignore package tarball (built via "mix hex.build").
|
||||||
|
vonbraun-*.tar
|
||||||
|
|
||||||
|
# Temporary files, for example, from tests.
|
||||||
|
/tmp/
|
|
@ -0,0 +1,2 @@
|
||||||
|
elixir 1.17.2-otp-26
|
||||||
|
erlang 26.2.5.2
|
|
@ -0,0 +1,3 @@
|
||||||
|
import Config
|
||||||
|
|
||||||
|
import_config "#{Mix.env()}.exs"
|
|
@ -0,0 +1,9 @@
|
||||||
|
import Config
|
||||||
|
|
||||||
|
config :logger, level: :debug
|
||||||
|
|
||||||
|
config :vonbraun,
|
||||||
|
name: "Moon Man",
|
||||||
|
nickname: "moonman",
|
||||||
|
domain: "vonbraun.discontent.top",
|
||||||
|
summary: "I am the famous Fediverse Moon"
|
|
@ -0,0 +1,18 @@
|
||||||
|
defmodule Vonbraun do
|
||||||
|
@moduledoc """
|
||||||
|
Documentation for `Vonbraun`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Hello world.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> Vonbraun.hello()
|
||||||
|
:world
|
||||||
|
|
||||||
|
"""
|
||||||
|
def hello do
|
||||||
|
:world
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Vonbraun.Application do
|
||||||
|
# See https://hexdocs.pm/elixir/Application.html
|
||||||
|
# for more information on OTP Applications
|
||||||
|
@moduledoc false
|
||||||
|
|
||||||
|
use Application
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def start(_type, _args) do
|
||||||
|
children = [
|
||||||
|
{Bandit, scheme: :http, plug: Vonbraun.MyRouter, port: 4012}
|
||||||
|
]
|
||||||
|
|
||||||
|
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||||
|
# for other strategies and supported options
|
||||||
|
opts = [strategy: :one_for_one, name: Vonbraun.Supervisor]
|
||||||
|
Supervisor.start_link(children, opts)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Vonbraun.InboxRouter do
|
||||||
|
use Plug.Router
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
plug :match
|
||||||
|
plug :dispatch
|
||||||
|
|
||||||
|
get "/" do
|
||||||
|
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
||||||
|
|
||||||
|
if conn.params["user"] == nickname do
|
||||||
|
send_resp(conn, 200, "ok")
|
||||||
|
else
|
||||||
|
send_resp(conn, 404, "fuck off")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
defmodule Vonbraun.MyPlug do
|
||||||
|
import Plug.Conn
|
||||||
|
|
||||||
|
def init(options) do
|
||||||
|
# initialize options
|
||||||
|
options
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(conn, _opts) do
|
||||||
|
conn
|
||||||
|
|> put_resp_content_type("text/plain")
|
||||||
|
|> send_resp(200, "Hello world")
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,219 @@
|
||||||
|
defmodule Vonbraun.MyRouter do
|
||||||
|
use Plug.Router
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
alias Vonbraun.InboxRouter
|
||||||
|
|
||||||
|
plug :match
|
||||||
|
plug :dispatch
|
||||||
|
|
||||||
|
|
||||||
|
defp render_outbox(nickname, domain), do: """
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://#{domain}/schemas/litepub-0.1.jsonld",
|
||||||
|
{
|
||||||
|
"@language": "und"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"first": "https://#{domain}/users/#{nickname}/outbox?page=true",
|
||||||
|
"id": "https://#{domain}/users/#{nickname}/outbox",
|
||||||
|
"type": "OrderedCollection"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
defp render_outbox_page(nickname, domain), do: """
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://#{domain}/schemas/litepub-0.1.jsonld",
|
||||||
|
{
|
||||||
|
"@language": "und"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "https://#{domain}/users/#{nickname}/outbox?page=true",
|
||||||
|
"orderedItems": [
|
||||||
|
],
|
||||||
|
"partOf": "https://#{domain}/users/#{nickname}/outbox",
|
||||||
|
"type": "OrderedCollectionPage"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
get "/.well-known/webfinger" do
|
||||||
|
conn = Plug.Conn.fetch_query_params(conn)
|
||||||
|
|
||||||
|
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
||||||
|
domain = Application.fetch_env!(:vonbraun, :domain)
|
||||||
|
|
||||||
|
with {:resource, resource} when is_binary(resource) <- {:resource, conn.params["resource"]},
|
||||||
|
{:admin_user, true} <- {:admin_user, resource in ["acct:#{nickname}", "acct:#{nickname}@#{domain}", "https://#{domain}/users/#{nickname}"]} do
|
||||||
|
out = """
|
||||||
|
{
|
||||||
|
"subject": "acct:#{nickname}@#{domain}",
|
||||||
|
"aliases": [
|
||||||
|
"https://#{domain}/users/#{nickname}"
|
||||||
|
],
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"rel": "http://webfinger.net/rel/profile-page",
|
||||||
|
"type": "text/html",
|
||||||
|
"href": "https://#{domain}/users/#{nickname}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "self",
|
||||||
|
"type": "application/activity+json",
|
||||||
|
"href": "https://#{domain}/users/#{nickname}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
conn = Plug.Conn.put_resp_content_type(conn, "application/jrd+json")
|
||||||
|
send_resp(conn, 200, out)
|
||||||
|
else
|
||||||
|
{:resource, resource} ->
|
||||||
|
Logger.error("not a binary resource: #{resource}")
|
||||||
|
send_resp(conn, 404, "oops")
|
||||||
|
{:admin_user, false} ->
|
||||||
|
Logger.error("Bad user: #{conn.params["resource"]}")
|
||||||
|
send_resp(conn, 404, "oops")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
get "/users/:user" do
|
||||||
|
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
||||||
|
|
||||||
|
if conn.params["user"] == nickname do
|
||||||
|
domain = Application.fetch_env!(:vonbraun, :domain)
|
||||||
|
name = Application.fetch_env!(:vonbraun, :name)
|
||||||
|
summary = Application.fetch_env!(:vonbraun, :summary)
|
||||||
|
|
||||||
|
out = """
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://#{domain}/schemas/litepub-0.1.jsonld",
|
||||||
|
{
|
||||||
|
"@language": "und"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"alsoKnownAs": [],
|
||||||
|
"attachment": [],
|
||||||
|
"capabilities": {
|
||||||
|
"acceptsChatMessages": true
|
||||||
|
},
|
||||||
|
"discoverable": false,
|
||||||
|
"endpoints": {
|
||||||
|
"sharedInbox": "https://#{domain}/inbox"
|
||||||
|
},
|
||||||
|
"followers": "https://#{domain}/users/#{nickname}/followers",
|
||||||
|
"following": "https://#{domain}/users/#{nickname}/following",
|
||||||
|
"icon": {
|
||||||
|
"type": "Image",
|
||||||
|
"url": "https://#{domain}/icon.png"
|
||||||
|
},
|
||||||
|
"id": "https://#{domain}/users/#{nickname}",
|
||||||
|
"inbox": "https://#{domain}/users/#{nickname}/inbox",
|
||||||
|
"manuallyApprovesFollowers": false,
|
||||||
|
"name": "#{name}",
|
||||||
|
"outbox": "https://#{domain}/users/#{nickname}/outbox",
|
||||||
|
"preferredUsername": "#{nickname}",
|
||||||
|
"publicKey": {
|
||||||
|
"id": "https://#{domain}/users/#{nickname}#main-key",
|
||||||
|
"owner": "https://#{domain}/users/#{nickname}",
|
||||||
|
"publicKeyPem": ""
|
||||||
|
},
|
||||||
|
"summary": "#{summary}",
|
||||||
|
"tag": [],
|
||||||
|
"type": "Person",
|
||||||
|
"url": "https://#{domain}/users/#{nickname}",
|
||||||
|
"vcard:bday": null,
|
||||||
|
"webfinger": "acct:#{nickname}@#{domain}"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
conn = Plug.Conn.put_resp_content_type(conn, "application/activity+json")
|
||||||
|
send_resp(conn, 200, out)
|
||||||
|
else
|
||||||
|
send_resp(conn, 404, "not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/users/:user/following" do
|
||||||
|
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
||||||
|
|
||||||
|
if conn.params["user"] == nickname do
|
||||||
|
domain = Application.fetch_env!(:vonbraun, :domain)
|
||||||
|
|
||||||
|
out = """
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "https://#{domain}/users/#{nickname}/following",
|
||||||
|
"type": "OrderedCollection",
|
||||||
|
"totalItems": 0,
|
||||||
|
"orderedItems": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
conn = Plug.Conn.put_resp_content_type(conn, "application/activity+json")
|
||||||
|
send_resp(conn, 200, out)
|
||||||
|
else
|
||||||
|
send_resp(conn, 404, "not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/users/:user/followers" do
|
||||||
|
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
||||||
|
|
||||||
|
if conn.params["user"] == nickname do
|
||||||
|
domain = Application.fetch_env!(:vonbraun, :domain)
|
||||||
|
|
||||||
|
out = """
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "https://#{domain}/users/#{nickname}/followers",
|
||||||
|
"type": "OrderedCollection",
|
||||||
|
"totalItems": 0,
|
||||||
|
"orderedItems": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
conn = Plug.Conn.put_resp_content_type(conn, "application/activity+json")
|
||||||
|
send_resp(conn, 200, out)
|
||||||
|
else
|
||||||
|
send_resp(conn, 404, "not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/users/:user/outbox" do
|
||||||
|
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
||||||
|
domain = Application.fetch_env!(:vonbraun, :domain)
|
||||||
|
user = conn.params["user"]
|
||||||
|
|
||||||
|
conn = Plug.Conn.fetch_query_params(conn)
|
||||||
|
|
||||||
|
with {:user, ^nickname} <- {:user, user},
|
||||||
|
{:page, "true"} <- {:page, conn.params["page"]} do
|
||||||
|
conn = Plug.Conn.put_resp_content_type(conn, "application/activity+json")
|
||||||
|
send_resp(conn, 200, render_outbox_page(nickname, domain))
|
||||||
|
else
|
||||||
|
{:user, _} ->
|
||||||
|
send_resp(conn, 404, "fuck off")
|
||||||
|
|
||||||
|
{:page, _} ->
|
||||||
|
conn = Plug.Conn.put_resp_content_type(conn, "application/activity+json")
|
||||||
|
send_resp(conn, 200, render_outbox(nickname, domain))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
forward "/inbox", to: InboxRouter
|
||||||
|
forward "/users/:user/inbox", to: InboxRouter
|
||||||
|
|
||||||
|
match _ do
|
||||||
|
send_resp(conn, 404, "oops")
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
defmodule Vonbraun.MixProject do
|
||||||
|
use Mix.Project
|
||||||
|
|
||||||
|
def project do
|
||||||
|
[
|
||||||
|
app: :vonbraun,
|
||||||
|
version: "0.1.0",
|
||||||
|
elixir: "~> 1.17",
|
||||||
|
start_permanent: Mix.env() == :prod,
|
||||||
|
deps: deps()
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run "mix help compile.app" to learn about applications.
|
||||||
|
def application do
|
||||||
|
[
|
||||||
|
extra_applications: [:logger],
|
||||||
|
mod: {Vonbraun.Application, []}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run "mix help deps" to learn about dependencies.
|
||||||
|
defp deps do
|
||||||
|
[
|
||||||
|
{:bandit, "~> 1.5.7"}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
%{
|
||||||
|
"bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"},
|
||||||
|
"hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"},
|
||||||
|
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
|
||||||
|
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
|
||||||
|
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
|
||||||
|
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
|
||||||
|
"thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"},
|
||||||
|
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
ExUnit.start()
|
|
@ -0,0 +1,8 @@
|
||||||
|
defmodule VonbraunTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
doctest Vonbraun
|
||||||
|
|
||||||
|
test "greets the world" do
|
||||||
|
assert Vonbraun.hello() == :world
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue