The code powering m.abunchtell.com https://m.abunchtell.com
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.
 
 
 
 

159 lines
4.7 KiB

  1. # frozen_string_literal: true
  2. class RemoveStatusService < BaseService
  3. include StreamEntryRenderer
  4. def call(status, **options)
  5. @payload = Oj.dump(event: :delete, payload: status.id.to_s)
  6. @status = status
  7. @account = status.account
  8. @tags = status.tags.pluck(:name).to_a
  9. @mentions = status.active_mentions.includes(:account).to_a
  10. @reblogs = status.reblogs.to_a
  11. @stream_entry = status.stream_entry
  12. @options = options
  13. remove_from_self if status.account.local?
  14. remove_from_followers
  15. remove_from_lists
  16. remove_from_affected
  17. remove_reblogs
  18. remove_from_hashtags
  19. remove_from_public
  20. remove_from_media if status.media_attachments.any?
  21. @status.destroy!
  22. # There is no reason to send out Undo activities when the
  23. # cause is that the original object has been removed, since
  24. # original object being removed implicitly removes reblogs
  25. # of it. The Delete activity of the original is forwarded
  26. # separately.
  27. return if !@account.local? || @options[:original_removed]
  28. remove_from_remote_followers
  29. remove_from_remote_affected
  30. end
  31. private
  32. def remove_from_self
  33. FeedManager.instance.unpush_from_home(@account, @status)
  34. end
  35. def remove_from_followers
  36. @account.followers_for_local_distribution.reorder(nil).find_each do |follower|
  37. FeedManager.instance.unpush_from_home(follower, @status)
  38. end
  39. end
  40. def remove_from_lists
  41. @account.lists_for_local_distribution.select(:id, :account_id).reorder(nil).find_each do |list|
  42. FeedManager.instance.unpush_from_list(list, @status)
  43. end
  44. end
  45. def remove_from_affected
  46. @mentions.map(&:account).select(&:local?).each do |account|
  47. Redis.current.publish("timeline:#{account.id}", @payload)
  48. end
  49. end
  50. def remove_from_remote_affected
  51. # People who got mentioned in the status, or who
  52. # reblogged it from someone else might not follow
  53. # the author and wouldn't normally receive the
  54. # delete notification - so here, we explicitly
  55. # send it to them
  56. target_accounts = (@mentions.map(&:account).reject(&:local?) + @reblogs.map(&:account).reject(&:local?))
  57. target_accounts << @status.reblog.account if @status.reblog? && !@status.reblog.account.local?
  58. target_accounts.uniq!(&:id)
  59. # Ostatus
  60. NotificationWorker.push_bulk(target_accounts.select(&:ostatus?).uniq(&:domain)) do |target_account|
  61. [salmon_xml, @account.id, target_account.id]
  62. end
  63. # ActivityPub
  64. ActivityPub::DeliveryWorker.push_bulk(target_accounts.select(&:activitypub?).uniq(&:inbox_url)) do |target_account|
  65. [signed_activity_json, @account.id, target_account.inbox_url]
  66. end
  67. end
  68. def remove_from_remote_followers
  69. # OStatus
  70. Pubsubhubbub::RawDistributionWorker.perform_async(salmon_xml, @account.id)
  71. # ActivityPub
  72. ActivityPub::DeliveryWorker.push_bulk(@account.followers.inboxes) do |inbox_url|
  73. [signed_activity_json, @account.id, inbox_url]
  74. end
  75. relay! if relayable?
  76. end
  77. def relayable?
  78. @status.public_visibility?
  79. end
  80. def relay!
  81. ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
  82. [signed_activity_json, @account.id, inbox_url]
  83. end
  84. end
  85. def salmon_xml
  86. @salmon_xml ||= stream_entry_to_xml(@stream_entry)
  87. end
  88. def signed_activity_json
  89. @signed_activity_json ||= Oj.dump(ActivityPub::LinkedDataSignature.new(activity_json).sign!(@account))
  90. end
  91. def activity_json
  92. @activity_json ||= ActiveModelSerializers::SerializableResource.new(
  93. @status,
  94. serializer: @status.reblog? ? ActivityPub::UndoAnnounceSerializer : ActivityPub::DeleteSerializer,
  95. adapter: ActivityPub::Adapter
  96. ).as_json
  97. end
  98. def remove_reblogs
  99. # We delete reblogs of the status before the original status,
  100. # because once original status is gone, reblogs will disappear
  101. # without us being able to do all the fancy stuff
  102. @reblogs.each do |reblog|
  103. RemoveStatusService.new.call(reblog, original_removed: true)
  104. end
  105. end
  106. def remove_from_hashtags
  107. return unless @status.public_visibility?
  108. @tags.each do |hashtag|
  109. Redis.current.publish("timeline:hashtag:#{hashtag}", @payload)
  110. Redis.current.publish("timeline:hashtag:#{hashtag}:local", @payload) if @status.local?
  111. end
  112. end
  113. def remove_from_public
  114. return unless @status.public_visibility?
  115. Redis.current.publish('timeline:public', @payload)
  116. Redis.current.publish('timeline:public:local', @payload) if @status.local?
  117. end
  118. def remove_from_media
  119. return unless @status.public_visibility?
  120. Redis.current.publish('timeline:public:media', @payload)
  121. Redis.current.publish('timeline:public:local:media', @payload) if @status.local?
  122. end
  123. def redis
  124. Redis.current
  125. end
  126. end