2
0

Add support for ingesting quote policies (#34479)

This commit is contained in:
Claire
2025-04-28 10:48:27 +02:00
committed by GitHub
parent 1a1f3f037d
commit 9ed6a14d45
7 changed files with 181 additions and 4 deletions

View File

@@ -83,7 +83,12 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end
def process_status_params
@status_parser = ActivityPub::Parser::StatusParser.new(@json, followers_collection: @account.followers_url, object: @object)
@status_parser = ActivityPub::Parser::StatusParser.new(
@json,
followers_collection: @account.followers_url,
actor_uri: ActivityPub::TagManager.instance.uri_for(@account),
object: @object
)
attachment_ids = process_attachments.take(Status::MEDIA_ATTACHMENTS_LIMIT).map(&:id)
@@ -105,6 +110,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
media_attachment_ids: attachment_ids,
ordered_media_attachment_ids: attachment_ids,
poll: process_poll,
quote_approval_policy: @status_parser.quote_policy,
}
end

View File

@@ -8,6 +8,7 @@ class ActivityPub::Parser::StatusParser
# @param [Hash] json
# @param [Hash] options
# @option options [String] :followers_collection
# @option options [String] :actor_uri
# @option options [Hash] :object
def initialize(json, **options)
@json = json
@@ -101,6 +102,18 @@ class ActivityPub::Parser::StatusParser
@object.dig(:shares, :totalItems)
end
def quote_policy
flags = 0
policy = @object.dig('interactionPolicy', 'canQuote')
return flags if policy.blank?
flags |= quote_subpolicy(policy['automaticApproval'])
flags <<= 16
flags |= quote_subpolicy(policy['manualApproval'])
flags
end
def quote_uri
%w(quote _misskey_quote quoteUrl quoteUri).filter_map do |key|
value_or_id(as_array(@object[key]).first)
@@ -113,6 +126,29 @@ class ActivityPub::Parser::StatusParser
private
def quote_subpolicy(subpolicy)
flags = 0
allowed_actors = as_array(subpolicy)
allowed_actors.uniq!
flags |= Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] if allowed_actors.delete('as:Public') || allowed_actors.delete('Public') || allowed_actors.delete('https://www.w3.org/ns/activitystreams#Public')
flags |= Status::QUOTE_APPROVAL_POLICY_FLAGS[:followers] if allowed_actors.delete(@options[:followers_collection])
# TODO: we don't actually store that collection URI
# flags |= Status::QUOTE_APPROVAL_POLICY_FLAGS[:followed]
# Remove the special-meaning actor URI
allowed_actors.delete(@options[:actor_uri])
# Tagged users are always allowed, so remove them
allowed_actors -= as_array(@object['tag']).filter_map { |tag| tag['href'] if equals_or_includes?(tag['type'], 'Mention') }
# Any unrecognized actor is marked as unknown
flags |= Status::QUOTE_APPROVAL_POLICY_FLAGS[:unknown] unless allowed_actors.empty?
flags
end
def raw_language_code
if content_language_map?
@object['contentMap'].keys.first

View File

@@ -28,6 +28,7 @@
# trendable :boolean
# ordered_media_attachment_ids :bigint(8) is an Array
# fetched_replies_at :datetime
# quote_approval_policy :integer default(0), not null
#
class Status < ApplicationRecord
@@ -44,6 +45,13 @@ class Status < ApplicationRecord
MEDIA_ATTACHMENTS_LIMIT = 4
QUOTE_APPROVAL_POLICY_FLAGS = {
unknown: (1 << 0),
public: (1 << 1),
followers: (1 << 2),
followed: (1 << 3),
}.freeze
rate_limit by: :account, family: :statuses
self.discard_column = :deleted_at

View File

@@ -10,7 +10,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
@activity_json = activity_json
@json = object_json
@status_parser = ActivityPub::Parser::StatusParser.new(@json)
@status_parser = ActivityPub::Parser::StatusParser.new(@json, followers_collection: status.account.followers_url, actor_uri: ActivityPub::TagManager.instance.uri_for(status.account))
@uri = @status_parser.uri
@status = status
@account = status.account
@@ -41,6 +41,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
Status.transaction do
record_previous_edit!
update_media_attachments!
update_interaction_policies!
update_poll!
update_immediate_attributes!
update_metadata!
@@ -62,12 +63,17 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
def handle_implicit_update!
with_redis_lock("create:#{@uri}") do
update_interaction_policies!
update_poll!(allow_significant_changes: false)
queue_poll_notifications!
update_counts!
end
end
def update_interaction_policies!
@status.quote_approval_policy = @status_parser.quote_policy
end
def update_media_attachments!
previous_media_attachments = @status.media_attachments.to_a
previous_media_attachments_ids = @status.ordered_media_attachment_ids || previous_media_attachments.map(&:id)