distributed-press-api-client 0.5.0rc4 → 0.5.0rc5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c9c267bf382bc379f9cbcb034747c09eac71af0b8873e3e2b4c45c60120bcf7
4
- data.tar.gz: b2ffbec67481d7d48687653e2fb7ed76f8bd7f2a587d807b73f3133ef842a655
3
+ metadata.gz: 6b468eae410973ff56d5e6eb85e04e9a2bdeb375f274841fff3599a71adf220e
4
+ data.tar.gz: 4bba1c34d1d866264af766c57b3beadcc70a4e064d9b0e50686bf2a2940d4e9c
5
5
  SHA512:
6
- metadata.gz: d06dc678b4bbceb7fa5c061ad3de5fa943108367ddbe48875a0eed24b9fa4e87b6f8af3aeca00d9c29453c75979c97eaf91afde98b0486028edf5cf0ffdad867
7
- data.tar.gz: 1a67f604b966d5973df3bde6c620d0e3d6aeffbdf57ac723128571e3f9aa784745f1871a3eb6de5f873fb2d617f8a5e95b3b2a93d60b4bdb527e1e50393b80bb
6
+ metadata.gz: e90870a42b49134a6a2916f87363a11f35514effc99b72f38044c4a2d5bb1505b2d42c82e4c6f7277fa8ad9f321ef86f867e070e74aff3742826e2a16892ade5
7
+ data.tar.gz: 676e4969b7c5dcbc785157ee38599de7faf823c62659c21b9108dd04ae0cbff6e62e26390bbcc407f9ac76a8566758b646ee36b16baeb235b157c0af290124f1
@@ -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,18 @@ 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 cc]).values].flatten.include? PUBLIC
41
+ end
42
+
31
43
  def inspect
32
44
  "#{self.class.name}(#{uri})"
33
45
  end
34
46
 
35
- def_delegators :object, :[], :dig, :to_h, :to_json
47
+ def_delegators :object, :[], :dig, :to_h, :to_json, :slice
36
48
  end
37
49
  end
38
50
  end
@@ -18,6 +18,7 @@ class DistributedPress
18
18
  replies
19
19
  to
20
20
  publicKey
21
+ audience
21
22
 
22
23
  alsoKnownAs
23
24
  devices
@@ -73,13 +74,22 @@ class DistributedPress
73
74
  when Hash
74
75
  reference_object!(o)
75
76
  o
76
- when String then dereferencer.references(dereferencer.uris(o))
77
+ when String
78
+ if o == DistributedPress::V1::Social::Reference::PUBLIC
79
+ o
80
+ else
81
+ dereferencer.references(dereferencer.uris(o))
82
+ end
83
+ else
84
+ o
77
85
  end
78
86
  end
79
87
  when Hash
80
88
  reference_object!(object[attribute])
81
89
  when String
82
- object[attribute] = dereferencer.references(dereferencer.uris(object[attribute]))
90
+ unless object[attribute] == DistributedPress::V1::Social::Reference::PUBLIC
91
+ object[attribute] = dereferencer.references(dereferencer.uris(object[attribute]))
92
+ end
83
93
  end
84
94
  end
85
95
  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.0rc5'
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.0rc5
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-18 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: