Federate and store a collection url (#38697)

This commit is contained in:
David Roetzel 2026-04-16 09:26:34 +02:00 committed by GitHub
parent 543db6d24c
commit fee38e57f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 46 additions and 3 deletions

View File

@ -15,6 +15,7 @@
# original_number_of_items :integer
# sensitive :boolean not null
# uri :string
# url :string
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint(8) not null

View File

@ -1,13 +1,16 @@
# frozen_string_literal: true
class ActivityPub::FeaturedCollectionSerializer < ActivityPub::Serializer
attributes :id, :type, :total_items, :name, :attributed_to,
# include Rails.application.routes.url_helpers
include RoutingHelper
attributes :id, :type, :total_items, :name, :attributed_to, :url,
:sensitive, :discoverable, :published, :updated
attribute :summary, unless: :language_present?
attribute :summary_map, if: :language_present?
has_one :tag, key: :topic, serializer: ActivityPub::NoteSerializer::TagSerializer
has_one :topic, serializer: ActivityPub::NoteSerializer::TagSerializer
has_many :collection_items, key: :ordered_items, serializer: ActivityPub::FeaturedItemSerializer
@ -31,6 +34,10 @@ class ActivityPub::FeaturedCollectionSerializer < ActivityPub::Serializer
ActivityPub::TagManager.instance.uri_for(object.account)
end
def url
account_collection_url(object.account, object)
end
def total_items
object.accepted_collection_items.size
end
@ -50,4 +57,8 @@ class ActivityPub::FeaturedCollectionSerializer < ActivityPub::Serializer
def collection_items
object.accepted_collection_items
end
def topic
object.tag
end
end

View File

@ -46,6 +46,13 @@ class ActivityPub::ProcessFeaturedCollectionService
@json['summaryMap']&.keys&.first
end
def url
url = url_to_href(@json['url'], 'text/html')
return @json['id'] if url.blank? || unsupported_uri_scheme?(url)
url
end
def collection_attributes
{
local: false,
@ -56,6 +63,7 @@ class ActivityPub::ProcessFeaturedCollectionService
discoverable: @json['discoverable'],
original_number_of_items: @json['totalItems'] || 0,
tag_name: @json.dig('topic', 'name'),
url:,
}
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddURLToCollections < ActiveRecord::Migration[8.1]
def change
add_column :collections, :url, :string
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 2026_04_10_083500) do
ActiveRecord::Schema[8.1].define(version: 2026_04_15_133505) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@ -400,6 +400,7 @@ ActiveRecord::Schema[8.1].define(version: 2026_04_10_083500) do
t.bigint "tag_id"
t.datetime "updated_at", null: false
t.string "uri"
t.string "url"
t.index ["account_id"], name: "index_collections_on_account_id"
t.index ["tag_id"], name: "index_collections_on_tag_id"
t.index ["uri"], name: "index_collections_on_uri", unique: true, where: "(uri IS NOT NULL)"

View File

@ -25,6 +25,7 @@ RSpec.describe ActivityPub::FeaturedCollectionSerializer do
'attributedTo' => ActivityPub::TagManager.instance.uri_for(collection.account),
'sensitive' => false,
'discoverable' => false,
'url' => account_collection_url(collection.account, collection),
'topic' => {
'href' => match(%r{/tags/people$}),
'type' => 'Hashtag',

View File

@ -16,6 +16,7 @@ RSpec.describe ActivityPub::ProcessFeaturedCollectionService do
'name' => 'Good people from other servers',
'sensitive' => false,
'discoverable' => true,
'url' => 'https://example.com/c/1',
'topic' => {
'type' => 'Hashtag',
'name' => '#people',
@ -50,6 +51,7 @@ RSpec.describe ActivityPub::ProcessFeaturedCollectionService do
expect(new_collection.description_html).to eq '<p>A list of remote actors you should follow.</p>'
expect(new_collection.sensitive).to be false
expect(new_collection.discoverable).to be true
expect(new_collection.url).to eq 'https://example.com/c/1'
expect(new_collection.tag.formatted_name).to eq '#people'
expect(ActivityPub::ProcessFeaturedItemWorker).to have_enqueued_sidekiq_job.with(new_collection.id, 'https://example.com/featured_items/1', 1, nil)
@ -75,6 +77,18 @@ RSpec.describe ActivityPub::ProcessFeaturedCollectionService do
end
end
context 'when the json does not include a `url`' do
let(:featured_collection_json) do
base_json.except('url')
end
it 'uses the `id` instead' do
subject.call(account, featured_collection_json)
expect(Collection.last.url).to eq 'https://example.com/featured_collections/1'
end
end
context 'when the collection already exists' do
let(:collection) { Fabricate(:remote_collection, account:, uri: base_json['id'], name: 'placeholder') }