Merge commit 'eaa1f9e450' into kb_migration

This commit is contained in:
KMY 2023-07-07 07:20:37 +09:00
commit 2a813d517d
73 changed files with 987 additions and 72 deletions

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
class ActivityPub::FetchReferencesService < BaseService
include JsonLdHelper
def call(status, collection_or_uri)
@account = status.account
collection_items(collection_or_uri)&.map { |item| value_or_id(item) }
end
private
def collection_items(collection_or_uri)
collection = fetch_collection(collection_or_uri)
return unless collection.is_a?(Hash) && collection['first'].present?
all_items = []
collection = fetch_collection(collection['first'])
while collection.is_a?(Hash)
items = begin
case collection['type']
when 'Collection', 'CollectionPage'
collection['items']
when 'OrderedCollection', 'OrderedCollectionPage'
collection['orderedItems']
end
end
break if items.blank?
all_items.concat(items)
break if all_items.size >= StatusReferenceValidator::LIMIT
collection = collection['next'].present? ? fetch_collection(collection['next']) : nil
end
all_items
end
def fetch_collection(collection_or_uri)
return collection_or_uri if collection_or_uri.is_a?(Hash)
return if invalid_origin?(collection_or_uri)
fetch_resource_without_id_validation(collection_or_uri, nil, true)
end
end

View file

@ -29,6 +29,8 @@ class ApproveAppealService < BaseService
undo_delete_statuses!
when 'mark_statuses_as_sensitive'
undo_mark_statuses_as_sensitive!
when 'force_cw'
undo_force_cw!
when 'sensitive'
undo_sensitive!
when 'silence'
@ -58,6 +60,13 @@ class ApproveAppealService < BaseService
end
end
def undo_force_cw!
representative_account = Account.representative
@strike.statuses.includes(:media_attachments).each do |status|
UpdateStatusService.new.call(status, representative_account.id, spoiler_text: '')
end
end
def undo_sensitive!
target_account.unsensitize!
end

View file

@ -34,6 +34,7 @@ class PostStatusService < BaseService
# @option [String] :idempotency Optional idempotency key
# @option [Boolean] :with_rate_limit
# @option [Enumerable] :allowed_mentions Optional array of expected mentioned account IDs, raises `UnexpectedMentionsError` if unexpected accounts end up in mentions
# @option [Enumerable] :status_reference_ids Optional array
# @return [Status]
def call(account, options = {})
@account = account
@ -78,6 +79,7 @@ class PostStatusService < BaseService
@markdown = @options[:markdown] || false
@scheduled_at = @options[:scheduled_at]&.to_datetime
@scheduled_at = nil if scheduled_in_the_past?
@reference_ids = (@options[:status_reference_ids] || []).map(&:to_i).filter(&:positive?)
rescue ArgumentError
raise ActiveRecord::RecordInvalid
end
@ -146,6 +148,7 @@ class PostStatusService < BaseService
def postprocess_status!
process_hashtags_service.call(@status)
ProcessReferencesWorker.perform_async(@status.id, @reference_ids, [])
Trends.tags.register(@status)
LinkCrawlWorker.perform_async(@status.id)
DistributionWorker.perform_async(@status.id)
@ -221,6 +224,7 @@ class PostStatusService < BaseService
media_attachments: @media || [],
ordered_media_attachment_ids: (@options[:media_ids] || []).map(&:to_i) & @media.map(&:id),
thread: @in_reply_to,
status_reference_ids: @status_reference_ids,
poll_attributes: poll_attributes,
sensitive: @sensitive,
spoiler_text: @options[:spoiler_text] || '',

View file

@ -0,0 +1,88 @@
# frozen_string_literal: true
class ProcessReferencesService < BaseService
include Payloadable
DOMAIN = ENV['WEB_DOMAIN'] || ENV.fetch('LOCAL_DOMAIN', nil)
REFURL_EXP = /(RT|QT|BT|RN|RE)((:|;)?\s+|:|;)(#{URI::DEFAULT_PARSER.make_regexp(%w(http https))})/
def call(status, reference_parameters, save_records: true, urls: nil)
@status = status
@reference_parameters = reference_parameters || []
@save_records = save_records
@urls = urls || []
old_references
return unless added_references.size.positive? || removed_references.size.positive?
StatusReference.transaction do
remove_old_references
add_references
@status.save! if @save_records
create_notifications!
end
end
private
def references
@references = @reference_parameters + scan_text!
end
def old_references
@old_references = @status.references.pluck(:id)
end
def added_references
(references - old_references).uniq
end
def removed_references
(old_references - references).uniq
end
def scan_text!
text = @status.account.local? ? @status.text : @status.text.gsub(%r{</?[^>]*>}, '')
@scan_text = fetch_statuses!(text.scan(REFURL_EXP).pluck(3).uniq).map(&:id).uniq.filter { |status_id| !status_id.zero? }
end
def fetch_statuses!(urls)
(urls + @urls)
.map { |url| ResolveURLService.new.call(url) }
.filter { |status| status }
end
def add_references
return if added_references.empty?
@added_objects = []
statuses = Status.where(id: added_references)
statuses.each do |status|
@added_objects << @status.reference_objects.new(target_status: status)
status.increment_count!(:status_referred_by_count)
end
end
def create_notifications!
local_reference_objects = @added_objects.filter { |ref| ref.target_status.account.local? }
return if local_reference_objects.empty?
LocalNotificationWorker.push_bulk(local_reference_objects) do |ref|
[ref.target_status.account_id, ref.id, 'StatusReference', 'status_reference']
end
end
def remove_old_references
return if removed_references.empty?
statuses = Status.where(id: removed_references)
@status.reference_objects.where(target_status: statuses).destroy_all
statuses.each do |status|
status.decrement_count!(:status_referred_by_count)
end
end
end

View file

@ -46,6 +46,7 @@ class RemoveStatusService < BaseService
remove_from_public
remove_from_media if @status.with_media?
remove_media
decrement_references
end
@status.destroy! if permanently?
@ -123,6 +124,12 @@ class RemoveStatusService < BaseService
end
end
def decrement_references
@status.references.each do |ref|
ref.decrement_count!(:status_referred_by_count)
end
end
def remove_from_hashtags
@account.featured_tags.where(tag_id: @status.tags.map(&:id)).each do |featured_tag|
featured_tag.decrement(@status.id)

View file

@ -142,6 +142,7 @@ class UpdateStatusService < BaseService
def update_metadata!
ProcessHashtagsService.new.call(@status)
ProcessMentionsService.new.call(@status)
ProcessReferencesWorker.perform_async(@status.id, (@options[:status_reference_ids] || []).map(&:to_i).filter(&:positive?), [])
end
def broadcast_updates!