diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index b292de7b26..1f8750e4c5 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -634,7 +634,18 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def quote - @quote ||= @object['quote'] || @object['quoteUrl'] || @object['quoteURL'] || @object['_misskey_quote'] + @quote ||= quote_from_tags || @object['quote'] || @object['quoteUrl'] || @object['quoteURL'] || @object['_misskey_quote'] + end + + LINK_MEDIA_TYPES = ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].freeze + + def quote_from_tags + return @quote_from_tags if defined?(@quote_from_tags) + + hit_tag = as_array(@object['tag']).detect do |tag| + equals_or_includes?(tag['type'], 'Link') && LINK_MEDIA_TYPES.include?(tag['mediaType']) && tag['href'].present? + end + @quote_from_tags = hit_tag && hit_tag['href'] end def join_group! diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index 6cfbc97f2f..fe7be2eae9 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -140,7 +140,19 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer end def virtual_tags - object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis + object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis + virtual_tags_of_quote + end + + def virtual_tags_of_quote + return [] unless object.quote? + + [ + { + type: 'Link', + mediaType: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + href: quote_uri, + }, + ] end def atom_uri diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index cda7d3f033..4fd0412b6d 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -1636,6 +1636,35 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'with quote as feb-e232 object links' do + let(:recipient) { Fabricate(:account) } + let!(:target_status) { Fabricate(:status, account: Fabricate(:account, domain: nil)) } + + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + tag: [ + { + type: 'Link', + mediaType: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + href: ActivityPub::TagManager.instance.uri_for(target_status), + }, + ], + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.references.pluck(:id)).to eq [target_status.id] + expect(status.quote).to_not be_nil + expect(status.quote.id).to eq target_status.id + end + end + context 'with references and quote' do let(:recipient) { Fabricate(:account) } let!(:target_status) { Fabricate(:status, account: Fabricate(:account, domain: nil)) } diff --git a/spec/serializers/activitypub/note_serializer_spec.rb b/spec/serializers/activitypub/note_serializer_spec.rb index e60144d320..71e4d33305 100644 --- a/spec/serializers/activitypub/note_serializer_spec.rb +++ b/spec/serializers/activitypub/note_serializer_spec.rb @@ -16,11 +16,14 @@ describe ActivityPub::NoteSerializer do let!(:reply_by_account_third) { Fabricate(:status, account: account, thread: parent, visibility: :public) } let!(:reply_by_account_visibility_direct) { Fabricate(:status, account: account, thread: parent, visibility: :direct) } let!(:referred) { nil } - let!(:referred2) { nil } + let!(:quote) { nil } before do parent.references << referred if referred.present? - parent.references << referred2 if referred2.present? + if quote.present? + parent.references << quote + parent.quote = quote + end end it 'has the expected shape' do @@ -78,7 +81,7 @@ describe ActivityPub::NoteSerializer do end end - context 'when has quote but no_convert setting' do + context 'when has a reference' do let(:referred) { Fabricate(:status) } it 'has a references collection' do @@ -94,4 +97,19 @@ describe ActivityPub::NoteSerializer do expect(subject['references']['first']['items']).to include referred.uri end end + + context 'when has a quote' do + let(:quote) { Fabricate(:status) } + + it 'has a quote as transitional type' do + expect(subject['quoteUri']).to eq ActivityPub::TagManager.instance.uri_for(quote) + end + + it 'has a quote as feb-e232 object link' do + tag = subject['tag'].detect { |t| t['type'] == 'Link' } + expect(tag).to_not be_nil + expect(tag['mediaType']).to eq 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + expect(tag['href']).to eq ActivityPub::TagManager.instance.uri_for(quote) + end + end end