闭社主体 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.

136 lines
4.4 KiB

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