feat: Send follow requests
This commit is contained in:
parent
1259d3202d
commit
90a158c380
5 changed files with 73 additions and 7 deletions
|
|
@ -1,2 +1,15 @@
|
||||||
defmodule ActivityPub do
|
defmodule ActivityPub do
|
||||||
|
def fetch_actor(actor_id) do
|
||||||
|
request =
|
||||||
|
Req.new(url: actor_id)
|
||||||
|
|> Req.Request.put_header("accept", "application/json")
|
||||||
|
|
||||||
|
case Req.get(request) do
|
||||||
|
{:ok, result} ->
|
||||||
|
{:ok, result.body}
|
||||||
|
|
||||||
|
error ->
|
||||||
|
error
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,9 @@ defmodule ActivityPub.Headers do
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_actor_key(key_id) do
|
def fetch_actor_key(key_id) do
|
||||||
request =
|
case ActivityPub.fetch_actor(key_id) do
|
||||||
Req.new(url: key_id)
|
{:ok, body} ->
|
||||||
|> Req.Request.put_header("accept", "application/json")
|
key_map = body["publicKey"]
|
||||||
|
|
||||||
case Req.get(request) do
|
|
||||||
{:ok, result} ->
|
|
||||||
key_map = result.body["publicKey"]
|
|
||||||
|
|
||||||
if key_map["id"] == key_id do
|
if key_map["id"] == key_id do
|
||||||
[public_key | _] =
|
[public_key | _] =
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
defmodule Postland.Activities do
|
defmodule Postland.Activities do
|
||||||
use Phoenix.VerifiedRoutes, endpoint: PostlandWeb.Endpoint, router: PostlandWeb.Router
|
use Phoenix.VerifiedRoutes, endpoint: PostlandWeb.Endpoint, router: PostlandWeb.Router
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
alias Postland.Activity
|
alias Postland.Activity
|
||||||
alias Postland.Repo
|
alias Postland.Repo
|
||||||
|
alias Postland.Follows
|
||||||
|
|
||||||
def process_activity(params) do
|
def process_activity(params) do
|
||||||
case record_activity(params) do
|
case record_activity(params) do
|
||||||
|
|
@ -20,6 +23,20 @@ defmodule Postland.Activities do
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cause_effects(%Activity{actor_id: actor_id, type: "Accept", data: %{"object" => %{"type" => "Follow"}}} = activity) do
|
||||||
|
case Follows.get(Postland.my_actor_id(), actor_id) do
|
||||||
|
nil ->
|
||||||
|
Logger.warning("Got accept for a follow we don't have in the db: #{actor_id}")
|
||||||
|
|
||||||
|
{:ok, activity}
|
||||||
|
|
||||||
|
request ->
|
||||||
|
Follows.confirm_request(request)
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, activity}
|
||||||
|
end
|
||||||
|
|
||||||
def cause_effects(%Activity{actor_id: actor_id, type: "Follow", data: %{"object" => object}} = activity) do
|
def cause_effects(%Activity{actor_id: actor_id, type: "Follow", data: %{"object" => object}} = activity) do
|
||||||
if object == Postland.my_actor_id() do
|
if object == Postland.my_actor_id() do
|
||||||
case Postland.Follows.record_inbound_request(actor_id) do
|
case Postland.Follows.record_inbound_request(actor_id) do
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ defmodule Postland.Follow do
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@primary_key false
|
||||||
schema "follows" do
|
schema "follows" do
|
||||||
field :follower, :string, primary_key: true
|
field :follower, :string, primary_key: true
|
||||||
field :followee, :string, primary_key: true
|
field :followee, :string, primary_key: true
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,47 @@
|
||||||
defmodule Postland.Follows do
|
defmodule Postland.Follows do
|
||||||
|
use Phoenix.VerifiedRoutes, endpoint: PostlandWeb.Endpoint, router: PostlandWeb.Router
|
||||||
|
|
||||||
import Ecto.Query, warn: false
|
import Ecto.Query, warn: false
|
||||||
|
|
||||||
|
alias Postland.Accounts
|
||||||
alias Postland.Follow
|
alias Postland.Follow
|
||||||
alias Postland.Repo
|
alias Postland.Repo
|
||||||
|
alias ActivityPub.Headers
|
||||||
|
|
||||||
|
alias Ecto.Multi
|
||||||
|
|
||||||
|
def record_and_send_follow_request(to_actor_id) do
|
||||||
|
Multi.new()
|
||||||
|
|> Multi.run(:follow_record, fn _data, _repo -> record_outbound_request(to_actor_id) end)
|
||||||
|
|> Multi.run(:send_request, fn _data, _repo ->
|
||||||
|
send_follow_request(to_actor_id)
|
||||||
|
end)
|
||||||
|
|> Repo.transaction()
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_follow_request(to_actor_id) do
|
||||||
|
encoded_followee = Base.url_encode64(to_actor_id)
|
||||||
|
encoded_follower = Base.url_encode64(Postland.my_actor_id())
|
||||||
|
|
||||||
|
actor = ActivityPub.fetch_actor(to_actor_id)
|
||||||
|
inbox = Map.get(actor, "inbox")
|
||||||
|
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!()
|
||||||
|
|
||||||
|
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()
|
||||||
|
end
|
||||||
|
|
||||||
def pending_inbound_requests() do
|
def pending_inbound_requests() do
|
||||||
my_actor_id = Postland.my_actor_id()
|
my_actor_id = Postland.my_actor_id()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue