Add replying to statuses
This commit is contained in:
parent
6c0fc06c21
commit
7d071d971c
|
@ -32,6 +32,7 @@ defmodule Clacks.ActivityPub do
|
||||||
actor :: String.t(),
|
actor :: String.t(),
|
||||||
html :: String.t(),
|
html :: String.t(),
|
||||||
context :: String.t() | nil,
|
context :: String.t() | nil,
|
||||||
|
in_reply_to :: String.t() | nil,
|
||||||
id :: String.t() | nil,
|
id :: String.t() | nil,
|
||||||
published :: DateTime.t(),
|
published :: DateTime.t(),
|
||||||
to :: [String.t()],
|
to :: [String.t()],
|
||||||
|
@ -41,6 +42,7 @@ defmodule Clacks.ActivityPub do
|
||||||
actor,
|
actor,
|
||||||
html,
|
html,
|
||||||
context \\ nil,
|
context \\ nil,
|
||||||
|
in_reply_to \\ nil,
|
||||||
id \\ nil,
|
id \\ nil,
|
||||||
published \\ DateTime.utc_now(),
|
published \\ DateTime.utc_now(),
|
||||||
to \\ [@public],
|
to \\ [@public],
|
||||||
|
@ -61,6 +63,7 @@ defmodule Clacks.ActivityPub do
|
||||||
"content" => html,
|
"content" => html,
|
||||||
"conversation" => context,
|
"conversation" => context,
|
||||||
"context" => context,
|
"context" => context,
|
||||||
|
"inReplyTo" => in_reply_to,
|
||||||
"published" => published |> DateTime.to_iso8601()
|
"published" => published |> DateTime.to_iso8601()
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,27 @@ defmodule ClacksWeb.ActivitiesController do
|
||||||
end
|
end
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
|
case conn.assigns[:format] do
|
||||||
|
"activity+json" ->
|
||||||
|
conn
|
||||||
|
|> put_status(404)
|
||||||
|
|> json(%{error: "Not Found"})
|
||||||
|
|
||||||
|
"html" ->
|
||||||
resp(conn, 404, "Not Found")
|
resp(conn, 404, "Not Found")
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -4,6 +4,8 @@ defmodule ClacksWeb.FrontendController do
|
||||||
alias ClacksWeb.Router.Helpers, as: Routes
|
alias ClacksWeb.Router.Helpers, as: Routes
|
||||||
alias ClacksWeb.Endpoint
|
alias ClacksWeb.Endpoint
|
||||||
|
|
||||||
|
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
def index(%Plug.Conn{assigns: %{user: user}} = conn, params) do
|
def index(%Plug.Conn{assigns: %{user: user}} = conn, params) do
|
||||||
user = Repo.preload(user, :actor)
|
user = Repo.preload(user, :actor)
|
||||||
|
|
||||||
|
@ -48,23 +50,67 @@ defmodule ClacksWeb.FrontendController do
|
||||||
|
|
||||||
with %Activity{
|
with %Activity{
|
||||||
local: true,
|
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: %{
|
data: %{
|
||||||
"type" => "Create",
|
"type" => "Create",
|
||||||
"object" => %{"type" => "Note", "attributedTo" => author_id} = note
|
"object" => %{"type" => "Note", "attributedTo" => author_id} = note
|
||||||
}
|
}
|
||||||
} <- Activity.get(id),
|
} <- Activity.get(id),
|
||||||
%Actor{} = author <- Actor.get_by_ap_id(author_id) do
|
%Actor{} = author <- Actor.get_by_ap_id(author_id) do
|
||||||
render(conn, "status.html", %{
|
render(conn, "reply.html", %{
|
||||||
current_user: current_user,
|
current_user: current_user,
|
||||||
note: note,
|
note: note,
|
||||||
author: author
|
author: author
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
nil ->
|
_ ->
|
||||||
put_status(conn, 404)
|
resp(conn, 404, "Not Found")
|
||||||
|
|
||||||
%Activity{local: false, data: %{"id" => ap_id}} ->
|
|
||||||
redirect(conn, external: ap_id)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -89,7 +135,7 @@ defmodule ClacksWeb.FrontendController do
|
||||||
def post_status(conn, %{"content" => content} = params) do
|
def post_status(conn, %{"content" => content} = params) do
|
||||||
current_user = conn.assigns[:user] |> Repo.preload(:actor)
|
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)
|
note_changeset = Object.changeset_for_creating(note)
|
||||||
{:ok, object} = Repo.insert(note_changeset)
|
{: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))
|
path = Map.get(params, "continue", Routes.frontend_path(Endpoint, :status, activity.id))
|
||||||
redirect(conn, to: path)
|
redirect(conn, to: path)
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -51,13 +51,13 @@ defmodule ClacksWeb.Router do
|
||||||
pipe_through :browser_maybe_authenticated
|
pipe_through :browser_maybe_authenticated
|
||||||
|
|
||||||
get "/", FrontendController, :index
|
get "/", FrontendController, :index
|
||||||
get "/status/:id", FrontendController, :status
|
|
||||||
post "/post", FrontendController, :post_status
|
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", ClacksWeb do
|
scope "/", ClacksWeb do
|
||||||
pipe_through :browser
|
pipe_through :browser
|
||||||
pipe_through :browser_authenticated
|
pipe_through :browser_authenticated
|
||||||
|
|
||||||
|
post "/post", FrontendController, :post_status
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", ClacksWeb do
|
scope "/", ClacksWeb do
|
||||||
|
@ -80,6 +80,7 @@ defmodule ClacksWeb.Router do
|
||||||
get "/users/:username", ActorController, :get
|
get "/users/:username", ActorController, :get
|
||||||
get "/activities/:id", ActivitiesController, :get
|
get "/activities/:id", ActivitiesController, :get
|
||||||
get "/objects/:id", ObjectsController, :get
|
get "/objects/:id", ObjectsController, :get
|
||||||
|
get "/status/:id", FrontendController, :status
|
||||||
end
|
end
|
||||||
|
|
||||||
# Other scopes may use custom stacks.
|
# Other scopes may use custom stacks.
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<%= @author.data["name"] %>
|
<%= @author.data["name"] %>
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
<a href="<%= @note["url"] %>">Permalink</a>
|
||||||
<div class="status-content">
|
<div class="status-content">
|
||||||
<%= @note["content"] %>
|
<%= @note["content"] %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1 +1,9 @@
|
||||||
<%= render "_status.html", author: @author, note: @note %>
|
<%= render "_status.html", author: @author, note: @note %>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<%= form_tag Routes.frontend_path(@conn, :post_status), method: :post do %>
|
||||||
|
<input type="hidden" name="in_reply_to" value="<%= @note["id"] %>">
|
||||||
|
<textarea id="content" name="content" cols="30" rows="10" placeholder="Reply"></textarea>
|
||||||
|
<%= submit "Post" %>
|
||||||
|
<% end %>
|
||||||
|
|
Loading…
Reference in New Issue