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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c9c267bf382bc379f9cbcb034747c09eac71af0b8873e3e2b4c45c60120bcf7
4
- data.tar.gz: b2ffbec67481d7d48687653e2fb7ed76f8bd7f2a587d807b73f3133ef842a655
3
+ metadata.gz: 6a07fc21fcba26bb8bcb854ec767be0030013b58341b93a17c4e4c084aeb7cf3
4
+ data.tar.gz: b72a76ca86a62730c0e8299c1089b5dd43b52154322c96f235015c07c902c386
5
5
  SHA512:
6
- metadata.gz: d06dc678b4bbceb7fa5c061ad3de5fa943108367ddbe48875a0eed24b9fa4e87b6f8af3aeca00d9c29453c75979c97eaf91afde98b0486028edf5cf0ffdad867
7
- data.tar.gz: 1a67f604b966d5973df3bde6c620d0e3d6aeffbdf57ac723128571e3f9aa784745f1871a3eb6de5f873fb2d617f8a5e95b3b2a93d60b4bdb527e1e50393b80bb
6
+ metadata.gz: bdb203374bb184030f0f6a1a3a5f6699e8f52579060a6f71e1bfea5420fbfc66519bbf3cb9ca62b3b2683034328ef0dcea016512b359ee340a3e53a4dd012fae
7
+ data.tar.gz: 1a7253c626fab33aa0adc50007b19394dcdfc1cd55360a5dbb291842663ee85a2daedbdb9a2e6048a9697889b2dae5c350b76882160da66d1b1803fed09a9b0e
@@ -7,6 +7,7 @@ require 'time'
7
7
  require 'digest/sha2'
8
8
  require 'uri'
9
9
  require_relative '../../version'
10
+ require_relative '../../../httparty/parser/nokogiri'
10
11
  require_relative 'signed_headers'
11
12
 
12
13
  # Retro-compatibility for URI < 0.12
@@ -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
- ReferencedObject.new(object: HTTParty::Parser.call(body, :json), dereferencer: self)
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
- uri = uris(uri)
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
- clients(uri).get(endpoint: uri.path, parser: @parser)
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 then dereferencer.references(dereferencer.uris(o))
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] = dereferencer.references(dereferencer.uris(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
@@ -3,5 +3,5 @@
3
3
  # API client
4
4
  class DistributedPress
5
5
  # Version
6
- VERSION = '0.5.0rc4'
6
+ VERSION = '0.5.0rc6'
7
7
  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.0rc4
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-17 00:00:00.000000000 Z
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: