diff options
Diffstat (limited to 'app/lib/activitypub')
-rw-r--r-- | app/lib/activitypub/activity/announce.rb | 4 | ||||
-rw-r--r-- | app/lib/activitypub/activity/create.rb | 10 | ||||
-rw-r--r-- | app/lib/activitypub/activity/update.rb | 4 | ||||
-rw-r--r-- | app/lib/activitypub/adapter.rb | 76 | ||||
-rw-r--r-- | app/lib/activitypub/serializer.rb | 30 |
5 files changed, 90 insertions, 34 deletions
diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 9f8ffd9fb..1aa6ee9ec 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -47,6 +47,10 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity followed_by_local_accounts? || requested_through_relay? || reblog_of_local_status? end + def requested_through_relay? + super || Relay.find_by(inbox_url: @account.inbox_url)&.enabled? + end + def reblog_of_local_status? status_from_uri(object_uri)&.account&.local? end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 8fe7b9138..dabdcbcf7 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -68,7 +68,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity thread: replied_to_status, conversation: conversation_from_uri(@object['conversation']), media_attachment_ids: process_attachments.take(4).map(&:id), - owned_poll: process_poll, + poll: process_poll, } end end @@ -240,11 +240,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def poll_vote? - return false if replied_to_status.nil? || replied_to_status.poll.nil? || !replied_to_status.local? || !replied_to_status.poll.options.include?(@object['name']) + return false if replied_to_status.nil? || replied_to_status.preloadable_poll.nil? || !replied_to_status.local? || !replied_to_status.preloadable_poll.options.include?(@object['name']) - unless replied_to_status.poll.expired? - replied_to_status.poll.votes.create!(account: @account, choice: replied_to_status.poll.options.index(@object['name']), uri: @object['id']) - ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.poll.hide_totals? + unless replied_to_status.preloadable_poll.expired? + replied_to_status.preloadable_poll.votes.create!(account: @account, choice: replied_to_status.preloadable_poll.options.index(@object['name']), uri: @object['id']) + ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals? end true diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb index bc9a63f98..70035325b 100644 --- a/app/lib/activitypub/activity/update.rb +++ b/app/lib/activitypub/activity/update.rb @@ -23,8 +23,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity return reject_payload! if invalid_origin?(@object['id']) status = Status.find_by(uri: object_uri, account_id: @account.id) - return if status.nil? || status.poll.nil? + return if status.nil? || status.preloadable_poll.nil? - ActivityPub::ProcessPollService.new.call(status.poll, @object) + ActivityPub::ProcessPollService.new.call(status.preloadable_poll, @object) end end diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 99f4d9305..94eb2899c 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -1,30 +1,24 @@ # frozen_string_literal: true class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base - CONTEXT = { - '@context': [ - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - - { - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', - 'sensitive' => 'as:sensitive', - 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' }, - 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' }, - 'Hashtag' => 'as:Hashtag', - 'ostatus' => 'http://ostatus.org#', - 'atomUri' => 'ostatus:atomUri', - 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', - 'conversation' => 'ostatus:conversation', - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' }, - 'featured' => { '@id' => 'toot:featured', '@type' => '@id' }, - 'schema' => 'http://schema.org#', - 'PropertyValue' => 'schema:PropertyValue', - 'value' => 'schema:value', - }, - ], + NAMED_CONTEXT_MAP = { + activitystreams: 'https://www.w3.org/ns/activitystreams', + security: 'https://w3id.org/security/v1', + }.freeze + + CONTEXT_EXTENSION_MAP = { + manually_approves_followers: { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers' }, + sensitive: { 'sensitive' => 'as:sensitive' }, + hashtag: { 'Hashtag' => 'as:Hashtag' }, + moved_to: { 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' } }, + also_known_as: { 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' } }, + emoji: { 'toot' => 'http://joinmastodon.org/ns#', 'Emoji' => 'toot:Emoji' }, + featured: { 'toot' => 'http://joinmastodon.org/ns#', 'featured' => { '@id' => 'toot:featured', '@type' => '@id' } }, + property_value: { 'schema' => 'http://schema.org#', 'PropertyValue' => 'schema:PropertyValue', 'value' => 'schema:value' }, + atom_uri: { 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri' }, + conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' }, + focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } }, + identity_proof: { 'toot' => 'http://joinmastodon.org/ns#', 'IdentityProof' => 'toot:IdentityProof' }, }.freeze def self.default_key_transform @@ -36,8 +30,36 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base end def serializable_hash(options = nil) - options = serialization_options(options) - serialized_hash = ActiveModelSerializers::Adapter::Attributes.new(serializer, instance_options).serializable_hash(options) - CONTEXT.merge(self.class.transform_key_casing!(serialized_hash, instance_options)) + options = serialization_options(options) + serialized_hash = serializer.serializable_hash(options) + serialized_hash = self.class.transform_key_casing!(serialized_hash, instance_options) + + { '@context' => serialized_context }.merge(serialized_hash) + end + + private + + def serialized_context + context_array = [] + + serializer_options = serializer.send(:instance_options) || {} + named_contexts = [:activitystreams] + serializer._named_contexts.keys + serializer_options.fetch(:named_contexts, {}).keys + context_extensions = serializer._context_extensions.keys + serializer_options.fetch(:context_extensions, {}).keys + + named_contexts.each do |key| + context_array << NAMED_CONTEXT_MAP[key] + end + + extensions = context_extensions.each_with_object({}) do |key, h| + h.merge!(CONTEXT_EXTENSION_MAP[key]) + end + + context_array << extensions unless extensions.empty? + + if context_array.size == 1 + context_array.first + else + context_array + end end end diff --git a/app/lib/activitypub/serializer.rb b/app/lib/activitypub/serializer.rb new file mode 100644 index 000000000..07bd8c494 --- /dev/null +++ b/app/lib/activitypub/serializer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class ActivityPub::Serializer < ActiveModel::Serializer + with_options instance_writer: false, instance_reader: true do |serializer| + serializer.class_attribute :_named_contexts + serializer.class_attribute :_context_extensions + + self._named_contexts ||= {} + self._context_extensions ||= {} + end + + def self.inherited(base) + super + + base._named_contexts = _named_contexts.dup + base._context_extensions = _context_extensions.dup + end + + def self.context(*named_contexts) + named_contexts.each do |context| + _named_contexts[context] = true + end + end + + def self.context_extensions(*extension_names) + extension_names.each do |extension_name| + _context_extensions[extension_name] = true + end + end +end |