activity.rb 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. # frozen_string_literal: true
  2. class ActivityPub::Activity
  3. include JsonLdHelper
  4. include Redisable
  5. include Lockable
  6. SUPPORTED_TYPES = %w(Note Question).freeze
  7. CONVERTED_TYPES = %w(Image Audio Video Article Page Event).freeze
  8. def initialize(json, account, **options)
  9. @json = json
  10. @account = account
  11. @object = @json['object']
  12. @options = options
  13. end
  14. def perform
  15. raise NotImplementedError
  16. end
  17. class << self
  18. def factory(json, account, **options)
  19. @json = json
  20. klass&.new(json, account, **options)
  21. end
  22. private
  23. def klass
  24. case @json['type']
  25. when 'Create'
  26. ActivityPub::Activity::Create
  27. when 'Announce'
  28. ActivityPub::Activity::Announce
  29. when 'Delete'
  30. ActivityPub::Activity::Delete
  31. when 'Follow'
  32. ActivityPub::Activity::Follow
  33. when 'Like'
  34. ActivityPub::Activity::Like
  35. when 'Block'
  36. ActivityPub::Activity::Block
  37. when 'Update'
  38. ActivityPub::Activity::Update
  39. when 'Undo'
  40. ActivityPub::Activity::Undo
  41. when 'Accept'
  42. ActivityPub::Activity::Accept
  43. when 'Reject'
  44. ActivityPub::Activity::Reject
  45. when 'Flag'
  46. ActivityPub::Activity::Flag
  47. when 'Add'
  48. ActivityPub::Activity::Add
  49. when 'Remove'
  50. ActivityPub::Activity::Remove
  51. when 'Move'
  52. ActivityPub::Activity::Move
  53. end
  54. end
  55. end
  56. protected
  57. def status_from_uri(uri)
  58. ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
  59. end
  60. def account_from_uri(uri)
  61. ActivityPub::TagManager.instance.uri_to_resource(uri, Account)
  62. end
  63. def object_uri
  64. @object_uri ||= uri_from_bearcap(value_or_id(@object))
  65. end
  66. def unsupported_object_type?
  67. @object.is_a?(String) || !(supported_object_type? || converted_object_type?)
  68. end
  69. def supported_object_type?
  70. equals_or_includes_any?(@object['type'], SUPPORTED_TYPES)
  71. end
  72. def converted_object_type?
  73. equals_or_includes_any?(@object['type'], CONVERTED_TYPES)
  74. end
  75. def delete_arrived_first?(uri)
  76. redis.exists?("delete_upon_arrival:#{@account.id}:#{uri}")
  77. end
  78. def delete_later!(uri)
  79. redis.setex("delete_upon_arrival:#{@account.id}:#{uri}", 6.hours.seconds, true)
  80. end
  81. def status_from_object
  82. # If the status is already known, return it
  83. status = status_from_uri(object_uri)
  84. return status unless status.nil?
  85. # If the boosted toot is embedded and it is a self-boost, handle it like a Create
  86. unless unsupported_object_type?
  87. actor_id = value_or_id(first_of_value(@object['attributedTo']))
  88. if actor_id == @account.uri
  89. virtual_object = { 'type' => 'Create', 'actor' => actor_id, 'object' => @object }
  90. return ActivityPub::Activity.factory(virtual_object, @account, request_id: @options[:request_id]).perform
  91. end
  92. end
  93. fetch_remote_original_status
  94. end
  95. def dereference_object!
  96. return unless @object.is_a?(String)
  97. dereferencer = ActivityPub::Dereferencer.new(@object, permitted_origin: @account.uri, signature_account: signed_fetch_account)
  98. @object = dereferencer.object unless dereferencer.object.nil?
  99. end
  100. def signed_fetch_account
  101. return Account.find(@options[:delivered_to_account_id]) if @options[:delivered_to_account_id].present?
  102. first_mentioned_local_account || first_local_follower
  103. end
  104. def first_mentioned_local_account
  105. audience = (as_array(@json['to']) + as_array(@json['cc'])).map { |x| value_or_id(x) }.uniq
  106. local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
  107. .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
  108. return if local_usernames.empty?
  109. Account.local.where(username: local_usernames).first
  110. end
  111. def first_local_follower
  112. @account.followers.local.first
  113. end
  114. def follow_request_from_object
  115. @follow_request ||= FollowRequest.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
  116. end
  117. def follow_from_object
  118. @follow ||= ::Follow.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
  119. end
  120. def fetch_remote_original_status
  121. if object_uri.start_with?('http')
  122. return if ActivityPub::TagManager.instance.local_uri?(object_uri)
  123. ActivityPub::FetchRemoteStatusService.new.call(object_uri, on_behalf_of: @account.followers.local.first, request_id: @options[:request_id])
  124. elsif @object['url'].present?
  125. ::FetchRemoteStatusService.new.call(@object['url'], request_id: @options[:request_id])
  126. end
  127. end
  128. def fetch?
  129. !@options[:delivery]
  130. end
  131. def followed_by_local_accounts?
  132. @account.passive_relationships.exists? || @options[:relayed_through_account]&.passive_relationships&.exists?
  133. end
  134. def requested_through_relay?
  135. @options[:relayed_through_account] && Relay.find_by(inbox_url: @options[:relayed_through_account].inbox_url)&.enabled?
  136. end
  137. def reject_payload!
  138. Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_account] && "via #{@options[:relayed_through_account].uri}"}")
  139. nil
  140. end
  141. end