mirror of
https://github.com/mastodon/mastodon.git
synced 2026-03-21 18:05:23 -05:00
Refactor activity serialization (#37678)
This commit is contained in:
parent
8ebe2e673e
commit
73206856c5
|
|
@ -26,7 +26,7 @@ class Api::V1::Statuses::PinsController < Api::V1::Statuses::BaseController
|
|||
def distribute_add_activity!
|
||||
json = ActiveModelSerializers::SerializableResource.new(
|
||||
@status,
|
||||
serializer: ActivityPub::AddSerializer,
|
||||
serializer: ActivityPub::AddNoteSerializer,
|
||||
adapter: ActivityPub::Adapter
|
||||
).as_json
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ class Api::V1::Statuses::PinsController < Api::V1::Statuses::BaseController
|
|||
def distribute_remove_activity!
|
||||
json = ActiveModelSerializers::SerializableResource.new(
|
||||
@status,
|
||||
serializer: ActivityPub::RemoveSerializer,
|
||||
serializer: ActivityPub::RemoveNoteSerializer,
|
||||
adapter: ActivityPub::Adapter
|
||||
).as_json
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class StatusesController < ApplicationController
|
|||
|
||||
def activity
|
||||
expires_in 3.minutes, public: @status.distributable? && public_fetch_mode?
|
||||
render_with_cache json: ActivityPub::ActivityPresenter.from_status(@status), content_type: 'application/activity+json', serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter
|
||||
render_with_cache json: @status, content_type: 'application/activity+json', serializer: activity_serializer, adapter: ActivityPub::Adapter
|
||||
end
|
||||
|
||||
def embed
|
||||
|
|
@ -69,4 +69,8 @@ class StatusesController < ApplicationController
|
|||
def redirect_to_original
|
||||
redirect_to(ActivityPub::TagManager.instance.url_for(@status.reblog), allow_other_host: true) if @status.reblog?
|
||||
end
|
||||
|
||||
def activity_serializer
|
||||
@status.reblog? ? ActivityPub::AnnounceNoteSerializer : ActivityPub::CreateNoteSerializer
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::ActivityPresenter < ActiveModelSerializers::Model
|
||||
attributes :id, :type, :actor, :published, :to, :cc, :virtual_object
|
||||
|
||||
class << self
|
||||
def from_status(status, allow_inlining: true)
|
||||
new.tap do |presenter|
|
||||
presenter.id = ActivityPub::TagManager.instance.activity_uri_for(status)
|
||||
presenter.type = status.reblog? ? 'Announce' : 'Create'
|
||||
presenter.actor = ActivityPub::TagManager.instance.uri_for(status.account)
|
||||
presenter.published = status.created_at
|
||||
presenter.to = ActivityPub::TagManager.instance.to(status)
|
||||
presenter.cc = ActivityPub::TagManager.instance.cc(status)
|
||||
|
||||
presenter.virtual_object = begin
|
||||
if status.reblog?
|
||||
if allow_inlining && status.account == status.proper.account && status.proper.private_visibility? && status.local?
|
||||
status.proper
|
||||
else
|
||||
ActivityPub::TagManager.instance.uri_for(status.proper)
|
||||
end
|
||||
else
|
||||
status.proper
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::ActivitySerializer < ActivityPub::Serializer
|
||||
def self.serializer_for(model, options)
|
||||
case model.class.name
|
||||
when 'Status'
|
||||
ActivityPub::NoteSerializer
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
attributes :id, :type, :actor, :published, :to, :cc
|
||||
|
||||
has_one :virtual_object, key: :object
|
||||
|
||||
def published
|
||||
object.published.iso8601
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::AddFeaturedCollectionSerializer < ActivityPub::Serializer
|
||||
include RoutingHelper
|
||||
|
||||
attributes :type, :actor, :target
|
||||
has_one :object, serializer: ActivityPub::FeaturedCollectionSerializer
|
||||
|
||||
def type
|
||||
'Add'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def target
|
||||
ap_account_featured_collections_url(object.account_id)
|
||||
end
|
||||
end
|
||||
24
app/serializers/activitypub/add_hashtag_serializer.rb
Normal file
24
app/serializers/activitypub/add_hashtag_serializer.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::AddHashtagSerializer < ActivityPub::Serializer
|
||||
attributes :type, :actor, :target
|
||||
|
||||
has_one :object, serializer: ActivityPub::HashtagSerializer
|
||||
|
||||
def type
|
||||
'Add'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def target
|
||||
# Technically this is not correct, as tags have their own collection.
|
||||
# But sadly we do not store the collection URI for tags anywhere so cannot
|
||||
# handle `Add` activities to that properly (yet). The receiving code for
|
||||
# this currently looks at the type of the contained objects to do the
|
||||
# right thing.
|
||||
ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
|
||||
end
|
||||
end
|
||||
23
app/serializers/activitypub/add_note_serializer.rb
Normal file
23
app/serializers/activitypub/add_note_serializer.rb
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::AddNoteSerializer < ActivityPub::Serializer
|
||||
attributes :type, :actor, :target
|
||||
|
||||
has_one :proper_object, key: :object
|
||||
|
||||
def type
|
||||
'Add'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def proper_object
|
||||
ActivityPub::TagManager.instance.uri_for(object)
|
||||
end
|
||||
|
||||
def target
|
||||
ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::AddSerializer < ActivityPub::Serializer
|
||||
class UriSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
|
||||
def serializable_hash(*_args)
|
||||
ActivityPub::TagManager.instance.uri_for(object)
|
||||
end
|
||||
end
|
||||
|
||||
def self.serializer_for(model, options)
|
||||
case model
|
||||
when Status
|
||||
UriSerializer
|
||||
when FeaturedTag
|
||||
ActivityPub::HashtagSerializer
|
||||
when Collection
|
||||
ActivityPub::FeaturedCollectionSerializer
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
include RoutingHelper
|
||||
|
||||
attributes :type, :actor, :target
|
||||
has_one :proper_object, key: :object
|
||||
|
||||
def type
|
||||
'Add'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def proper_object
|
||||
object
|
||||
end
|
||||
|
||||
def target
|
||||
case object
|
||||
when Status, FeaturedTag
|
||||
# Technically this is not correct, as tags have their own collection.
|
||||
# But sadly we do not store the collection URI for tags anywhere so cannot
|
||||
# handle `Add` activities to that properly (yet). The receiving code for
|
||||
# this currently looks at the type of the contained objects to do the
|
||||
# right thing.
|
||||
ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
|
||||
when Collection
|
||||
ap_account_featured_collections_url(object.account_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
53
app/serializers/activitypub/announce_note_serializer.rb
Normal file
53
app/serializers/activitypub/announce_note_serializer.rb
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::AnnounceNoteSerializer < ActivityPub::Serializer
|
||||
def self.serializer_for(model, options)
|
||||
return ActivityPub::NoteSerializer if model.is_a?(Status)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
attributes :id, :type, :actor, :published, :to, :cc
|
||||
|
||||
has_one :virtual_object, key: :object
|
||||
|
||||
def id
|
||||
ActivityPub::TagManager.instance.activity_uri_for(object)
|
||||
end
|
||||
|
||||
def type
|
||||
'Announce'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def to
|
||||
ActivityPub::TagManager.instance.to(object)
|
||||
end
|
||||
|
||||
def cc
|
||||
ActivityPub::TagManager.instance.cc(object)
|
||||
end
|
||||
|
||||
def published
|
||||
object.created_at.iso8601
|
||||
end
|
||||
|
||||
def virtual_object
|
||||
if allow_inlining? && object.account == object.proper.account && object.proper.private_visibility? && object.local?
|
||||
object.proper
|
||||
else
|
||||
ActivityPub::TagManager.instance.uri_for(object.proper)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allow_inlining?
|
||||
return instance_options[:allow_inlining] if instance_options.key?(:allow_inlining)
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
31
app/serializers/activitypub/create_note_serializer.rb
Normal file
31
app/serializers/activitypub/create_note_serializer.rb
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::CreateNoteSerializer < ActivityPub::Serializer
|
||||
attributes :id, :type, :actor, :published, :to, :cc
|
||||
|
||||
has_one :object, serializer: ActivityPub::NoteSerializer
|
||||
|
||||
def id
|
||||
ActivityPub::TagManager.instance.activity_uri_for(object)
|
||||
end
|
||||
|
||||
def type
|
||||
'Create'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def to
|
||||
ActivityPub::TagManager.instance.to(object)
|
||||
end
|
||||
|
||||
def cc
|
||||
ActivityPub::TagManager.instance.cc(object)
|
||||
end
|
||||
|
||||
def published
|
||||
object.created_at.iso8601
|
||||
end
|
||||
end
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::DeleteSerializer < ActivityPub::Serializer
|
||||
class ActivityPub::DeleteNoteSerializer < ActivityPub::Serializer
|
||||
class TombstoneSerializer < ActivityPub::Serializer
|
||||
context_extensions :atom_uri
|
||||
|
||||
|
|
@ -2,14 +2,15 @@
|
|||
|
||||
class ActivityPub::OutboxSerializer < ActivityPub::CollectionSerializer
|
||||
def self.serializer_for(model, options)
|
||||
if model.instance_of?(::ActivityPub::ActivityPresenter)
|
||||
ActivityPub::ActivitySerializer
|
||||
case model
|
||||
when Status
|
||||
model.reblog? ? ActivityPub::AnnounceNoteSerializer : ActivityPub::CreateNoteSerializer
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def items
|
||||
object.items.map { |status| ActivityPub::ActivityPresenter.from_status(status) }
|
||||
object.items
|
||||
end
|
||||
end
|
||||
|
|
|
|||
18
app/serializers/activitypub/remove_hashtag_serializer.rb
Normal file
18
app/serializers/activitypub/remove_hashtag_serializer.rb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::RemoveHashtagSerializer < ActivityPub::Serializer
|
||||
attributes :type, :actor, :target
|
||||
has_one :object, serializer: ActivityPub::HashtagSerializer
|
||||
|
||||
def type
|
||||
'Remove'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def target
|
||||
ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
|
||||
end
|
||||
end
|
||||
22
app/serializers/activitypub/remove_note_serializer.rb
Normal file
22
app/serializers/activitypub/remove_note_serializer.rb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::RemoveNoteSerializer < ActivityPub::Serializer
|
||||
attributes :type, :actor, :target
|
||||
has_one :proper_object, key: :object
|
||||
|
||||
def type
|
||||
'Remove'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def proper_object
|
||||
ActivityPub::TagManager.instance.uri_for(object)
|
||||
end
|
||||
|
||||
def target
|
||||
ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::RemoveSerializer < ActivityPub::Serializer
|
||||
class UriSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
|
||||
def serializable_hash(*_args)
|
||||
ActivityPub::TagManager.instance.uri_for(object)
|
||||
end
|
||||
end
|
||||
|
||||
def self.serializer_for(model, options)
|
||||
case model.class.name
|
||||
when 'Status'
|
||||
UriSerializer
|
||||
when 'FeaturedTag'
|
||||
ActivityPub::HashtagSerializer
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
include RoutingHelper
|
||||
|
||||
attributes :type, :actor, :target
|
||||
has_one :proper_object, key: :object
|
||||
|
||||
def type
|
||||
'Remove'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def proper_object
|
||||
object
|
||||
end
|
||||
|
||||
def target
|
||||
ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
|
||||
end
|
||||
end
|
||||
|
|
@ -3,7 +3,11 @@
|
|||
class ActivityPub::UndoAnnounceSerializer < ActivityPub::Serializer
|
||||
attributes :id, :type, :actor, :to
|
||||
|
||||
has_one :virtual_object, key: :object, serializer: ActivityPub::ActivitySerializer
|
||||
has_one :virtual_object, key: :object, serializer: ActivityPub::AnnounceNoteSerializer do |serializer|
|
||||
serializer.send(:instance_options)[:allow_inlining] = false
|
||||
|
||||
object
|
||||
end
|
||||
|
||||
def id
|
||||
[ActivityPub::TagManager.instance.uri_for(object.account), '#announces/', object.id, '/undo'].join
|
||||
|
|
@ -22,6 +26,6 @@ class ActivityPub::UndoAnnounceSerializer < ActivityPub::Serializer
|
|||
end
|
||||
|
||||
def virtual_object
|
||||
ActivityPub::ActivityPresenter.from_status(object, allow_inlining: false)
|
||||
object
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::UpdateSerializer < ActivityPub::Serializer
|
||||
class ActivityPub::UpdateActorSerializer < ActivityPub::Serializer
|
||||
attributes :id, :type, :actor, :to
|
||||
|
||||
has_one :object, serializer: ActivityPub::ActorSerializer
|
||||
37
app/serializers/activitypub/update_note_serializer.rb
Normal file
37
app/serializers/activitypub/update_note_serializer.rb
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::UpdateNoteSerializer < ActivityPub::Serializer
|
||||
attributes :id, :type, :actor, :published, :to, :cc
|
||||
|
||||
has_one :object, serializer: ActivityPub::NoteSerializer
|
||||
|
||||
def id
|
||||
[ActivityPub::TagManager.instance.uri_for(object), '#updates/', edited_at.to_i].join
|
||||
end
|
||||
|
||||
def type
|
||||
'Update'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def to
|
||||
ActivityPub::TagManager.instance.to(object)
|
||||
end
|
||||
|
||||
def cc
|
||||
ActivityPub::TagManager.instance.cc(object)
|
||||
end
|
||||
|
||||
def published
|
||||
edited_at.iso8601
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def edited_at
|
||||
instance_options[:updated_at]&.to_datetime || object.edited_at
|
||||
end
|
||||
end
|
||||
|
|
@ -34,7 +34,8 @@ class BackupService < BaseService
|
|||
add_comma = true
|
||||
|
||||
file.write(statuses.map do |status|
|
||||
item = serialize_payload(ActivityPub::ActivityPresenter.from_status(status), ActivityPub::ActivitySerializer)
|
||||
serializer = status.reblog? ? ActivityPub::AnnounceNoteSerializer : ActivityPub::CreateNoteSerializer
|
||||
item = serialize_payload(status, serializer)
|
||||
item.delete(:@context)
|
||||
|
||||
unless item[:type] == 'Announce' || item[:object][:attachment].blank?
|
||||
|
|
|
|||
|
|
@ -32,6 +32,6 @@ class CreateCollectionService
|
|||
end
|
||||
|
||||
def activity_json
|
||||
ActiveModelSerializers::SerializableResource.new(@collection, serializer: ActivityPub::AddSerializer, adapter: ActivityPub::Adapter).to_json
|
||||
ActiveModelSerializers::SerializableResource.new(@collection, serializer: ActivityPub::AddFeaturedCollectionSerializer, adapter: ActivityPub::Adapter).to_json
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ class CreateFeaturedTagService < BaseService
|
|||
private
|
||||
|
||||
def build_json(featured_tag)
|
||||
Oj.dump(serialize_payload(featured_tag, ActivityPub::AddSerializer, signer: @account))
|
||||
Oj.dump(serialize_payload(featured_tag, ActivityPub::AddHashtagSerializer, signer: @account))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -49,8 +49,4 @@ class ReblogService < BaseService
|
|||
def increment_statistics
|
||||
ActivityTracker.increment('activity:interactions')
|
||||
end
|
||||
|
||||
def build_json(reblog)
|
||||
Oj.dump(serialize_payload(ActivityPub::ActivityPresenter.from_status(reblog), ActivityPub::ActivitySerializer, signer: reblog.account))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ class RemoveFeaturedTagService < BaseService
|
|||
private
|
||||
|
||||
def build_json(featured_tag)
|
||||
Oj.dump(serialize_payload(featured_tag, ActivityPub::RemoveSerializer, signer: @account))
|
||||
Oj.dump(serialize_payload(featured_tag, ActivityPub::RemoveHashtagSerializer, signer: @account))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class RemoveStatusService < BaseService
|
|||
end
|
||||
|
||||
def signed_activity_json
|
||||
@signed_activity_json ||= Oj.dump(serialize_payload(@status, @status.reblog? ? ActivityPub::UndoAnnounceSerializer : ActivityPub::DeleteSerializer, signer: @account, always_sign: true))
|
||||
@signed_activity_json ||= Oj.dump(serialize_payload(@status, @status.reblog? ? ActivityPub::UndoAnnounceSerializer : ActivityPub::DeleteNoteSerializer, signer: @account, always_sign: true))
|
||||
end
|
||||
|
||||
def remove_reblogs
|
||||
|
|
|
|||
|
|
@ -72,6 +72,6 @@ class SuspendAccountService < BaseService
|
|||
end
|
||||
|
||||
def signed_activity_json
|
||||
@signed_activity_json ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateSerializer, signer: @account))
|
||||
@signed_activity_json ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateActorSerializer, signer: @account))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -63,6 +63,6 @@ class UnsuspendAccountService < BaseService
|
|||
end
|
||||
|
||||
def signed_activity_json
|
||||
@signed_activity_json ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateSerializer, signer: @account))
|
||||
@signed_activity_json ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateActorSerializer, signer: @account))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,11 +24,15 @@ class ActivityPub::DistributionWorker < ActivityPub::RawDistributionWorker
|
|||
end
|
||||
|
||||
def payload
|
||||
@payload ||= Oj.dump(serialize_payload(activity, ActivityPub::ActivitySerializer, signer: @account))
|
||||
@payload ||= Oj.dump(serialize_payload(@status, activity_serializer, serializer_options.merge(signer: @account)))
|
||||
end
|
||||
|
||||
def activity
|
||||
ActivityPub::ActivityPresenter.from_status(@status)
|
||||
def activity_serializer
|
||||
@status.reblog? ? ActivityPub::AnnounceNoteSerializer : ActivityPub::CreateNoteSerializer
|
||||
end
|
||||
|
||||
def serializer_options
|
||||
{}
|
||||
end
|
||||
|
||||
def options
|
||||
|
|
|
|||
|
|
@ -15,15 +15,11 @@ class ActivityPub::StatusUpdateDistributionWorker < ActivityPub::DistributionWor
|
|||
|
||||
protected
|
||||
|
||||
def activity
|
||||
ActivityPub::ActivityPresenter.new(
|
||||
id: [ActivityPub::TagManager.instance.uri_for(@status), '#updates/', @options[:updated_at]&.to_datetime&.to_i || @status.edited_at.to_i].join,
|
||||
type: 'Update',
|
||||
actor: ActivityPub::TagManager.instance.uri_for(@status.account),
|
||||
published: @options[:updated_at]&.to_datetime || @status.edited_at,
|
||||
to: ActivityPub::TagManager.instance.to(@status),
|
||||
cc: ActivityPub::TagManager.instance.cc(@status),
|
||||
virtual_object: @status
|
||||
)
|
||||
def activity_serializer
|
||||
ActivityPub::UpdateNoteSerializer
|
||||
end
|
||||
|
||||
def serializer_options
|
||||
super.merge({ updated_at: @options[:updated_at] })
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23,6 +23,6 @@ class ActivityPub::UpdateDistributionWorker < ActivityPub::RawDistributionWorker
|
|||
end
|
||||
|
||||
def payload
|
||||
@payload ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateSerializer, signer: @account, sign_with: @options[:sign_with]))
|
||||
@payload ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateActorSerializer, signer: @account, sign_with: @options[:sign_with]))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::ActivitySerializer do
|
||||
subject { serialized_record_json(presenter, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:status) { Fabricate(:status, created_at: Time.utc(2026, 0o1, 27, 15, 29, 31)) }
|
||||
|
||||
context 'with a new status' do
|
||||
let(:presenter) { ActivityPub::ActivityPresenter.from_status(status) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => tag_manager.activity_uri_for(status),
|
||||
'type' => 'Create',
|
||||
'actor' => tag_manager.uri_for(status.account),
|
||||
'published' => '2026-01-27T15:29:31Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [a_string_matching(/followers$/)],
|
||||
'object' => a_hash_including(
|
||||
'id' => tag_manager.uri_for(status)
|
||||
),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a new reblog' do
|
||||
let(:reblog) { Fabricate(:status, reblog: status, created_at: Time.utc(2026, 0o1, 27, 16, 21, 44)) }
|
||||
let(:presenter) { ActivityPub::ActivityPresenter.from_status(reblog) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => tag_manager.activity_uri_for(reblog),
|
||||
'type' => 'Announce',
|
||||
'actor' => tag_manager.uri_for(reblog.account),
|
||||
'published' => '2026-01-27T16:21:44Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [tag_manager.uri_for(status.account), a_string_matching(/followers$/)],
|
||||
'object' => tag_manager.uri_for(status),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
|
||||
context 'when inlining of private local status is allowed' do
|
||||
let(:status) { Fabricate(:status, visibility: :private, created_at: Time.utc(2026, 0o1, 27, 15, 29, 31)) }
|
||||
let(:reblog) { Fabricate(:status, reblog: status, account: status.account, created_at: Time.utc(2026, 0o1, 27, 16, 21, 44)) }
|
||||
let(:presenter) { ActivityPub::ActivityPresenter.from_status(reblog, allow_inlining: true) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => tag_manager.activity_uri_for(reblog),
|
||||
'type' => 'Announce',
|
||||
'actor' => tag_manager.uri_for(reblog.account),
|
||||
'published' => '2026-01-27T16:21:44Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [tag_manager.uri_for(status.account), a_string_matching(/followers$/)],
|
||||
'object' => a_hash_including(
|
||||
'id' => tag_manager.uri_for(status)
|
||||
),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a custom presenter for a status `Update`' do
|
||||
let(:status) { Fabricate(:status, edited_at: Time.utc(2026, 0o1, 27, 15, 29, 31)) }
|
||||
let(:presenter) do
|
||||
ActivityPub::ActivityPresenter.new(
|
||||
id: 'https://localhost/status/1#updates/1769527771',
|
||||
type: 'Update',
|
||||
actor: 'https://localhost/actor/1',
|
||||
published: status.edited_at,
|
||||
to: ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
cc: ['https://localhost/actor/1/followers'],
|
||||
virtual_object: status
|
||||
)
|
||||
end
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => 'https://localhost/status/1#updates/1769527771',
|
||||
'type' => 'Update',
|
||||
'actor' => 'https://localhost/actor/1',
|
||||
'published' => '2026-01-27T15:29:31Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => ['https://localhost/actor/1/followers'],
|
||||
'object' => a_hash_including(
|
||||
'id' => tag_manager.uri_for(status)
|
||||
),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::AddFeaturedCollectionSerializer do
|
||||
subject { serialized_record_json(object, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:object) { Fabricate(:collection) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Add',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured_collections$}),
|
||||
'object' => a_hash_including({
|
||||
'type' => 'FeaturedCollection',
|
||||
}),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
26
spec/serializers/activitypub/add_hashtag_serializer_spec.rb
Normal file
26
spec/serializers/activitypub/add_hashtag_serializer_spec.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::AddHashtagSerializer do
|
||||
subject { serialized_record_json(object, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:object) { Fabricate(:featured_tag) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Add',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => a_hash_including({
|
||||
'type' => 'Hashtag',
|
||||
}),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
24
spec/serializers/activitypub/add_note_serializer_spec.rb
Normal file
24
spec/serializers/activitypub/add_note_serializer_spec.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::AddNoteSerializer do
|
||||
subject { serialized_record_json(object, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:object) { Fabricate(:status) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Add',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => tag_manager.uri_for(object),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::AddSerializer do
|
||||
describe '.serializer_for' do
|
||||
subject { described_class.serializer_for(model, {}) }
|
||||
|
||||
context 'with a Status model' do
|
||||
let(:model) { Status.new }
|
||||
|
||||
it { is_expected.to eq(described_class::UriSerializer) }
|
||||
end
|
||||
|
||||
context 'with a FeaturedTag model' do
|
||||
let(:model) { FeaturedTag.new }
|
||||
|
||||
it { is_expected.to eq(ActivityPub::HashtagSerializer) }
|
||||
end
|
||||
|
||||
context 'with a Collection model' do
|
||||
let(:model) { Collection.new }
|
||||
|
||||
it { is_expected.to eq(ActivityPub::FeaturedCollectionSerializer) }
|
||||
end
|
||||
|
||||
context 'with an Array' do
|
||||
let(:model) { [] }
|
||||
|
||||
it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#target' do
|
||||
subject { described_class.new(object).target }
|
||||
|
||||
context 'when object is a Status' do
|
||||
let(:object) { Fabricate(:status) }
|
||||
|
||||
it { is_expected.to match(%r{/#{object.account_id}/collections/featured$}) }
|
||||
end
|
||||
|
||||
context 'when object is a FeaturedTag' do
|
||||
let(:object) { Fabricate(:featured_tag) }
|
||||
|
||||
it { is_expected.to match(%r{/#{object.account_id}/collections/featured$}) }
|
||||
end
|
||||
|
||||
context 'when object is a Collection' do
|
||||
let(:object) { Fabricate(:collection) }
|
||||
|
||||
it { is_expected.to match(%r{/#{object.account_id}/featured_collections$}) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Serialization' do
|
||||
subject { serialized_record_json(object, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
|
||||
context 'with a status' do
|
||||
let(:object) { Fabricate(:status) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Add',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => tag_manager.uri_for(object),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a featured tag' do
|
||||
let(:object) { Fabricate(:featured_tag) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Add',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => a_hash_including({
|
||||
'type' => 'Hashtag',
|
||||
}),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a collection' do
|
||||
let(:object) { Fabricate(:collection) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Add',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured_collections$}),
|
||||
'object' => a_hash_including({
|
||||
'type' => 'FeaturedCollection',
|
||||
}),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::AnnounceNoteSerializer do
|
||||
subject { serialized_record_json(reblog, described_class, adapter: ActivityPub::Adapter, options:) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:status) { Fabricate(:status, created_at: Time.utc(2026, 1, 27, 15, 29, 31)) }
|
||||
let(:reblog) { Fabricate(:status, reblog: status, created_at: Time.utc(2026, 1, 27, 16, 21, 44)) }
|
||||
let(:options) { {} }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => tag_manager.activity_uri_for(reblog),
|
||||
'type' => 'Announce',
|
||||
'actor' => tag_manager.uri_for(reblog.account),
|
||||
'published' => '2026-01-27T16:21:44Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [tag_manager.uri_for(status.account), a_string_matching(/followers$/)],
|
||||
'object' => tag_manager.uri_for(status),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
|
||||
context 'when status is local and private' do
|
||||
let(:status) { Fabricate(:status, visibility: :private, created_at: Time.utc(2026, 1, 27, 15, 29, 31)) }
|
||||
let(:reblog) { Fabricate(:status, reblog: status, account: status.account, created_at: Time.utc(2026, 1, 27, 16, 21, 44)) }
|
||||
|
||||
context 'when inlining of private local status is allowed' do
|
||||
shared_examples 'serialization with inlining' do
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => tag_manager.activity_uri_for(reblog),
|
||||
'type' => 'Announce',
|
||||
'actor' => tag_manager.uri_for(reblog.account),
|
||||
'published' => '2026-01-27T16:21:44Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [tag_manager.uri_for(status.account), a_string_matching(/followers$/)],
|
||||
'object' => a_hash_including(
|
||||
'id' => tag_manager.uri_for(status)
|
||||
),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with `allow_inlining` explicitly set to `true`' do
|
||||
let(:options) { { allow_inlining: true } }
|
||||
|
||||
it_behaves_like 'serialization with inlining'
|
||||
end
|
||||
|
||||
context 'with `allow_inlining` unset' do
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'serialization with inlining'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when inlining is not allowed' do
|
||||
let(:options) { { allow_inlining: false } }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => tag_manager.activity_uri_for(reblog),
|
||||
'type' => 'Announce',
|
||||
'actor' => tag_manager.uri_for(reblog.account),
|
||||
'published' => '2026-01-27T16:21:44Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [tag_manager.uri_for(status.account), a_string_matching(/followers$/)],
|
||||
'object' => tag_manager.uri_for(status),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
26
spec/serializers/activitypub/create_note_serializer_spec.rb
Normal file
26
spec/serializers/activitypub/create_note_serializer_spec.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::CreateNoteSerializer do
|
||||
subject { serialized_record_json(status, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:status) { Fabricate(:status, created_at: Time.utc(2026, 1, 27, 15, 29, 31)) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => tag_manager.activity_uri_for(status),
|
||||
'type' => 'Create',
|
||||
'actor' => tag_manager.uri_for(status.account),
|
||||
'published' => '2026-01-27T15:29:31Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [a_string_matching(/followers$/)],
|
||||
'object' => a_hash_including(
|
||||
'id' => tag_manager.uri_for(status)
|
||||
),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::DeleteSerializer do
|
||||
RSpec.describe ActivityPub::DeleteNoteSerializer do
|
||||
subject { serialized_record_json(status, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::RemoveHashtagSerializer do
|
||||
subject { serialized_record_json(object, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:object) { Fabricate(:featured_tag) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Remove',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => a_hash_including({
|
||||
'type' => 'Hashtag',
|
||||
}),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
24
spec/serializers/activitypub/remove_note_serializer_spec.rb
Normal file
24
spec/serializers/activitypub/remove_note_serializer_spec.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::RemoveNoteSerializer do
|
||||
subject { serialized_record_json(object, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:object) { Fabricate(:status) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Remove',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => tag_manager.uri_for(object),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::RemoveSerializer do
|
||||
describe '.serializer_for' do
|
||||
subject { described_class.serializer_for(model, {}) }
|
||||
|
||||
context 'with a Status model' do
|
||||
let(:model) { Status.new }
|
||||
|
||||
it { is_expected.to eq(described_class::UriSerializer) }
|
||||
end
|
||||
|
||||
context 'with a FeaturedTag model' do
|
||||
let(:model) { FeaturedTag.new }
|
||||
|
||||
it { is_expected.to eq(ActivityPub::HashtagSerializer) }
|
||||
end
|
||||
|
||||
context 'with an Array' do
|
||||
let(:model) { [] }
|
||||
|
||||
it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Serialization' do
|
||||
subject { serialized_record_json(object, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
|
||||
context 'with a status' do
|
||||
let(:object) { Fabricate(:status) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Remove',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => tag_manager.uri_for(object),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a featured tag' do
|
||||
let(:object) { Fabricate(:featured_tag) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'type' => 'Remove',
|
||||
'actor' => tag_manager.uri_for(object.account),
|
||||
'target' => a_string_matching(%r{/featured$}),
|
||||
'object' => a_hash_including({
|
||||
'type' => 'Hashtag',
|
||||
}),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('id')
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('to')
|
||||
expect(subject).to_not have_key('cc')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -26,4 +26,17 @@ RSpec.describe ActivityPub::UndoAnnounceSerializer do
|
|||
expect(subject).to_not have_key('cc')
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
|
||||
context 'when status is local and private' do
|
||||
let(:status) { Fabricate(:status, visibility: :private) }
|
||||
let(:reblog) { Fabricate(:status, reblog: status, account: status.account) }
|
||||
|
||||
it 'does not inline the status' do
|
||||
expect(subject).to include({
|
||||
'object' => a_hash_including({
|
||||
'object' => tag_manager.uri_for(status),
|
||||
}),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::UpdateSerializer do
|
||||
RSpec.describe ActivityPub::UpdateActorSerializer do
|
||||
subject { serialized_record_json(account, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
26
spec/serializers/activitypub/update_note_serializer_spec.rb
Normal file
26
spec/serializers/activitypub/update_note_serializer_spec.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::UpdateNoteSerializer do
|
||||
subject { serialized_record_json(status, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:status) { Fabricate(:status, edited_at: Time.utc(2026, 1, 27, 15, 29, 31)) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => "#{tag_manager.uri_for(status)}#updates/1769527771",
|
||||
'type' => 'Update',
|
||||
'actor' => tag_manager.uri_for(status.account),
|
||||
'published' => '2026-01-27T15:29:31Z',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => [a_string_matching(%r{/followers$})],
|
||||
'object' => a_hash_including(
|
||||
'id' => tag_manager.uri_for(status)
|
||||
),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
end
|
||||
|
|
@ -51,5 +51,46 @@ RSpec.describe ActivityPub::DistributionWorker do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a reblog' do
|
||||
before do
|
||||
follower.follow!(reblog.account)
|
||||
end
|
||||
|
||||
context 'when the reblogged status is not private' do
|
||||
let(:status) { Fabricate(:status) }
|
||||
let(:reblog) { Fabricate(:status, reblog: status) }
|
||||
|
||||
it 'delivers an activity without inlining the status' do
|
||||
expected_json = {
|
||||
type: 'Announce',
|
||||
object: ActivityPub::TagManager.instance.uri_for(status),
|
||||
}
|
||||
|
||||
expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(expected_json), reblog.account.id, 'http://example.com', anything]]) do
|
||||
subject.perform(reblog.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the reblogged status is private' do
|
||||
let(:status) { Fabricate(:status, visibility: :private) }
|
||||
let(:reblog) { Fabricate(:status, reblog: status, account: status.account) }
|
||||
|
||||
it 'delivers an activity that inlines the status' do
|
||||
expected_json = {
|
||||
type: 'Announce',
|
||||
object: a_hash_including({
|
||||
id: ActivityPub::TagManager.instance.uri_for(status),
|
||||
type: 'Note',
|
||||
}),
|
||||
}
|
||||
|
||||
expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(expected_json), reblog.account.id, 'http://example.com', anything]]) do
|
||||
subject.perform(reblog.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user