@ -6,6 +6,15 @@ class PostStatusService < BaseService
MIN_SCHEDULE_OFFSET = 5 . minutes . freeze
class UnexpectedMentionsError < StandardError
attr_reader :accounts
def initialize ( message , accounts )
super ( message )
@accounts = accounts
end
end
# Post a text status update, fetch and notify remote users mentioned
# @param [Account] account Account from which to post
# @param [Hash] options
@ -21,6 +30,7 @@ class PostStatusService < BaseService
# @option [Doorkeeper::Application] :application
# @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
# @return [Status]
def call ( account , options = { } )
@account = account
@ -63,12 +73,25 @@ class PostStatusService < BaseService
end
def process_status!
@status = @account . statuses . new ( status_attributes )
process_mentions_service . call ( @status , save_records : false )
safeguard_mentions! ( @status )
# The following transaction block is needed to wrap the UPDATEs to
# the media attachments when the status is created
ApplicationRecord . transaction do
@status = @account . statuses . create! ( status_attributes )
@status . save!
end
end
def safeguard_mentions! ( status )
return if @options [ :allowed_mentions ] . nil?
expected_account_ids = @options [ :allowed_mentions ] . map ( & :to_i )
unexpected_accounts = status . mentions . map ( & :account ) . to_a . reject { | mentioned_account | expected_account_ids . include? ( mentioned_account . id ) }
return if unexpected_accounts . empty?
raise UnexpectedMentionsError . new ( 'Post would be sent to unexpected accounts' , unexpected_accounts )
end
def schedule_status!
@ -93,7 +116,6 @@ class PostStatusService < BaseService
def postprocess_status!
process_hashtags_service . call ( @status )
process_mentions_service . call ( @status )
Trends . tags . register ( @status )
LinkCrawlWorker . perform_async ( @status . id )
DistributionWorker . perform_async ( @status . id )