- Support for custom Elixir modules (such as MRF policies)
- User settings: Add _This account is a_ option.
- OAuth: admin scopes support (relevant setting: `[:auth, :enforce_oauth_admin_scope_usage]`).
+- ActivityPub: support for `replies` collection (output for outgoing federation & fetching on incoming federation).
<details>
<summary>API Changes</summary>
- Configuration: `feed.logo` option for tag feed.
- Tag feed: `/tags/:tag.rss` - list public statuses by hashtag.
- Mastodon API: Add `reacted` property to `emoji_reactions`
+- ActivityPub: `[:activitypub, :note_replies_output_limit]` setting sets the number of note self-replies to output on outgoing federation.
</details>
### Fixed
unfollow_blocked: true,
outgoing_blocks: true,
follow_handshake_timeout: 500,
+ note_replies_output_limit: 5,
sign_object_fetches: true
config :pleroma, :streamer,
config :pleroma, configurable_from_database: false
-config :pleroma, :mastodon_compatibility,
- # https://git.pleroma.social/pleroma/pleroma/issues/1505
- federated_note_replies_limit: 5
-
config :swarm, node_blacklist: [~r/myhtml_.*$/]
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
type: :boolean,
description: "Sign object fetches with HTTP signatures"
},
+ %{
+ key: :note_replies_output_limit,
+ type: :integer,
+ description:
+ "The number of Note replies' URIs to be included with outgoing federation (`5` to match Mastodon hardcoded value, `0` to disable the output)."
+ },
%{
key: :follow_handshake_timeout,
type: :integer,
}
]
},
- %{
- group: :pleroma,
- key: :mastodon_compatibility,
- type: :group,
- description: "Mastodon compatibility-related settings.",
- children: [
- %{
- key: :federated_note_replies_limit,
- type: :integer,
- description:
- "The number of Note self-reply URIs to be included with outgoing federation (`5` to mimic Mastodon hardcoded value, `0` to disable)."
- }
- ]
- },
%{
group: :pleroma,
type: :group,
Based on Mastodon's ActivityPub::NoteSerializer#replies.
"""
def set_replies(obj) do
- limit = Pleroma.Config.get([:mastodon_compatibility, :federated_note_replies_limit], 0)
+ limit = Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0)
replies_uris =
with true <- limit > 0 || nil,
end
def replies(%{"replies" => replies = %{}}) do
- replies = with %{} <- replies["first"], do: replies["first"], else: (_ -> replies)
+ replies =
+ if is_map(replies["first"]) do
+ replies["first"]
+ else
+ replies
+ end
+
replies["items"] || []
end
},
_job
) do
- Fetcher.fetch_object_from_id!(id)
+ {:ok, _object} = Fetcher.fetch_object_from_id(id)
end
end
end
end
- describe "handle_incoming:`replies` handling" do
+ describe "`replies` handling in handle_incoming/2" do
setup do
data =
File.read!("test/fixtures/mastodon-post-activity.json")
%{data: data, items: items, collection: collection}
end
- test "it schedules background fetching of wrapped `replies` collection items", %{
+ test "with wrapped `replies` collection, it schedules background fetching of items", %{
data: data,
items: items,
collection: collection
end
describe "set_replies/1" do
- clear_config([:mastodon_compatibility, :federated_note_replies_limit]) do
- Pleroma.Config.put([:mastodon_compatibility, :federated_note_replies_limit], 2)
+ clear_config([:activitypub, :note_replies_output_limit]) do
+ Pleroma.Config.put([:activitypub, :note_replies_output_limit], 2)
end
test "returns unmodified object if activity doesn't have self-replies" do
{:ok, self_reply2} =
CommonAPI.post(user, %{"status" => "self-reply 2", "in_reply_to_status_id" => id1})
- # Assuming to _not_ be present in `replies` due to :federated_note_replies_limit is set to 2
+ # Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
{:ok, _} =
CommonAPI.post(user, %{"status" => "self-reply 3", "in_reply_to_status_id" => id1})
assert result["@context"]
end
+ describe "note activity's `replies` collection rendering" do
+ clear_config([:activitypub, :note_replies_output_limit]) do
+ Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5)
+ end
+
+ test "renders `replies` collection for a note activity" do
+ user = insert(:user)
+ activity = insert(:note_activity, user: user)
+
+ {:ok, self_reply1} =
+ CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => activity.id})
+
+ result = ObjectView.render("object.json", %{object: refresh_record(activity)})
+ replies_uris = [self_reply1.data["id"]]
+
+ assert %{
+ "type" => "Collection",
+ "first" => %{"type" => "Collection", "items" => ^replies_uris}
+ } = get_in(result, ["object", "replies"])
+ end
+ end
+
test "renders a like activity" do
note = insert(:note_activity)
object = Object.normalize(note)