X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fmastodon_api%2Fviews%2Fstatus_view.ex;h=209119dd51a2268cc0e9b9f419856f595a762ec2;hb=ad5263c647aea65dbeb4c329825671895e0a8863;hp=b14ca9f5d65a59a4dab62b89868424182979486a;hpb=d3677d2b4d4d53619777509e0169bb0764213d39;p=akkoma diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index b14ca9f5d..84ab20a1c 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -7,19 +7,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do alias Pleroma.Activity alias Pleroma.HTML + alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User + alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI.Utils - alias Pleroma.Web.MediaProxy alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.StatusView + alias Pleroma.Web.MediaProxy + + import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1] # TODO: Add cached version. defp get_replied_to_activities(activities) do activities |> Enum.map(fn - %{data: %{"type" => "Create", "object" => %{"inReplyTo" => in_reply_to}}} -> - in_reply_to != "" && in_reply_to + %{data: %{"type" => "Create", "object" => object}} -> + object = Object.normalize(object) + object.data["inReplyTo"] != "" && object.data["inReplyTo"] _ -> nil @@ -28,7 +33,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do |> Activity.create_by_object_ap_id() |> Repo.all() |> Enum.reduce(%{}, fn activity, acc -> - Map.put(acc, activity.data["object"]["id"], activity) + object = Object.normalize(activity) + Map.put(acc, object.data["id"], activity) end) end @@ -45,6 +51,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do end end + defp get_context_id(%{data: %{"context_id" => context_id}}) when not is_nil(context_id), + do: context_id + + defp get_context_id(%{data: %{"context" => context}}) when is_binary(context), + do: Utils.context_to_conversation_id(context) + + defp get_context_id(_), do: nil + + defp reblogged?(activity, user) do + object = Object.normalize(activity) || %{} + present?(user && user.ap_id in (object.data["announcements"] || [])) + end + def render("index.json", opts) do replied_to_activities = get_replied_to_activities(opts.activities) @@ -58,13 +77,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do def render( "status.json", - %{activity: %{data: %{"type" => "Announce", "object" => object}} = activity} = opts + %{activity: %{data: %{"type" => "Announce", "object" => _object}} = activity} = opts ) do user = get_user(activity.data["actor"]) created_at = Utils.to_masto_date(activity.data["published"]) + activity_object = Object.normalize(activity) + + reblogged_activity = + Activity.create_by_object_ap_id(activity_object.data["id"]) + |> Activity.with_preloaded_bookmark(opts[:for]) + |> Repo.one() + + reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity)) + + favorited = opts[:for] && opts[:for].ap_id in (activity_object.data["likes"] || []) - reblogged = Activity.get_create_by_object_ap_id(object) - reblogged = render("status.json", Map.put(opts, :activity, reblogged)) + bookmarked = Activity.get_bookmark(reblogged_activity, opts[:for]) != nil mentions = activity.recipients @@ -74,8 +102,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do %{ id: to_string(activity.id), - uri: object, - url: object, + uri: activity_object.data["id"], + url: activity_object.data["id"], account: AccountView.render("account.json", %{user: user}), in_reply_to_id: nil, in_reply_to_account_id: nil, @@ -85,8 +113,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do reblogs_count: 0, replies_count: 0, favourites_count: 0, - reblogged: false, - favourited: false, + reblogged: reblogged?(reblogged_activity, opts[:for]), + favourited: present?(favorited), + bookmarked: present?(bookmarked), muted: false, pinned: pinned?(activity, user), sensitive: false, @@ -100,18 +129,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do website: nil }, language: nil, - emojis: [] + emojis: [], + pleroma: %{ + local: activity.local + } } end - def render("status.json", %{activity: %{data: %{"object" => object}} = activity} = opts) do + def render("status.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do + object = Object.normalize(activity) + user = get_user(activity.data["actor"]) - like_count = object["like_count"] || 0 - announcement_count = object["announcement_count"] || 0 + like_count = object.data["like_count"] || 0 + announcement_count = object.data["announcement_count"] || 0 - tags = object["tag"] || [] - sensitive = object["sensitive"] || Enum.member?(tags, "nsfw") + tags = object.data["tag"] || [] + sensitive = object.data["sensitive"] || Enum.member?(tags, "nsfw") mentions = activity.recipients @@ -119,50 +153,93 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do |> Enum.filter(& &1) |> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end) - repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || []) - favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || []) + favorited = opts[:for] && opts[:for].ap_id in (object.data["likes"] || []) + + bookmarked = Activity.get_bookmark(activity, opts[:for]) != nil + + thread_muted? = + case activity.thread_muted? do + thread_muted? when is_boolean(thread_muted?) -> thread_muted? + nil -> CommonAPI.thread_muted?(user, activity) + end - attachment_data = object["attachment"] || [] + attachment_data = object.data["attachment"] || [] attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment) - created_at = Utils.to_masto_date(object["published"]) + created_at = Utils.to_masto_date(object.data["published"]) reply_to = get_reply_to(activity, opts) + reply_to_user = reply_to && get_user(reply_to.data["actor"]) content = object |> render_content() - |> HTML.get_cached_scrubbed_html_for_object( + + content_html = + content + |> HTML.get_cached_scrubbed_html_for_activity( + User.html_filter_policy(opts[:for]), + activity, + "mastoapi:content" + ) + + content_plaintext = + content + |> HTML.get_cached_stripped_html_for_activity( + activity, + "mastoapi:content" + ) + + summary = object.data["summary"] || "" + + summary_html = + summary + |> HTML.get_cached_scrubbed_html_for_activity( User.html_filter_policy(opts[:for]), activity, - __MODULE__ + "mastoapi:summary" + ) + + summary_plaintext = + summary + |> HTML.get_cached_stripped_html_for_activity( + activity, + "mastoapi:summary" ) card = render("card.json", Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)) + url = + if user.local do + Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, activity) + else + object.data["external_url"] || object.data["id"] + end + %{ id: to_string(activity.id), - uri: object["id"], - url: object["external_url"] || object["id"], + uri: object.data["id"], + url: url, account: AccountView.render("account.json", %{user: user}), in_reply_to_id: reply_to && to_string(reply_to.id), in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id), reblog: nil, card: card, - content: content, + content: content_html, created_at: created_at, reblogs_count: announcement_count, - replies_count: 0, + replies_count: object.data["repliesCount"] || 0, favourites_count: like_count, - reblogged: present?(repeated), + reblogged: reblogged?(activity, opts[:for]), favourited: present?(favorited), - muted: false, + bookmarked: present?(bookmarked), + muted: thread_muted? || User.mutes?(opts[:for], user), pinned: pinned?(activity, user), sensitive: sensitive, - spoiler_text: object["summary"] || "", + spoiler_text: summary_html, visibility: get_visibility(object), - media_attachments: attachments |> Enum.take(4), + media_attachments: attachments, mentions: mentions, tags: build_tags(tags), application: %{ @@ -170,7 +247,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do website: nil }, language: nil, - emojis: build_emojis(activity.data["object"]["emoji"]) + emojis: build_emojis(object.data["emoji"]), + pleroma: %{ + local: activity.local, + conversation_id: get_context_id(activity), + in_reply_to_account_acct: reply_to_user && reply_to_user.nickname, + content: %{"text/plain" => content_plaintext}, + spoiler_text: %{"text/plain" => summary_plaintext} + } } end @@ -179,8 +263,25 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do end def render("card.json", %{rich_media: rich_media, page_url: page_url}) do - page_url = rich_media[:url] || page_url page_url_data = URI.parse(page_url) + + page_url_data = + if rich_media[:url] != nil do + URI.merge(page_url_data, URI.parse(rich_media[:url])) + else + page_url_data + end + + page_url = page_url_data |> to_string + + image_url = + if rich_media[:image] != nil do + URI.merge(page_url_data, URI.parse(rich_media[:image])) + |> to_string + else + nil + end + site_name = rich_media[:site_name] || page_url_data.host %{ @@ -188,9 +289,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do provider_name: site_name, provider_url: page_url_data.scheme <> "://" <> page_url_data.host, url: page_url, - image: rich_media[:image] |> MediaProxy.url(), - title: rich_media[:title], - description: rich_media[:description], + image: image_url |> MediaProxy.url(), + title: rich_media[:title] || "", + description: rich_media[:description] || "", pleroma: %{ opengraph: rich_media } @@ -223,66 +324,49 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do preview_url: href, text_url: href, type: type, - description: attachment["name"] + description: attachment["name"], + pleroma: %{mime_type: media_type} } end def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do - _id = activity.data["object"]["inReplyTo"] - replied_to_activities[activity.data["object"]["inReplyTo"]] - end + object = Object.normalize(activity) - def get_reply_to(%{data: %{"object" => object}}, _) do - if object["inReplyTo"] && object["inReplyTo"] != "" do - Activity.get_create_by_object_ap_id(object["inReplyTo"]) - else - nil + with nil <- replied_to_activities[object.data["inReplyTo"]] do + # If user didn't participate in the thread + Activity.get_in_reply_to_activity(activity) end end - def get_visibility(object) do - public = "https://www.w3.org/ns/activitystreams#Public" - to = object["to"] || [] - cc = object["cc"] || [] - - cond do - public in to -> - "public" + def get_reply_to(%{data: %{"object" => _object}} = activity, _) do + object = Object.normalize(activity) - public in cc -> - "unlisted" - - # this should use the sql for the object's activity - Enum.any?(to, &String.contains?(&1, "/followers")) -> - "private" - - length(cc) > 0 -> - "private" - - true -> - "direct" + if object.data["inReplyTo"] && object.data["inReplyTo"] != "" do + Activity.get_create_by_object_ap_id(object.data["inReplyTo"]) + else + nil end end - def render_content(%{"type" => "Video"} = object) do - with name when not is_nil(name) and name != "" <- object["name"] do - "

#{name}

#{object["content"]}" + def render_content(%{data: %{"type" => "Video"}} = object) do + with name when not is_nil(name) and name != "" <- object.data["name"] do + "

#{name}

#{object.data["content"]}" else - _ -> object["content"] || "" + _ -> object.data["content"] || "" end end - def render_content(%{"type" => object_type} = object) + def render_content(%{data: %{"type" => object_type}} = object) when object_type in ["Article", "Page"] do - with summary when not is_nil(summary) and summary != "" <- object["name"], - url when is_bitstring(url) <- object["url"] do - "

#{summary}

#{object["content"]}" + with summary when not is_nil(summary) and summary != "" <- object.data["name"], + url when is_bitstring(url) <- object.data["url"] do + "

#{summary}

#{object.data["content"]}" else - _ -> object["content"] || "" + _ -> object.data["content"] || "" end end - def render_content(object), do: object["content"] || "" + def render_content(object), do: object.data["content"] || "" @doc """ Builds a dictionary tags.