From 9d4f18b984d6699bdf96e5f5963edfe80063426c Mon Sep 17 00:00:00 2001 From: Fire Demon Date: Sat, 27 Jun 2020 14:22:30 -0500 Subject: Monsterfork v2 Kaiju Commit 2020.06.27.1 - 2020.09.05.5 --- app/services/resolve_mentions_service.rb | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 app/services/resolve_mentions_service.rb (limited to 'app/services/resolve_mentions_service.rb') diff --git a/app/services/resolve_mentions_service.rb b/app/services/resolve_mentions_service.rb new file mode 100644 index 000000000..e51e9f1ef --- /dev/null +++ b/app/services/resolve_mentions_service.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +class ResolveMentionsService < BaseService + # Scan text for mentions and create local mention pointers + # @param [Status] status Status to attach to mention pointers + # @option [String] :text Text containing mentions to resolve (default: use status text) + # @option [Enumerable] :mentions Additional mentions to include + # @return [Array] Array containing text with mentions resolved (String) and mention pointers (Set) + def call(status, text: nil, mentions: []) + mentions = Mention.includes(:account).where(id: mentions.pluck(:id), accounts: { suspended_at: nil }).or(status.mentions.includes(:account)) + implicit_mention_acct_ids = mentions.active.pluck(:account_id).to_set + text = status.text if text.nil? + mentions = mentions.to_set + + 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 Goldfinger::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.where(status: status).first_or_create(status: status, silent: false) + mention.update(silent: false) if mention.silent? + + mentions << mention + implicit_mention_acct_ids.delete(mentioned_account.id) + + "@#{mentioned_account.acct}" + end + + Mention.where(id: implicit_mention_acct_ids).update_all(silent: true) + + [text, mentions] + end + + private + + def mention_undeliverable?(mentioned_account) + mentioned_account.nil? || (!mentioned_account.local? && mentioned_account.ostatus?) + end + + def resolve_account_service + ResolveAccountService.new + end +end -- cgit