defmodule Pleroma.Web.MastodonAPI.StatusView do
use Pleroma.Web, :view
+ require Pleroma.Constants
+
alias Pleroma.Activity
alias Pleroma.HTML
alias Pleroma.Object
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1]
# TODO: Add cached version.
+ defp get_replied_to_activities([]), do: %{}
+
defp get_replied_to_activities(activities) do
activities
|> Enum.map(fn
- %{data: %{"type" => "Create", "object" => object}} ->
- object = Object.normalize(object)
- object.data["inReplyTo"] != "" && object.data["inReplyTo"]
+ %{data: %{"type" => "Create"}} = activity ->
+ object = Object.normalize(activity)
+ object && object.data["inReplyTo"] != "" && object.data["inReplyTo"]
_ ->
nil
end)
|> Enum.filter(& &1)
- |> Activity.create_by_object_ap_id()
+ |> Activity.create_by_object_ap_id_with_object()
|> Repo.all()
|> Enum.reduce(%{}, fn activity, acc ->
object = Object.normalize(activity)
- Map.put(acc, object.data["id"], activity)
+ if object, do: Map.put(acc, object.data["id"], activity), else: acc
end)
end
reblogged_activity =
Activity.create_by_object_ap_id(activity_object.data["id"])
|> Activity.with_preloaded_bookmark(opts[:for])
+ |> Activity.with_set_thread_muted_field(opts[:for])
|> Repo.one()
reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity))
id: to_string(activity.id),
uri: activity_object.data["id"],
url: activity_object.data["id"],
- account: AccountView.render("account.json", %{user: user}),
+ account: AccountView.render("account.json", %{user: user, for: opts[:for]}),
in_reply_to_id: nil,
in_reply_to_account_id: nil,
reblog: reblogged,
object = Object.normalize(activity)
user = get_user(activity.data["actor"])
+ user_follower_address = user.follower_address
like_count = object.data["like_count"] || 0
announcement_count = object.data["announcement_count"] || 0
tags = object.data["tag"] || []
sensitive = object.data["sensitive"] || Enum.member?(tags, "nsfw")
+ tag_mentions =
+ tags
+ |> Enum.filter(fn tag -> is_map(tag) and tag["type"] == "Mention" end)
+ |> Enum.map(fn tag -> tag["href"] end)
+
mentions =
- activity.recipients
- |> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end)
+ (object.data["to"] ++ tag_mentions)
+ |> Enum.uniq()
+ |> Enum.map(fn
+ Pleroma.Constants.as_public() -> nil
+ ^user_follower_address -> nil
+ ap_id -> User.get_cached_by_ap_id(ap_id)
+ end)
|> Enum.filter(& &1)
|> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end)
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 -> (opts[:for] && CommonAPI.thread_muted?(opts[:for], activity)) || false
+ end
+
attachment_data = object.data["attachment"] || []
attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
if user.local do
Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, activity)
else
- object.data["external_url"] || object.data["id"]
+ object.data["url"] || object.data["external_url"] || object.data["id"]
end
%{
id: to_string(activity.id),
uri: object.data["id"],
url: url,
- account: AccountView.render("account.json", %{user: user}),
+ account: AccountView.render("account.json", %{user: user, for: opts[:for]}),
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,
reblogged: reblogged?(activity, opts[:for]),
favourited: present?(favorited),
bookmarked: present?(bookmarked),
- muted: CommonAPI.thread_muted?(user, activity) || User.mutes?(opts[:for], user),
+ muted: thread_muted? || User.mutes?(opts[:for], user),
pinned: pinned?(activity, user),
sensitive: sensitive,
spoiler_text: summary_html,
provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
url: page_url,
image: image_url |> MediaProxy.url(),
- title: rich_media[:title],
- description: rich_media[:description],
+ title: rich_media[:title] || "",
+ description: rich_media[:description] || "",
pleroma: %{
opengraph: rich_media
}
}
end
- # TODO: Add tests for this view
def render("poll.json", %{object: object} = opts) do
{multiple, options} =
case object.data do
(object.data["closed"] || object.data["endTime"])
|> NaiveDateTime.from_iso8601!()
- votes_count = object.data["votes_count"] || 0
-
expired =
end_time
|> NaiveDateTime.compare(NaiveDateTime.utc_now())
_ -> false
end
- options =
- Enum.map(options, fn %{"name" => name} = option ->
- name =
- HTML.filter_tags(
- name,
- User.html_filter_policy(opts[:for])
- )
+ voted =
+ if opts[:for] do
+ existing_votes =
+ Pleroma.Web.ActivityPub.Utils.get_existing_votes(opts[:for].ap_id, object)
+
+ existing_votes != [] or opts[:for].ap_id == object.data["actor"]
+ else
+ false
+ end
+
+ {options, votes_count} =
+ Enum.map_reduce(options, 0, fn %{"name" => name} = option, count ->
+ current_count = option["replies"]["totalItems"] || 0
- %{title: name, votes_count: option["replies"]["votes_count"] || 0}
+ {%{
+ title: HTML.strip_tags(name),
+ votes_count: current_count
+ }, current_count + count}
end)
%{
- # Mastodon uses separate ids for polls, but an object can't have more than one poll embedded so object id is fine
- id: object.id,
+ # Mastodon uses separate ids for polls, but an object can't have
+ # more than one poll embedded so object id is fine
+ id: to_string(object.id),
expires_at: Utils.to_masto_date(end_time),
expired: expired,
multiple: multiple,
votes_count: votes_count,
options: options,
- voted: false,
+ voted: voted,
emojis: build_emojis(object.data["emoji"])
}
else