Compare commits

...

2 Commits

Author SHA1 Message Date
Shadowfacts 0afe2d3b30
Slightly improve timestamps for old posts 2020-05-18 22:30:16 -04:00
Shadowfacts 4733aa23ab
Refacotr posting into separate module
This will make it easier to keep in sync creating posts from multiple
places (e.g. MastoAPI).
2020-05-18 22:27:08 -04:00
4 changed files with 82 additions and 37 deletions

View File

@ -89,6 +89,7 @@ defmodule Clacks.ActivityPub do
@spec synthesized_create(object :: map()) :: map() @spec synthesized_create(object :: map()) :: map()
def synthesized_create(object) do def synthesized_create(object) do
# todo: does this need to have an id field?
%{ %{
"@context" => @context, "@context" => @context,
"type" => "Create", "type" => "Create",

View File

@ -0,0 +1,60 @@
defmodule Clacks.UserActionsHelper do
alias Clacks.{User, Repo, Activity, Object, ActivityPub}
@public "https://www.w3.org/ns/activitystreams#Public"
@spec post_status(
author :: User.t(),
content :: String.t(),
in_reply_to :: String.t() | Activity.t() | nil
) :: {:ok, Activity.t()} | {:error, any()}
def post_status(author, content, in_reply_to_ap_id) when is_binary(in_reply_to_ap_id) do
case Activity.get_by_ap_id(in_reply_to_ap_id) do
nil ->
{:error, "Could find post to reply to with AP ID '#{in_reply_to_ap_id}'"}
in_reply_to ->
post_status(author, content, in_reply_to)
end
end
def post_status(author, content, in_reply_to) do
note = note_for_posting(author, content, in_reply_to)
note_changeset = Object.changeset_for_creating(note)
{:ok, _object} = Repo.insert(note_changeset)
%{"id" => ap_id} = create = ActivityPub.create(note)
case ActivityPub.Helper.save_and_federate(create, author.actor) do
{:ok, activity} ->
{:ok, activity}
:error ->
{:error, "Unable to save and federate activity with ID '#{ap_id}'"}
end
end
defp note_for_posting(author, content, %Activity{
data: %{"id" => in_reply_to_ap_id, "context" => context, "actor" => in_reply_to_actor}
}) do
to = [in_reply_to_actor, @public]
# todo: followers
cc = []
ActivityPub.note(
author.actor.ap_id,
content,
context,
in_reply_to_ap_id,
nil,
DateTime.utc_now(),
to,
cc
)
end
defp note_for_posting(author, content, _in_reply_to) do
ActivityPub.note(author.actor.ap_id, content)
end
end

View File

@ -1,6 +1,6 @@
defmodule ClacksWeb.FrontendController do defmodule ClacksWeb.FrontendController do
use ClacksWeb, :controller use ClacksWeb, :controller
alias Clacks.{Actor, User, Timeline, Repo, ActivityPub, Activity, Object} alias Clacks.{Actor, User, Timeline, Repo, ActivityPub, Activity, Object, UserActionsHelper}
alias ClacksWeb.Router.Helpers, as: Routes alias ClacksWeb.Router.Helpers, as: Routes
alias ClacksWeb.Endpoint alias ClacksWeb.Endpoint
import Ecto.Query import Ecto.Query
@ -251,47 +251,22 @@ defmodule ClacksWeb.FrontendController do
}) })
end end
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 = note_for_posting(current_user, params) UserActionsHelper.post_status(current_user, content, Map.get(params, "in_reply_to"))
note_changeset = Object.changeset_for_creating(note) |> case do
{:ok, _object} = Repo.insert(note_changeset) {:ok, activity} ->
path = Map.get(params, "continue", Routes.frontend_path(Endpoint, :status, activity.id))
redirect(conn, to: path)
create = ActivityPub.create(note) {:error, reason} ->
{:ok, activity} = ActivityPub.Helper.save_and_federate(create, current_user.actor) conn
|> put_flash(:error, "Unable to post status: #{inspect(reason)}")
path = Map.get(params, "continue", Routes.frontend_path(Endpoint, :status, activity.id)) |> redirect(to: Map.get(params, "continue", Routes.frontend_path(Endpoint, :index)))
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
end end
defp note_for_posting(current_user, %{"content" => content}) do
ActivityPub.note(current_user.actor.ap_id, content)
end
@spec follow_activity(follower :: Actor.t(), followee :: Actor.t()) :: map() @spec follow_activity(follower :: Actor.t(), followee :: Actor.t()) :: map()
def follow_activity(follower, followee) do def follow_activity(follower, followee) do
# todo: get latest # todo: get latest

View File

@ -46,8 +46,17 @@ defmodule ClacksWeb.FrontendView do
# less than a week, days # less than a week, days
"#{Integer.floor_div(diff, 60 * 60 * 24)}d" "#{Integer.floor_div(diff, 60 * 60 * 24)}d"
diff < 60 * 60 * 24 * 30 ->
# less than a month(ish), weeks
"#{Integer.floor_div(diff, 60 * 60 * 24 * 7)}wk"
diff < 60 * 60 * 24 * 365 ->
# less than a year, months(ish)
# todo: figure out actually how many months
"#{Integer.floor_div(diff, 60 * 60 * 24 * 30)}mo"
true -> true ->
Timex.format!(datetime, "%FT%T%:z", :strftime) Timex.format!(datetime, "%F", :strftime)
end end
end end