defmodule NullaWeb.InboxController do use NullaWeb, :controller alias Nulla.ActivityPub alias Nulla.Snowflake alias Nulla.HTTPSignature alias Nulla.Utils alias Nulla.Models.Actor alias Nulla.Models.Relation alias Nulla.Models.Activity def inbox(conn, %{ "id" => _create_id, "type" => "Create", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _read_id, "type" => "Read", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _update_id, "type" => "Update", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _delete_id, "type" => "Delete", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _add_id, "type" => "Add", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _view_id, "type" => "View", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _move_id, "type" => "Move", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _undo_id, "type" => "Undo", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => follow_id, "type" => "Follow", "actor" => actor_uri, "object" => target_uri }) do accept_id = Snowflake.next_id() with local_actor <- Actor.get_actor(ap_id: target_uri), {:ok, remote_actor_json} <- Utils.fetch_remote_actor(actor_uri), :ok <- HTTPSignature.verify(conn, remote_actor_json["publicKey"]["publicKeyPem"]), {:ok, remote_actor} <- Actor.get_or_create_actor(remote_actor_json), {:ok, follow_activity} <- Activity.create_activity(%{ ap_id: follow_id, type: "Follow", actor: remote_actor.ap_id, object: target_uri }), {:ok, accept_activity} <- Activity.create_activity(%{ id: accept_id, ap_id: "https://#{local_actor.domain}/activities/accept/#{accept_id}", type: "Accept", actor: local_actor.ap_id, object: Jason.encode!(follow_activity) }), {:ok, _relation} <- Relation.get_or_create_relation(local_actor.id, remote_actor.id, followed_by: true) do activity = %Activity{accept_activity | object: Jason.decode!(accept_activity.object)} body = Jason.encode!(ActivityPub.activity(activity)) headers = HTTPSignature.make_headers(body, remote_actor_json["inbox"], local_actor) request = Finch.build(:post, remote_actor_json["inbox"], headers, body) case Finch.request(request, Nulla.Finch) do {:ok, %Finch.Response{status: code}} when code in 200..299 -> IO.puts("Accept delivered successfully") :ok {:ok, %Finch.Response{status: code, body: resp}} -> IO.inspect({:error, code, resp}, label: "Failed to deliver Accept") {:error, {:http_error, code}} {:error, reason} -> IO.inspect(reason, label: "Finch delivery failed") {:error, reason} end send_resp(conn, 200, "") else error -> IO.inspect(error, label: "Follow error") json(conn, %{"error" => "Failed to process Follow"}) end end def inbox(conn, %{ "id" => _accept_id, "type" => "Accept", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _reject_id, "type" => "Reject", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _block_id, "type" => "Block", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _join_id, "type" => "Join", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _leave_id, "type" => "Leave", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _like_id, "type" => "Like", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _dislike_id, "type" => "Dislike", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _announce_id, "type" => "Announce", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, %{ "id" => _question_id, "type" => "Question", "actor" => _actor_uri, "object" => _target_uri }) do send_resp(conn, 200, "") end def inbox(conn, _params) do send_resp(conn, 400, "") end end