fetch_featured_collection_service.rb 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. # frozen_string_literal: true
  2. class ActivityPub::FetchFeaturedCollectionService < BaseService
  3. include JsonLdHelper
  4. def call(account)
  5. return if account.featured_collection_url.blank? || account.suspended? || account.local?
  6. @account = account
  7. @json = fetch_resource(@account.featured_collection_url, true, local_follower)
  8. return unless supported_context?(@json)
  9. process_items(collection_items(@json))
  10. end
  11. private
  12. def collection_items(collection)
  13. collection = fetch_collection(collection['first']) if collection['first'].present?
  14. return unless collection.is_a?(Hash)
  15. case collection['type']
  16. when 'Collection', 'CollectionPage'
  17. collection['items']
  18. when 'OrderedCollection', 'OrderedCollectionPage'
  19. collection['orderedItems']
  20. end
  21. end
  22. def fetch_collection(collection_or_uri)
  23. return collection_or_uri if collection_or_uri.is_a?(Hash)
  24. return if invalid_origin?(collection_or_uri)
  25. fetch_resource_without_id_validation(collection_or_uri, local_follower, true)
  26. end
  27. def process_items(items)
  28. status_ids = items.filter_map do |item|
  29. uri = value_or_id(item)
  30. next if ActivityPub::TagManager.instance.local_uri?(uri)
  31. status = ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: local_follower)
  32. next unless status&.account_id == @account.id
  33. status.id
  34. rescue ActiveRecord::RecordInvalid => e
  35. Rails.logger.debug "Invalid pinned status #{uri}: #{e.message}"
  36. nil
  37. end
  38. to_remove = []
  39. to_add = status_ids
  40. StatusPin.where(account: @account).pluck(:status_id).each do |status_id|
  41. if status_ids.include?(status_id)
  42. to_add.delete(status_id)
  43. else
  44. to_remove << status_id
  45. end
  46. end
  47. StatusPin.where(account: @account, status_id: to_remove).delete_all unless to_remove.empty?
  48. to_add.each do |status_id|
  49. StatusPin.create!(account: @account, status_id: status_id)
  50. end
  51. end
  52. def local_follower
  53. return @local_follower if defined?(@local_follower)
  54. @local_follower = @account.followers.local.without_suspended.first
  55. end
  56. end