forked from asonix/mastodon
There are edge cases where requests to certain hosts timeout when using the vanilla HTTP.rb gem, which the goldfinger gem uses. Now that we no longer need to support OStatus servers, webfinger logic is so simple that there is no point encapsulating it in a gem, so we can just use our own Request class. With that, we benefit from more robust timeout code and IPv4/IPv6 resolution. Fix #14091
79 lines
2.3 KiB
Ruby
79 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class ProcessMentionsService < BaseService
|
|
include Payloadable
|
|
|
|
# Scan status for mentions and fetch remote mentioned users, create
|
|
# local mention pointers, send Salmon notifications to mentioned
|
|
# remote users
|
|
# @param [Status] status
|
|
def call(status)
|
|
return unless status.local?
|
|
|
|
@status = status
|
|
mentions = []
|
|
|
|
status.text = status.text.gsub(Account::MENTION_RE) do |match|
|
|
username, domain = Regexp.last_match(1).split('@')
|
|
|
|
domain = begin
|
|
if TagManager.instance.local_domain?(domain)
|
|
nil
|
|
else
|
|
TagManager.instance.normalize_domain(domain)
|
|
end
|
|
end
|
|
|
|
mentioned_account = Account.find_remote(username, domain)
|
|
|
|
if mention_undeliverable?(mentioned_account)
|
|
begin
|
|
mentioned_account = resolve_account_service.call(Regexp.last_match(1))
|
|
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError
|
|
mentioned_account = nil
|
|
end
|
|
end
|
|
|
|
next match if mention_undeliverable?(mentioned_account) || mentioned_account&.suspended?
|
|
|
|
mention = mentioned_account.mentions.new(status: status)
|
|
mentions << mention if mention.save
|
|
|
|
"@#{mentioned_account.acct}"
|
|
end
|
|
|
|
status.save!
|
|
check_for_spam(status)
|
|
|
|
mentions.each { |mention| create_notification(mention) }
|
|
end
|
|
|
|
private
|
|
|
|
def mention_undeliverable?(mentioned_account)
|
|
mentioned_account.nil? || (!mentioned_account.local? && mentioned_account.ostatus?)
|
|
end
|
|
|
|
def create_notification(mention)
|
|
mentioned_account = mention.account
|
|
|
|
if mentioned_account.local?
|
|
LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name, :mention)
|
|
elsif mentioned_account.activitypub?
|
|
ActivityPub::DeliveryWorker.perform_async(activitypub_json, mention.status.account_id, mentioned_account.inbox_url)
|
|
end
|
|
end
|
|
|
|
def activitypub_json
|
|
return @activitypub_json if defined?(@activitypub_json)
|
|
@activitypub_json = Oj.dump(serialize_payload(ActivityPub::ActivityPresenter.from_status(@status), ActivityPub::ActivitySerializer, signer: @status.account))
|
|
end
|
|
|
|
def resolve_account_service
|
|
ResolveAccountService.new
|
|
end
|
|
|
|
def check_for_spam(status)
|
|
SpamCheck.perform(status)
|
|
end
|
|
end
|