Merge pull request 'Mastodon API: add the quote entity to statuses' (#8035) from lambadalambda/pleroma:feature/mastodon-quote-entity into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8035
This commit is contained in:
commit
a019cb7466
4 changed files with 107 additions and 2 deletions
1
changelog.d/mastodon-quote-entity.add
Normal file
1
changelog.d/mastodon-quote-entity.add
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add the Mastodon quote entity (`quote` with `state` and `quoted_status`) to statuses, so Mastodon 4.4+ clients show quote posts
|
||||
|
|
@ -234,6 +234,29 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
|||
type: :integer,
|
||||
description: "How many statuses quoted this status."
|
||||
},
|
||||
quote: %Schema{
|
||||
type: :object,
|
||||
nullable: true,
|
||||
description:
|
||||
"The status being quoted, if any (Mastodon 4.4+). Quoted statuses only have `quoted_status_id`.",
|
||||
properties: %{
|
||||
state: %Schema{
|
||||
type: :string,
|
||||
enum: ["accepted", "unauthorized", "deleted"],
|
||||
description: "Whether the quoted status can be shown"
|
||||
},
|
||||
quoted_status: %Schema{
|
||||
allOf: [%OpenApiSpex.Reference{"$ref": "#/components/schemas/Status"}],
|
||||
nullable: true,
|
||||
description: "The quoted status, if it can be shown"
|
||||
},
|
||||
quoted_status_id: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "ID of the quoted status, if it can be shown"
|
||||
}
|
||||
}
|
||||
},
|
||||
reblog: %Schema{
|
||||
allOf: [%OpenApiSpex.Reference{"$ref": "#/components/schemas/Status"}],
|
||||
nullable: true,
|
||||
|
|
|
|||
|
|
@ -455,6 +455,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
language: get_language(object),
|
||||
emojis: build_emojis(object.data["emoji"]),
|
||||
quotes_count: object.data["quotesCount"] || 0,
|
||||
quote: build_quote(object, quote_activity, quote_post, opts),
|
||||
pleroma: %{
|
||||
local: activity.local,
|
||||
conversation_id: get_context_id(activity),
|
||||
|
|
@ -691,7 +692,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
%{ancestors: ancestors, descendants: descendants} =
|
||||
activities
|
||||
|> Enum.reverse()
|
||||
|> Enum.group_by(fn %{id: id} -> if id < activity.id, do: :ancestors, else: :descendants end)
|
||||
|> Enum.group_by(fn %{id: id} ->
|
||||
if id < activity.id, do: :ancestors, else: :descendants
|
||||
end)
|
||||
|> Map.put_new(:ancestors, [])
|
||||
|> Map.put_new(:descendants, [])
|
||||
|
||||
|
|
@ -742,6 +745,26 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
end
|
||||
end
|
||||
|
||||
# Mastodon (4.4+) quote entity. Quoted statuses get a shallow quote that only
|
||||
# has the id, as quotes are only rendered one level deep.
|
||||
defp build_quote(%Object{data: %{"quoteUrl" => url}}, quote_activity, quote_post, opts)
|
||||
when is_binary(url) and url != "" do
|
||||
state =
|
||||
cond do
|
||||
is_nil(quote_activity) -> "deleted"
|
||||
visible_for_user?(quote_activity, opts[:for]) -> "accepted"
|
||||
true -> "unauthorized"
|
||||
end
|
||||
|
||||
if opts[:show_quote] == false do
|
||||
%{state: state, quoted_status_id: if(state == "accepted", do: to_string(quote_activity.id))}
|
||||
else
|
||||
%{state: state, quoted_status: if(state == "accepted", do: quote_post)}
|
||||
end
|
||||
end
|
||||
|
||||
defp build_quote(_object, _quote_activity, _quote_post, _opts), do: nil
|
||||
|
||||
def get_quote(activity, %{quoted_activities: quoted_activities}) do
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
|
|
|
|||
|
|
@ -345,7 +345,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
bookmark_folder: nil,
|
||||
list_id: nil
|
||||
},
|
||||
quotes_count: 0
|
||||
quotes_count: 0,
|
||||
quote: nil
|
||||
}
|
||||
|
||||
assert status == expected
|
||||
|
|
@ -507,6 +508,63 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
refute status.pleroma.quote_visible
|
||||
end
|
||||
|
||||
describe "Mastodon quote entity" do
|
||||
test "a quote has the quoted status, and quoted statuses only a shallow quote" do
|
||||
post = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, quote_post} = CommonAPI.post(user, %{status: "he", quoted_status_id: post.id})
|
||||
|
||||
{:ok, quoted_quote_post} =
|
||||
CommonAPI.post(user, %{status: "yo", quoted_status_id: quote_post.id})
|
||||
|
||||
status = StatusView.render("show.json", %{activity: quoted_quote_post})
|
||||
|
||||
assert %{state: "accepted", quoted_status: %{id: quoted_id} = quoted} = status.quote
|
||||
assert quoted_id == to_string(quote_post.id)
|
||||
assert quoted.quote == %{state: "accepted", quoted_status_id: to_string(post.id)}
|
||||
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "a quote of a post the user cannot see is unauthorized" do
|
||||
user = insert(:user)
|
||||
private = insert(:followers_only_note_activity, user: user)
|
||||
|
||||
quote_private =
|
||||
insert(:note_activity,
|
||||
note: insert(:note, data: %{"quoteUrl" => Object.normalize(private).data["id"]})
|
||||
)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: quote_private})
|
||||
assert status.quote == %{state: "unauthorized", quoted_status: nil}
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
|
||||
follower = insert(:user)
|
||||
CommonAPI.follow(user, follower)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: quote_private, for: follower})
|
||||
assert %{state: "accepted", quoted_status: %{id: id}} = status.quote
|
||||
assert id == to_string(private.id)
|
||||
end
|
||||
|
||||
test "a quote of a missing post is deleted" do
|
||||
quote_missing =
|
||||
insert(:note_activity,
|
||||
note: insert(:note, data: %{"quoteUrl" => "https://example.com/objects/gone"})
|
||||
)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: quote_missing})
|
||||
assert status.quote == %{state: "deleted", quoted_status: nil}
|
||||
end
|
||||
|
||||
test "a post without a quote has no quote" do
|
||||
status = StatusView.render("show.json", %{activity: insert(:note_activity)})
|
||||
assert status.quote == nil
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
end
|
||||
|
||||
test "repost of quote post" do
|
||||
post = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue