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.

147 lines
4.7 KiB

  1. # frozen_string_literal: true
  2. class ProcessInteractionService < BaseService
  3. include AuthorExtractor
  4. include Authorization
  5. # Record locally the remote interaction with our user
  6. # @param [String] envelope Salmon envelope
  7. # @param [Account] target_account Account the Salmon was addressed to
  8. def call(envelope, target_account)
  9. body = salmon.unpack(envelope)
  10. xml = Nokogiri::XML(body)
  11. xml.encoding = 'utf-8'
  12. account = author_from_xml(xml.at_xpath('/xmlns:entry', xmlns: TagManager::XMLNS))
  13. return if account.nil? || account.suspended?
  14. if salmon.verify(envelope, account.keypair)
  15. RemoteProfileUpdateWorker.perform_async(account.id, body.force_encoding('UTF-8'), true)
  16. case verb(xml)
  17. when :follow
  18. follow!(account, target_account) unless target_account.locked? || target_account.blocking?(account) || target_account.domain_blocking?(account.domain)
  19. when :request_friend
  20. follow_request!(account, target_account) unless !target_account.locked? || target_account.blocking?(account) || target_account.domain_blocking?(account.domain)
  21. when :authorize
  22. authorize_follow_request!(account, target_account)
  23. when :reject
  24. reject_follow_request!(account, target_account)
  25. when :unfollow
  26. unfollow!(account, target_account)
  27. when :favorite
  28. favourite!(xml, account)
  29. when :unfavorite
  30. unfavourite!(xml, account)
  31. when :post
  32. add_post!(body, account) if mentions_account?(xml, target_account)
  33. when :share
  34. add_post!(body, account) unless status(xml).nil?
  35. when :delete
  36. delete_post!(xml, account)
  37. when :block
  38. reflect_block!(account, target_account)
  39. when :unblock
  40. reflect_unblock!(account, target_account)
  41. end
  42. end
  43. rescue Goldfinger::Error, HTTP::Error, OStatus2::BadSalmonError, Mastodon::NotPermittedError
  44. nil
  45. end
  46. private
  47. def mentions_account?(xml, account)
  48. xml.xpath('/xmlns:entry/xmlns:link[@rel="mentioned"]', xmlns: TagManager::XMLNS).each { |mention_link| return true if [TagManager.instance.uri_for(account), TagManager.instance.url_for(account)].include?(mention_link.attribute('href').value) }
  49. false
  50. end
  51. def verb(xml)
  52. raw = xml.at_xpath('//activity:verb', activity: TagManager::AS_XMLNS).content
  53. TagManager::VERBS.key(raw)
  54. rescue
  55. :post
  56. end
  57. def follow!(account, target_account)
  58. follow = account.follow!(target_account)
  59. NotifyService.new.call(target_account, follow)
  60. end
  61. def follow_request!(account, target_account)
  62. follow_request = FollowRequest.create!(account: account, target_account: target_account)
  63. NotifyService.new.call(target_account, follow_request)
  64. end
  65. def authorize_follow_request!(account, target_account)
  66. follow_request = FollowRequest.find_by(account: target_account, target_account: account)
  67. follow_request&.authorize!
  68. Pubsubhubbub::SubscribeWorker.perform_async(account.id) unless account.subscribed?
  69. end
  70. def reject_follow_request!(account, target_account)
  71. follow_request = FollowRequest.find_by(account: target_account, target_account: account)
  72. follow_request&.reject!
  73. end
  74. def unfollow!(account, target_account)
  75. account.unfollow!(target_account)
  76. end
  77. def reflect_block!(account, target_account)
  78. UnfollowService.new.call(target_account, account) if target_account.following?(account)
  79. account.block!(target_account)
  80. end
  81. def reflect_unblock!(account, target_account)
  82. UnblockService.new.call(account, target_account)
  83. end
  84. def delete_post!(xml, account)
  85. status = Status.find(xml.at_xpath('//xmlns:id', xmlns: TagManager::XMLNS).content)
  86. return if status.nil?
  87. authorize_with account, status, :destroy?
  88. RemovalWorker.perform_async(status.id)
  89. end
  90. def favourite!(xml, from_account)
  91. current_status = status(xml)
  92. return if current_status.nil?
  93. favourite = current_status.favourites.where(account: from_account).first_or_create!(account: from_account)
  94. NotifyService.new.call(current_status.account, favourite)
  95. end
  96. def unfavourite!(xml, from_account)
  97. current_status = status(xml)
  98. return if current_status.nil?
  99. favourite = current_status.favourites.where(account: from_account).first
  100. favourite&.destroy
  101. end
  102. def add_post!(body, account)
  103. ProcessingWorker.perform_async(account.id, body.force_encoding('UTF-8'))
  104. end
  105. def status(xml)
  106. uri = activity_id(xml)
  107. return nil unless TagManager.instance.local_id?(uri)
  108. Status.find(TagManager.instance.unique_tag_to_local_id(uri, 'Status'))
  109. end
  110. def activity_id(xml)
  111. xml.at_xpath('//activity:object', activity: TagManager::AS_XMLNS).at_xpath('./xmlns:id', xmlns: TagManager::XMLNS).content
  112. end
  113. def salmon
  114. @salmon ||= OStatus2::Salmon.new
  115. end
  116. end