diff --git a/lib/activity_pub.ex b/lib/activity_pub.ex index ef64556..d3b7639 100644 --- a/lib/activity_pub.ex +++ b/lib/activity_pub.ex @@ -1,15 +1,31 @@ defmodule ActivityPub do + def get(url, actor_url, private_key) do + headers = ActivityPub.Headers.signing_headers("GET", url, "", actor_url, private_key) + + Req.new(url: url) + |> Req.Request.put_header("accept", "application/activity+json") + |> Req.Request.put_headers(headers) + |> Req.get() + |> case do + {:ok, response} -> + {:ok, response.body} + + other -> + other + end + end + def fetch_actor(actor_id) do - request = - Req.new(url: actor_id) - |> Req.Request.put_header("accept", "application/json") + request = + Req.new(url: actor_id) + |> Req.Request.put_header("accept", "application/json") - case Req.get(request) do - {:ok, result} -> - {:ok, result.body} + case Req.get(request) do + {:ok, result} -> + {:ok, result.body} - error -> - error - end + error -> + error + end end end diff --git a/lib/activity_pub/webfinger.ex b/lib/activity_pub/webfinger.ex new file mode 100644 index 0000000..613a49a --- /dev/null +++ b/lib/activity_pub/webfinger.ex @@ -0,0 +1,22 @@ +defmodule ActivityPub.Webfinger do + def lookup_resource(acct_handle) do + [_handle, domain] = String.split(acct_handle, "@") + + uri = %URI{ + scheme: "https", + authority: domain, + host: domain, + port: 443, + path: "/.well-known/webfinger", + query: "resource=acct:#{acct_handle}" + } + + case Req.get(uri) do + {:ok, response} -> + {:ok, response.body} + + other -> + other + end + end +end diff --git a/lib/postland/follows.ex b/lib/postland/follows.ex index 6903534..404539b 100644 --- a/lib/postland/follows.ex +++ b/lib/postland/follows.ex @@ -43,14 +43,27 @@ defmodule Postland.Follows do } |> Jason.encode!() - headers = Headers.signing_headers("POST", inbox, body, Postland.my_actor_id(), Accounts.solo_user().private_key) + headers = + Headers.signing_headers( + "POST", + inbox, + body, + Postland.my_actor_id(), + Accounts.solo_user().private_key + ) Req.post(inbox, headers: headers, body: body) end end def get_follow_activity(follower) do - from(a in Activity, where: a.type == "Follow", where: a.actor_id == ^follower, limit: 1, order_by: [desc: :inserted_at]) |> Repo.one() + from(a in Activity, + where: a.type == "Follow", + where: a.actor_id == ^follower, + limit: 1, + order_by: [desc: :inserted_at] + ) + |> Repo.one() end def record_and_send_follow_request(to_actor_id) do @@ -60,6 +73,19 @@ defmodule Postland.Follows do send_follow_request(to_actor_id) end) |> Repo.transaction() + |> case do + {:ok, %{follow_record: follow_record}} = result -> + Phoenix.PubSub.broadcast( + Postland.PubSub, + "follows:#{to_actor_id}", + {:update, follow_record} + ) + + result + + other -> + other + end end def send_follow_request(to_actor_id) do @@ -68,22 +94,32 @@ defmodule Postland.Follows do {:ok, actor} = ActivityPub.fetch_actor(to_actor_id) inbox = Map.get(actor, "inbox") - follow_request = %{ + + follow_request = + %{ "@context" => "https://www.w3.org/ns/activitystreams", "id" => url(~p"/follows/#{encoded_followee}/#{encoded_follower}"), "type" => "Follow", "actor" => Postland.my_actor_id(), "object" => to_actor_id - } - |> Jason.encode!() + } + |> Jason.encode!() - headers = Headers.signing_headers("POST", inbox, follow_request, Postland.my_actor_id(), Accounts.solo_user().private_key) + headers = + Headers.signing_headers( + "POST", + inbox, + follow_request, + Postland.my_actor_id(), + Accounts.solo_user().private_key + ) Req.post(inbox, headers: headers, body: follow_request) end def get(follower, followee) do - from(f in Follow, where: f.followee == ^followee, where: f.follower == ^follower) |> Repo.one() + from(f in Follow, where: f.followee == ^followee, where: f.follower == ^follower) + |> Repo.one() end def pending_inbound_requests() do @@ -109,5 +145,9 @@ defmodule Postland.Follows do request |> Follow.confirm_changeset() |> Repo.update() + |> case do + {:ok, follow} -> + Phoenix.PubSub.broadcast(Postland.PubSub, "follows:#{follow.followee}", {:update, follow}) + end end end diff --git a/lib/postland_web/controllers/export_controller.ex b/lib/postland_web/controllers/export_controller.ex index 1ab1acb..4552c86 100644 --- a/lib/postland_web/controllers/export_controller.ex +++ b/lib/postland_web/controllers/export_controller.ex @@ -9,7 +9,7 @@ defmodule PostlandWeb.ExportController do files = [filename, "#{filename}-shm", "#{filename}-wal"] |> Enum.map(&String.to_charlist/1) zip_path = Path.join([File.cwd!(), "priv", "tmp", "db-export.zip"]) - :zip.create(zip_path, files, cwd: dirname) + :zip.create(String.to_charlist(zip_path), files, cwd: dirname) send_download(conn, {:file, zip_path}, filename: "db-export.zip") end diff --git a/lib/postland_web/live/other_profile_live.ex b/lib/postland_web/live/other_profile_live.ex new file mode 100644 index 0000000..e4b8b10 --- /dev/null +++ b/lib/postland_web/live/other_profile_live.ex @@ -0,0 +1,77 @@ +defmodule PostlandWeb.OtherProfileLive do + use PostlandWeb, :live_view + + alias Postland.Follows + + def render(assigns) do + ~H""" +