闭社主体 forked from https://github.com/tootsuite/mastodon
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.

151 lines
5.0 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: OStatus::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 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: OStatus::TagManager::XMLNS).each { |mention_link| return true if [OStatus::TagManager.instance.uri_for(account), OStatus::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: OStatus::TagManager::AS_XMLNS).content
  53. OStatus::TagManager::VERBS.key(raw)
  54. rescue
  55. :post
  56. end
  57. def follow!(account, target_account)
  58. follow = account.follow!(target_account)
  59. FollowRequest.find_by(account: account, target_account: target_account)&.destroy
  60. NotifyService.new.call(target_account, follow)
  61. end
  62. def follow_request!(account, target_account)
  63. return if account.requested?(target_account)
  64. follow_request = FollowRequest.create!(account: account, target_account: target_account)
  65. NotifyService.new.call(target_account, follow_request)
  66. end
  67. def authorize_follow_request!(account, target_account)
  68. follow_request = FollowRequest.find_by(account: target_account, target_account: account)
  69. follow_request&.authorize!
  70. Pubsubhubbub::SubscribeWorker.perform_async(account.id) unless account.subscribed?
  71. end
  72. def reject_follow_request!(account, target_account)
  73. follow_request = FollowRequest.find_by(account: target_account, target_account: account)
  74. follow_request&.reject!
  75. end
  76. def unfollow!(account, target_account)
  77. account.unfollow!(target_account)
  78. FollowRequest.find_by(account: account, target_account: target_account)&.destroy
  79. end
  80. def reflect_block!(account, target_account)
  81. UnfollowService.new.call(target_account, account) if target_account.following?(account)
  82. account.block!(target_account)
  83. end
  84. def reflect_unblock!(account, target_account)
  85. UnblockService.new.call(account, target_account)
  86. end
  87. def delete_post!(xml, account)
  88. status = Status.find(xml.at_xpath('//xmlns:id', xmlns: OStatus::TagManager::XMLNS).content)
  89. return if status.nil?
  90. authorize_with account, status, :destroy?
  91. RemovalWorker.perform_async(status.id)
  92. end
  93. def favourite!(xml, from_account)
  94. current_status = status(xml)
  95. return if current_status.nil?
  96. favourite = current_status.favourites.where(account: from_account).first_or_create!(account: from_account)
  97. NotifyService.new.call(current_status.account, favourite)
  98. end
  99. def unfavourite!(xml, from_account)
  100. current_status = status(xml)
  101. return if current_status.nil?
  102. favourite = current_status.favourites.where(account: from_account).first
  103. favourite&.destroy
  104. end
  105. def add_post!(body, account)
  106. ProcessingWorker.perform_async(account.id, body.force_encoding('UTF-8'))
  107. end
  108. def status(xml)
  109. uri = activity_id(xml)
  110. return nil unless OStatus::TagManager.instance.local_id?(uri)
  111. Status.find(OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Status'))
  112. end
  113. def activity_id(xml)
  114. xml.at_xpath('//activity:object', activity: OStatus::TagManager::AS_XMLNS).at_xpath('./xmlns:id', xmlns: OStatus::TagManager::XMLNS).content
  115. end
  116. def salmon
  117. @salmon ||= OStatus2::Salmon.new
  118. end
  119. end