diff --git a/app/helpers/json_ld_helper.rb b/app/helpers/json_ld_helper.rb index 212894d0cd..078aba456a 100644 --- a/app/helpers/json_ld_helper.rb +++ b/app/helpers/json_ld_helper.rb @@ -26,6 +26,8 @@ module JsonLdHelper # The url attribute can be a string, an array of strings, or an array of objects. # The objects could include a mimeType. Not-included mimeType means it's text/html. def url_to_href(value, preferred_type = nil) + value = [value] if value.is_a?(Hash) + single_value = if value.is_a?(Array) && !value.first.is_a?(String) value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) } elsif value.is_a?(Array) @@ -41,6 +43,15 @@ module JsonLdHelper end end + def url_to_media_type(value, preferred_type = nil) + value = [value] if value.is_a?(Hash) + return unless value.is_a?(Array) && !value.first.is_a?(String) + + single_value = value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) } + + single_value['mediaType'] unless single_value.nil? + end + def as_array(value) if value.nil? [] diff --git a/app/lib/activitypub/parser/media_attachment_parser.rb b/app/lib/activitypub/parser/media_attachment_parser.rb index bcbf92214f..1f4f43cb15 100644 --- a/app/lib/activitypub/parser/media_attachment_parser.rb +++ b/app/lib/activitypub/parser/media_attachment_parser.rb @@ -15,7 +15,7 @@ class ActivityPub::Parser::MediaAttachmentParser end def remote_url - url = Addressable::URI.parse(@json['url'])&.normalize&.to_s + url = Addressable::URI.parse(url_to_href(@json['url']))&.normalize&.to_s url unless unsupported_uri_scheme?(url) rescue Addressable::URI::InvalidURIError nil @@ -43,7 +43,7 @@ class ActivityPub::Parser::MediaAttachmentParser end def file_content_type - @json['mediaType'] + @json['mediaType'] || url_to_media_type(@json['url']) end private diff --git a/spec/lib/activitypub/parser/media_attachment_parser_spec.rb b/spec/lib/activitypub/parser/media_attachment_parser_spec.rb new file mode 100644 index 0000000000..9456b5e648 --- /dev/null +++ b/spec/lib/activitypub/parser/media_attachment_parser_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::Parser::MediaAttachmentParser do + subject { described_class.new(json) } + + let(:json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + type: 'Document', + mediaType: 'image/png', + url: 'http://example.com/attachment.png', + }.deep_stringify_keys + end + + it 'correctly parses media attachment' do + expect(subject).to have_attributes( + remote_url: 'http://example.com/attachment.png', + file_content_type: 'image/png' + ) + end + + context 'when the URL is a link with multiple options' do + let(:json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + type: 'Document', + url: [ + { + type: 'Link', + mediaType: 'image/png', + href: 'http://example.com/attachment.png', + }, + { + type: 'Link', + mediaType: 'image/avif', + href: 'http://example.com/attachment.avif', + }, + ], + }.deep_stringify_keys + end + + it 'returns the first option' do + expect(subject).to have_attributes( + remote_url: 'http://example.com/attachment.png', + file_content_type: 'image/png' + ) + end + end +end