From 7d071d971cc8b6529b59d4d5fdf291ea3be9ce9a Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Wed, 22 Apr 2020 22:54:46 -0400 Subject: [PATCH] Add replying to statuses --- lib/clacks/activitypub.ex | 3 + .../controllers/activities_controller.ex | 22 ++++- .../controllers/frontend_controller.ex | 87 +++++++++++++++++-- lib/clacks_web/router.ex | 5 +- .../templates/frontend/_status.html.eex | 1 + .../templates/frontend/status.html.eex | 8 ++ 6 files changed, 116 insertions(+), 10 deletions(-) diff --git a/lib/clacks/activitypub.ex b/lib/clacks/activitypub.ex index 579855c..1321790 100644 --- a/lib/clacks/activitypub.ex +++ b/lib/clacks/activitypub.ex @@ -32,6 +32,7 @@ defmodule Clacks.ActivityPub do actor :: String.t(), html :: String.t(), context :: String.t() | nil, + in_reply_to :: String.t() | nil, id :: String.t() | nil, published :: DateTime.t(), to :: [String.t()], @@ -41,6 +42,7 @@ defmodule Clacks.ActivityPub do actor, html, context \\ nil, + in_reply_to \\ nil, id \\ nil, published \\ DateTime.utc_now(), to \\ [@public], @@ -61,6 +63,7 @@ defmodule Clacks.ActivityPub do "content" => html, "conversation" => context, "context" => context, + "inReplyTo" => in_reply_to, "published" => published |> DateTime.to_iso8601() } end diff --git a/lib/clacks_web/controllers/activities_controller.ex b/lib/clacks_web/controllers/activities_controller.ex index 7d8c087..f14b5e7 100644 --- a/lib/clacks_web/controllers/activities_controller.ex +++ b/lib/clacks_web/controllers/activities_controller.ex @@ -18,7 +18,27 @@ defmodule ClacksWeb.ActivitiesController do end _ -> - resp(conn, 404, "Not Found") + case conn.assigns[:format] do + "activity+json" -> + conn + |> put_status(404) + |> json(%{error: "Not Found"}) + + "html" -> + resp(conn, 404, "Not Found") + end + end + end + + def get_status(conn, %{"id" => status_id}) do + case Activity.get(status_id) do + %Activity{local: true, data: data} -> + json(conn, data) + + _ -> + conn + |> put_status(404) + |> json(%{error: "Not Found"}) end end end diff --git a/lib/clacks_web/controllers/frontend_controller.ex b/lib/clacks_web/controllers/frontend_controller.ex index 67a48ae..2b3c02e 100644 --- a/lib/clacks_web/controllers/frontend_controller.ex +++ b/lib/clacks_web/controllers/frontend_controller.ex @@ -4,6 +4,8 @@ defmodule ClacksWeb.FrontendController do alias ClacksWeb.Router.Helpers, as: Routes alias ClacksWeb.Endpoint + @public "https://www.w3.org/ns/activitystreams#Public" + def index(%Plug.Conn{assigns: %{user: user}} = conn, params) do user = Repo.preload(user, :actor) @@ -48,23 +50,67 @@ defmodule ClacksWeb.FrontendController do with %Activity{ local: true, + data: + %{ + "type" => "Create", + "object" => %{"type" => "Note", "attributedTo" => author_id} = note + } = data + } <- Activity.get(id), + %Actor{} = author <- Actor.get_by_ap_id(author_id) do + case conn.assigns[:format] do + "activity+json" -> + json(conn, data) + + "html" -> + render(conn, "status.html", %{ + current_user: current_user, + note: note, + author: author + }) + end + else + nil -> + case conn.assigns[:format] do + "activity+json" -> + conn + |> put_status(404) + |> json(%{error: "Not Found"}) + + "html" -> + resp(conn, 404, "Not Found") + end + + %Activity{local: false, data: %{"id" => ap_id}} -> + case conn.assigns[:format] do + "activity+json" -> + conn + |> put_status(404) + |> json(%{error: "Not Found"}) + + "html" -> + redirect(conn, external: ap_id) + end + end + end + + def reply(conn, %{"id" => id}) do + current_user = conn.assigns[:user] + + with %Activity{ data: %{ "type" => "Create", "object" => %{"type" => "Note", "attributedTo" => author_id} = note } } <- Activity.get(id), %Actor{} = author <- Actor.get_by_ap_id(author_id) do - render(conn, "status.html", %{ + render(conn, "reply.html", %{ current_user: current_user, note: note, author: author }) else - nil -> - put_status(conn, 404) - - %Activity{local: false, data: %{"id" => ap_id}} -> - redirect(conn, external: ap_id) + _ -> + resp(conn, 404, "Not Found") end end @@ -89,7 +135,7 @@ defmodule ClacksWeb.FrontendController do def post_status(conn, %{"content" => content} = params) do current_user = conn.assigns[:user] |> Repo.preload(:actor) - note = ActivityPub.note(current_user.actor.ap_id, content) + note = note_for_posting(current_user, params) note_changeset = Object.changeset_for_creating(note) {:ok, object} = Repo.insert(note_changeset) @@ -104,4 +150,31 @@ defmodule ClacksWeb.FrontendController do path = Map.get(params, "continue", Routes.frontend_path(Endpoint, :status, activity.id)) redirect(conn, to: path) end + + defp note_for_posting(current_user, %{"content" => content, "in_reply_to" => in_reply_to_ap_id}) do + with %Activity{data: %{"context" => context, "actor" => in_reply_to_actor}} <- + Activity.get_by_ap_id(in_reply_to_ap_id) do + to = [in_reply_to_actor, @public] + # todo: followers + cc = [] + + ActivityPub.note( + current_user.actor.ap_id, + content, + context, + in_reply_to_ap_id, + nil, + DateTime.utc_now(), + to, + cc + ) + else + _ -> + ActivityPub.note(current_user.actor.ap_id, content) + end + end + + defp note_for_posting(current_user, %{"content" => content}) do + ActivityPub.note(current_user.actor.ap_id, content) + end end diff --git a/lib/clacks_web/router.ex b/lib/clacks_web/router.ex index e67d612..c34b852 100644 --- a/lib/clacks_web/router.ex +++ b/lib/clacks_web/router.ex @@ -51,13 +51,13 @@ defmodule ClacksWeb.Router do pipe_through :browser_maybe_authenticated get "/", FrontendController, :index - get "/status/:id", FrontendController, :status - post "/post", FrontendController, :post_status end scope "/", ClacksWeb do pipe_through :browser pipe_through :browser_authenticated + + post "/post", FrontendController, :post_status end scope "/", ClacksWeb do @@ -80,6 +80,7 @@ defmodule ClacksWeb.Router do get "/users/:username", ActorController, :get get "/activities/:id", ActivitiesController, :get get "/objects/:id", ObjectsController, :get + get "/status/:id", FrontendController, :status end # Other scopes may use custom stacks. diff --git a/lib/clacks_web/templates/frontend/_status.html.eex b/lib/clacks_web/templates/frontend/_status.html.eex index 58fb5f2..7bc9888 100644 --- a/lib/clacks_web/templates/frontend/_status.html.eex +++ b/lib/clacks_web/templates/frontend/_status.html.eex @@ -9,6 +9,7 @@ <%= @author.data["name"] %> + ">Permalink
<%= @note["content"] %>
diff --git a/lib/clacks_web/templates/frontend/status.html.eex b/lib/clacks_web/templates/frontend/status.html.eex index 0789470..44f42a1 100644 --- a/lib/clacks_web/templates/frontend/status.html.eex +++ b/lib/clacks_web/templates/frontend/status.html.eex @@ -1 +1,9 @@ <%= render "_status.html", author: @author, note: @note %> + +
+ +<%= form_tag Routes.frontend_path(@conn, :post_status), method: :post do %> + "> + + <%= submit "Post" %> +<% end %>