diff options
Diffstat (limited to 'lib/pleroma/web/common_api')
-rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 58 | ||||
-rw-r--r-- | lib/pleroma/web/common_api/utils.ex | 122 |
2 files changed, 112 insertions, 68 deletions
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 0f84542f0..14a68929d 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -1,5 +1,5 @@ defmodule Pleroma.Web.CommonAPI do - alias Pleroma.{Repo, Activity, Object, User} + alias Pleroma.{Repo, Activity, Object} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Formatter @@ -8,7 +8,7 @@ defmodule Pleroma.Web.CommonAPI do def delete(activity_id, user) do with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id), %Object{} = object <- Object.get_by_ap_id(object_id), - true <- user.info["is_moderator"] || (user.ap_id == object.data["actor"]), + true <- user.info["is_moderator"] || user.ap_id == object.data["actor"], {:ok, delete} <- ActivityPub.delete(object) do {:ok, delete} end @@ -46,17 +46,22 @@ defmodule Pleroma.Web.CommonAPI do end end - def get_visibility(%{"visibility" => visibility}), do: visibility - def get_visibility(%{"in_reply_to_status_id" => status_id}) when status_id do + def get_visibility(%{"visibility" => visibility}) + when visibility in ~w{public unlisted private direct}, + do: visibility + + def get_visibility(%{"in_reply_to_status_id" => status_id}) when not is_nil(status_id) do inReplyTo = get_replied_to_activity(status_id) Pleroma.Web.MastodonAPI.StatusView.get_visibility(inReplyTo.data["object"]) end + def get_visibility(_), do: "public" @instance Application.get_env(:pleroma, :instance) @limit Keyword.get(@instance, :limit) def post(user, %{"status" => status} = data) do visibility = get_visibility(data) + with status <- String.trim(status), length when length in 1..@limit <- String.length(status), attachments <- attachments_from_ids(data["media_ids"]), @@ -64,18 +69,51 @@ defmodule Pleroma.Web.CommonAPI do inReplyTo <- get_replied_to_activity(data["in_reply_to_status_id"]), {to, cc} <- to_for_user_and_mentions(user, mentions, inReplyTo, visibility), tags <- Formatter.parse_tags(status, data), - content_html <- make_content_html(status, mentions, attachments, tags, data["no_attachment_links"]), + content_html <- + make_content_html(status, mentions, attachments, tags, data["no_attachment_links"]), context <- make_context(inReplyTo), cw <- data["spoiler_text"], - object <- make_note_data(user.ap_id, to, context, content_html, attachments, inReplyTo, tags, cw, cc), - object <- Map.put(object, "emoji", Formatter.get_emoji(status) |> Enum.reduce(%{}, fn({name, file}, acc) -> Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url}#{file}") end)) do - res = ActivityPub.create(%{to: to, actor: user, context: context, object: object, additional: %{"cc" => cc}}) - User.increase_note_count(user) + object <- + make_note_data( + user.ap_id, + to, + context, + content_html, + attachments, + inReplyTo, + tags, + cw, + cc + ), + object <- + Map.put( + object, + "emoji", + Formatter.get_emoji(status) + |> Enum.reduce(%{}, fn {name, file}, acc -> + Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url()}#{file}") + end) + ) do + res = + ActivityPub.create(%{ + to: to, + actor: user, + context: context, + object: object, + additional: %{"cc" => cc} + }) + res end end def update(user) do - ActivityPub.update(%{local: true, to: [user.follower_address], cc: [], actor: user.ap_id, object: Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user})}) + ActivityPub.update(%{ + local: true, + to: [user.follower_address], + cc: [], + actor: user.ap_id, + object: Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user}) + }) end end diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 75c63e5f4..57f8be894 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -1,11 +1,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do - alias Pleroma.{Repo, Object, Formatter, User, Activity} + alias Pleroma.{Repo, Object, Formatter, Activity} alias Pleroma.Web.ActivityPub.Utils alias Calendar.Strftime # This is a hack for twidere. def get_by_id_or_ap_id(id) do activity = Repo.get(Activity, id) || Activity.get_create_activity_by_object_ap_id(id) + if activity.data["type"] == "Create" do activity else @@ -16,10 +17,11 @@ defmodule Pleroma.Web.CommonAPI.Utils do def get_replied_to_activity(id) when not is_nil(id) do Repo.get(Activity, id) end + def get_replied_to_activity(_), do: nil def attachments_from_ids(ids) do - Enum.map(ids || [], fn (media_id) -> + Enum.map(ids || [], fn media_id -> Repo.get(Object, media_id).data end) end @@ -27,8 +29,9 @@ defmodule Pleroma.Web.CommonAPI.Utils do def to_for_user_and_mentions(user, mentions, inReplyTo, "public") do to = ["https://www.w3.org/ns/activitystreams#Public"] - mentioned_users = Enum.map(mentions, fn ({_, %{ap_id: ap_id}}) -> ap_id end) + mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) cc = [user.follower_address | mentioned_users] + if inReplyTo do {to, Enum.uniq([inReplyTo.data["actor"] | cc])} else @@ -46,8 +49,9 @@ defmodule Pleroma.Web.CommonAPI.Utils do {[user.follower_address | to], cc} end - def to_for_user_and_mentions(user, mentions, inReplyTo, "direct") do - mentioned_users = Enum.map(mentions, fn ({_, %{ap_id: ap_id}}) -> ap_id end) + def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do + mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) + if inReplyTo do {Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []} else @@ -57,77 +61,78 @@ defmodule Pleroma.Web.CommonAPI.Utils do def make_content_html(status, mentions, attachments, tags, no_attachment_links \\ false) do status + |> String.replace("\r", "") |> format_input(mentions, tags) |> maybe_add_attachments(attachments, no_attachment_links) end def make_context(%Activity{data: %{"context" => context}}), do: context - def make_context(_), do: Utils.generate_context_id + def make_context(_), do: Utils.generate_context_id() + + def maybe_add_attachments(text, _attachments, _no_links = true), do: text - def maybe_add_attachments(text, attachments, _no_links = true), do: text def maybe_add_attachments(text, attachments, _no_links) do add_attachments(text, attachments) end + def add_attachments(text, attachments) do - attachment_text = Enum.map(attachments, fn - (%{"url" => [%{"href" => href} | _]}) -> - name = URI.decode(Path.basename(href)) - "<a href=\"#{href}\" class='attachment'>#{shortname(name)}</a>" - _ -> "" - end) + attachment_text = + Enum.map(attachments, fn + %{"url" => [%{"href" => href} | _]} -> + name = URI.decode(Path.basename(href)) + "<a href=\"#{href}\" class='attachment'>#{shortname(name)}</a>" + + _ -> + "" + end) + Enum.join([text | attachment_text], "<br>") end - def format_input(text, mentions, _tags) do + def format_input(text, mentions, tags) do text - |> Formatter.html_escape - |> Formatter.linkify + |> Formatter.html_escape() |> String.replace("\n", "<br>") - |> add_user_links(mentions) - # |> add_tag_links(tags) + |> (&{[], &1}).() + |> Formatter.add_links() + |> Formatter.add_user_links(mentions) + |> Formatter.add_hashtag_links(tags) + |> Formatter.finalize() end def add_tag_links(text, tags) do - tags = tags - |> Enum.sort_by(fn ({tag, _}) -> -String.length(tag) end) + tags = + tags + |> Enum.sort_by(fn {tag, _} -> -String.length(tag) end) - Enum.reduce(tags, text, fn({full, tag}, text) -> - url = "#<a href='#{Pleroma.Web.base_url}/tag/#{tag}' rel='tag'>#{tag}</a>" + Enum.reduce(tags, text, fn {full, tag}, text -> + url = "#<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{tag}</a>" String.replace(text, full, url) end) end - def add_user_links(text, mentions) do - mentions = mentions - |> Enum.sort_by(fn ({name, _}) -> -String.length(name) end) - |> Enum.map(fn({name, user}) -> {name, user, Ecto.UUID.generate} end) - - # This replaces the mention with a unique reference first so it doesn't - # contain parts of other replaced mentions. There probably is a better - # solution for this... - step_one = mentions - |> Enum.reduce(text, fn ({match, _user, uuid}, text) -> - String.replace(text, match, uuid) - end) - - Enum.reduce(mentions, step_one, fn ({match, %User{ap_id: ap_id}, uuid}, text) -> - short_match = String.split(match, "@") |> tl() |> hd() - String.replace(text, uuid, "<span><a href='#{ap_id}'>@<span>#{short_match}</span></a></span>") - end) - end - - def make_note_data(actor, to, context, content_html, attachments, inReplyTo, tags, cw \\ nil, cc \\ []) do - object = %{ - "type" => "Note", - "to" => to, - "cc" => cc, - "content" => content_html, - "summary" => cw, - "context" => context, - "attachment" => attachments, - "actor" => actor, - "tag" => tags |> Enum.map(fn ({_, tag}) -> tag end) - } + def make_note_data( + actor, + to, + context, + content_html, + attachments, + inReplyTo, + tags, + cw \\ nil, + cc \\ [] + ) do + object = %{ + "type" => "Note", + "to" => to, + "cc" => cc, + "content" => content_html, + "summary" => cw, + "context" => context, + "attachment" => attachments, + "actor" => actor, + "tag" => tags |> Enum.map(fn {_, tag} -> tag end) + } if inReplyTo do object @@ -147,24 +152,25 @@ defmodule Pleroma.Web.CommonAPI.Utils do end def date_to_asctime(date) do - with {:ok, date, _offset} <- date |> DateTime.from_iso8601 do + with {:ok, date, _offset} <- date |> DateTime.from_iso8601() do format_asctime(date) - else _e -> + else + _e -> "" end end def to_masto_date(%NaiveDateTime{} = date) do date - |> NaiveDateTime.to_iso8601 + |> NaiveDateTime.to_iso8601() |> String.replace(~r/(\.\d+)?$/, ".000Z", global: false) end def to_masto_date(date) do try do date - |> NaiveDateTime.from_iso8601! - |> NaiveDateTime.to_iso8601 + |> NaiveDateTime.from_iso8601!() + |> NaiveDateTime.to_iso8601() |> String.replace(~r/(\.\d+)?$/, ".000Z", global: false) rescue _e -> "" |