1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
# frozen_string_literal: true
class ActivityPub::FetchCollectionItemsService < BaseService
include JsonLdHelper
def call(collection_or_uri, account, page_limit: 10, item_limit: 100, allow_synchronous_requests: true)
@account = account
@allow_synchronous_requests = allow_synchronous_requests
collection_items(collection_or_uri, page_limit, item_limit)
end
private
def collection_items(collection_or_uri, page_limit, item_limit)
collection = fetch_collection(collection_or_uri)
return [] unless collection.is_a?(Hash)
collection = fetch_collection(collection['first']) if collection['first'].present?
page_count = 0
item_count = 0
items = []
while collection.present? && collection.is_a?(Hash) && collection['type'].present?
batch = case collection['type']
when 'Collection', 'CollectionPage'
collection['items'].each
when 'OrderedCollection', 'OrderedCollectionPage'
collection['orderedItems']
end
batch_size = [batch.count, item_limit - item_count].min
items.push(
batch.take(batch_size)
.map { |item| value_or_id(item) }
.reject { |uri| unsupported_uri_scheme?(uri) || ActivityPub::TagManager.instance.local_uri?(uri) }
)
item_count += batch_size
page_count += 1
break unless item_count < item_limit && page_count < page_limit && collection['next'].present?
collection = fetch_collection(collection['next'])
end
items.uniq
end
def fetch_collection(collection_or_uri)
return collection_or_uri if collection_or_uri.is_a?(Hash)
return unless @allow_synchronous_requests
return if invalid_origin?(collection_or_uri)
on_behalf_of = @account.present? ? @account.followers.local.first : nil
fetch_resource_without_id_validation(collection_or_uri, on_behalf_of, true)
rescue Mastodon::UnexpectedResponseError
nil
end
end
|