distributed-press-api-client 0.5.0rc4 → 0.5.0rc6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/distributed_press/v1/social/client.rb +1 -0
- data/lib/distributed_press/v1/social/collection.rb +35 -0
- data/lib/distributed_press/v1/social/dereferencer.rb +45 -5
- data/lib/distributed_press/v1/social/reference.rb +27 -1
- data/lib/distributed_press/v1/social/referenced_object.rb +14 -2
- data/lib/distributed_press/version.rb +1 -1
- data/lib/httparty/parser/nokogiri.rb +21 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a07fc21fcba26bb8bcb854ec767be0030013b58341b93a17c4e4c084aeb7cf3
|
4
|
+
data.tar.gz: b72a76ca86a62730c0e8299c1089b5dd43b52154322c96f235015c07c902c386
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdb203374bb184030f0f6a1a3a5f6699e8f52579060a6f71e1bfea5420fbfc66519bbf3cb9ca62b3b2683034328ef0dcea016512b359ee340a3e53a4dd012fae
|
7
|
+
data.tar.gz: 1a7253c626fab33aa0adc50007b19394dcdfc1cd55360a5dbb291842663ee85a2daedbdb9a2e6048a9697889b2dae5c350b76882160da66d1b1803fed09a9b0e
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'referenced_object'
|
4
|
+
|
5
|
+
class DistributedPress
|
6
|
+
module V1
|
7
|
+
module Social
|
8
|
+
# A Collection or OrderedCollection is a an object with a list of
|
9
|
+
# items. Sometimes, collections are paginated, so we provide
|
10
|
+
# methods to traverse them.
|
11
|
+
class Collection < ReferencedObject
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
RECURSIVE_ATTRIBUTES = %w[items orderedItems first next].freeze
|
15
|
+
|
16
|
+
# If the Collection has items, yield them and keep processing
|
17
|
+
# any pages forward until the end.
|
18
|
+
#
|
19
|
+
# @todo Use totalItems from the starting object for validation
|
20
|
+
# @todo Implement lazy loading
|
21
|
+
def each(&block)
|
22
|
+
Enumerator.new do |enum|
|
23
|
+
RECURSIVE_ATTRIBUTES.each do |attribute|
|
24
|
+
next unless object.key?(attribute)
|
25
|
+
|
26
|
+
object[attribute].each(&block).each do |item|
|
27
|
+
enum << item
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'addressable'
|
4
4
|
require_relative 'reference'
|
5
5
|
require_relative 'referenced_object'
|
6
|
+
require_relative 'collection'
|
6
7
|
|
7
8
|
class DistributedPress
|
8
9
|
module V1
|
@@ -17,7 +18,7 @@ class DistributedPress
|
|
17
18
|
def _dump(_)
|
18
19
|
Marshal.dump(client)
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
def self._load(client)
|
22
23
|
new(client: Marshal.load(client))
|
23
24
|
end
|
@@ -25,22 +26,61 @@ class DistributedPress
|
|
25
26
|
# @param :client [DistributedPress::V1::Social::Client]
|
26
27
|
def initialize(client:)
|
27
28
|
@client = client
|
29
|
+
# @todo Replace with a class
|
28
30
|
@parser =
|
29
31
|
proc do |body, format|
|
32
|
+
next HTTParty::Parser.call(body, :html) if body&.starts_with? '<'
|
30
33
|
next HTTParty::Parser.call(body, format || :plain) unless body&.starts_with? '{'
|
31
34
|
|
32
|
-
|
35
|
+
object = HTTParty::Parser.call(body, :json)
|
36
|
+
|
37
|
+
# @todo Actually validate objects
|
38
|
+
case object['type']
|
39
|
+
when 'Collection', 'OrderedCollection', 'CollectionPage'
|
40
|
+
Collection.new(object: object, dereferencer: self)
|
41
|
+
else
|
42
|
+
ReferencedObject.new(object: object, dereferencer: self)
|
43
|
+
end
|
33
44
|
end
|
34
45
|
end
|
35
46
|
|
36
|
-
# Fetch a URI
|
47
|
+
# Fetch a URI, if it's an HTML page, look for the alternate
|
48
|
+
# version so we always have the correct activity.
|
37
49
|
#
|
50
|
+
# @todo Raise an error if the content-type is not supported?
|
38
51
|
# @param :uri [String, Addressable::URI]
|
39
52
|
# @return [HTTParty::Response]
|
40
53
|
def get(uri:)
|
41
|
-
|
54
|
+
response = nil
|
55
|
+
|
56
|
+
loop do
|
57
|
+
uri = uris(uri)
|
58
|
+
client = clients(uri)
|
59
|
+
response = client.get(endpoint: uri.path, parser: @parser)
|
60
|
+
|
61
|
+
# Break the loop if the request failed
|
62
|
+
break unless response.success?
|
63
|
+
# Or if it's not an HTML document
|
64
|
+
break unless response.parsed_response.is_a?(::Nokogiri::HTML5::Document)
|
65
|
+
|
66
|
+
link = response.parsed_response.css('link[rel=alternate]').find do |link|
|
67
|
+
next unless link['type']
|
68
|
+
next true if client.class::ACCEPT.include?(link['type'])
|
69
|
+
|
70
|
+
client.class::ACCEPT.any? do |accept|
|
71
|
+
link['type'].start_with? accept
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
break if link.nil?
|
76
|
+
break if link['href'].nil?
|
77
|
+
break if link['href'].empty?
|
78
|
+
|
79
|
+
# Start loop again with the new URI
|
80
|
+
uri = link['href']
|
81
|
+
end
|
42
82
|
|
43
|
-
|
83
|
+
response
|
44
84
|
end
|
45
85
|
|
46
86
|
# Gets a client for a URI
|
@@ -8,6 +8,11 @@ class DistributedPress
|
|
8
8
|
class Reference
|
9
9
|
extend Forwardable
|
10
10
|
|
11
|
+
# Public addressing doesn't lead to an activity
|
12
|
+
#
|
13
|
+
# @return [String]
|
14
|
+
PUBLIC = 'https://www.w3.org/ns/activitystreams#Public'
|
15
|
+
|
11
16
|
# @return [String]
|
12
17
|
attr_reader :uri
|
13
18
|
|
@@ -28,11 +33,32 @@ class DistributedPress
|
|
28
33
|
@object ||= dereferencer.get(uri: uri)
|
29
34
|
end
|
30
35
|
|
36
|
+
# Is this a public post?
|
37
|
+
#
|
38
|
+
# @return [Bool]
|
39
|
+
def public?
|
40
|
+
[slice(*%w[audience to]).values].flatten.include? PUBLIC
|
41
|
+
end
|
42
|
+
|
43
|
+
# Is it unlisted?
|
44
|
+
#
|
45
|
+
# @return [Bool]
|
46
|
+
def unlisted?
|
47
|
+
[self['cc']].flatten.include? PUBLIC
|
48
|
+
end
|
49
|
+
|
50
|
+
# It's not publicly available
|
51
|
+
#
|
52
|
+
# @return [Bool]
|
53
|
+
def private?
|
54
|
+
!public? && !unlisted?
|
55
|
+
end
|
56
|
+
|
31
57
|
def inspect
|
32
58
|
"#{self.class.name}(#{uri})"
|
33
59
|
end
|
34
60
|
|
35
|
-
def_delegators :object, :[], :dig, :to_h, :to_json
|
61
|
+
def_delegators :object, :[], :dig, :to_h, :to_json, :slice
|
36
62
|
end
|
37
63
|
end
|
38
64
|
end
|
@@ -4,6 +4,8 @@ class DistributedPress
|
|
4
4
|
module V1
|
5
5
|
module Social
|
6
6
|
# An object with external references
|
7
|
+
#
|
8
|
+
# @todo Merge with Reference
|
7
9
|
class ReferencedObject
|
8
10
|
extend Forwardable
|
9
11
|
|
@@ -18,6 +20,7 @@ class DistributedPress
|
|
18
20
|
replies
|
19
21
|
to
|
20
22
|
publicKey
|
23
|
+
audience
|
21
24
|
|
22
25
|
alsoKnownAs
|
23
26
|
devices
|
@@ -73,13 +76,22 @@ class DistributedPress
|
|
73
76
|
when Hash
|
74
77
|
reference_object!(o)
|
75
78
|
o
|
76
|
-
when String
|
79
|
+
when String
|
80
|
+
if o == DistributedPress::V1::Social::Reference::PUBLIC
|
81
|
+
o
|
82
|
+
else
|
83
|
+
dereferencer.references(dereferencer.uris(o))
|
84
|
+
end
|
85
|
+
else
|
86
|
+
o
|
77
87
|
end
|
78
88
|
end
|
79
89
|
when Hash
|
80
90
|
reference_object!(object[attribute])
|
81
91
|
when String
|
82
|
-
object[attribute]
|
92
|
+
unless object[attribute] == DistributedPress::V1::Social::Reference::PUBLIC
|
93
|
+
object[attribute] = dereferencer.references(dereferencer.uris(object[attribute]))
|
94
|
+
end
|
83
95
|
end
|
84
96
|
end
|
85
97
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httparty/parser'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
module HTTParty
|
7
|
+
class Parser
|
8
|
+
# Parse HTML as Nokogiri documents
|
9
|
+
module Nokogiri
|
10
|
+
protected
|
11
|
+
|
12
|
+
def html
|
13
|
+
::Nokogiri::HTML5(body)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
HTTParty::Parser.class_eval do
|
20
|
+
prepend HTTParty::Parser::Nokogiri
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: distributed-press-api-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.0rc6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- f
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -120,6 +120,20 @@ dependencies:
|
|
120
120
|
- - "~>"
|
121
121
|
- !ruby/object:Gem::Version
|
122
122
|
version: 2.6.0
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: nokogiri
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '1.16'
|
130
|
+
type: :runtime
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '1.16'
|
123
137
|
- !ruby/object:Gem::Dependency
|
124
138
|
name: activesupport
|
125
139
|
requirement: !ruby/object:Gem::Requirement
|
@@ -310,6 +324,7 @@ files:
|
|
310
324
|
- lib/distributed_press/v1/social/allowlist.rb
|
311
325
|
- lib/distributed_press/v1/social/blocklist.rb
|
312
326
|
- lib/distributed_press/v1/social/client.rb
|
327
|
+
- lib/distributed_press/v1/social/collection.rb
|
313
328
|
- lib/distributed_press/v1/social/dereferencer.rb
|
314
329
|
- lib/distributed_press/v1/social/followers.rb
|
315
330
|
- lib/distributed_press/v1/social/hook.rb
|
@@ -324,6 +339,7 @@ files:
|
|
324
339
|
- lib/distributed_press/version.rb
|
325
340
|
- lib/dry/schema/processor_decorator.rb
|
326
341
|
- lib/dry/schema/result_decorator.rb
|
342
|
+
- lib/httparty/parser/nokogiri.rb
|
327
343
|
- lib/jekyll-distributed-press-v0.rb
|
328
344
|
homepage: https://0xacab.org/sutty/distributed-press-api-client
|
329
345
|
licenses:
|