You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

71 lines
2.3 KiB

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