process_mentions_service.rb 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. # frozen_string_literal: true
  2. class ProcessMentionsService < BaseService
  3. include Payloadable
  4. # Scan status for mentions and fetch remote mentioned users, create
  5. # local mention pointers, send Salmon notifications to mentioned
  6. # remote users
  7. # @param [Status] status
  8. def call(status)
  9. return unless status.local?
  10. @status = status
  11. mentions = []
  12. status.text = status.text.gsub(Account::MENTION_RE) do |match|
  13. username, domain = Regexp.last_match(1).split('@')
  14. domain = begin
  15. if TagManager.instance.local_domain?(domain)
  16. nil
  17. else
  18. TagManager.instance.normalize_domain(domain)
  19. end
  20. end
  21. mentioned_account = Account.find_remote(username, domain)
  22. if mention_undeliverable?(mentioned_account)
  23. begin
  24. mentioned_account = resolve_account_service.call(Regexp.last_match(1))
  25. rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError
  26. mentioned_account = nil
  27. end
  28. end
  29. next match if mention_undeliverable?(mentioned_account) || mentioned_account&.suspended?
  30. mention = mentioned_account.mentions.new(status: status)
  31. mentions << mention if mention.save
  32. "@#{mentioned_account.acct}"
  33. end
  34. status.save!
  35. check_for_spam(status)
  36. mentions.each { |mention| create_notification(mention) }
  37. end
  38. private
  39. def mention_undeliverable?(mentioned_account)
  40. mentioned_account.nil? || (!mentioned_account.local? && mentioned_account.ostatus?)
  41. end
  42. def create_notification(mention)
  43. mentioned_account = mention.account
  44. if mentioned_account.local?
  45. LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name, :mention)
  46. elsif mentioned_account.activitypub?
  47. ActivityPub::DeliveryWorker.perform_async(activitypub_json, mention.status.account_id, mentioned_account.inbox_url, { synchronize_followers: !mention.status.distributable? })
  48. end
  49. end
  50. def activitypub_json
  51. return @activitypub_json if defined?(@activitypub_json)
  52. @activitypub_json = Oj.dump(serialize_payload(ActivityPub::ActivityPresenter.from_status(@status), ActivityPub::ActivitySerializer, signer: @status.account))
  53. end
  54. def resolve_account_service
  55. ResolveAccountService.new
  56. end
  57. def check_for_spam(status)
  58. SpamCheck.perform(status)
  59. end
  60. end