distributed-press-api-client 0.4.0rc3 → 0.4.1

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: ee95dc9deb3cb19084a66ee33ee4970906619c6489ce0bf29b0aa9f90ae99d93
4
- data.tar.gz: abcb6a90f1e16ad51aac21f15b79067c141f4cdc45edfbddc69704dd235adac7
3
+ metadata.gz: 6a5f4b33d4222028ca00dfe7e4a3f9e0fd5a4e4c620068e8ae094df84e4d4a2c
4
+ data.tar.gz: ba21a56decb67357d65243ea5f7a12f92e705f689a2501fe3419921d6ffeea0f
5
5
  SHA512:
6
- metadata.gz: 5d3e98400b29ee2258a29beb1c47fab70a07d1cbdd43a96df9842a507d2ee3f3aaf9d3eeef1dee381967363227fb8af68b0b9f080861feac67595b1a081c43b0
7
- data.tar.gz: 55291cec6e026520a3e9f111fd80e55b4762aa551f1dcae12015951a01d9d6dd55bbda07394f5f36566e3500abed7673e2a71c90feaf2f4092ef838361d3c8e8
6
+ metadata.gz: 3a8f016d1fba233cf4e106b6f114fa82b34949af8b88cde9c252d4c33bb440c30c233eadee120205d4ff9c019327f44d9f9e4971abc8733c4e2c5856ec2a5986
7
+ data.tar.gz: 43019f74c34831fa3a9164db342e971307ab8c76e225445a7a95cf82f025e2496af8cfa0c1264fcd620ad2126f1066093280bbcfa5d113705c658247583c7aec
@@ -86,12 +86,12 @@ class DistributedPress
86
86
 
87
87
  def _dump(_)
88
88
  Marshal.dump({
89
- public_key_url: public_key_url,
90
- url: url,
91
- private_key_pem: @private_key_pem,
92
- key_size: key_size,
93
- cache_store: self.class.cache_store
94
- })
89
+ public_key_url: public_key_url,
90
+ url: url,
91
+ private_key_pem: @private_key_pem,
92
+ key_size: key_size,
93
+ cache_store: self.class.cache_store
94
+ })
95
95
  end
96
96
 
97
97
  def self._load(hash)
@@ -202,7 +202,7 @@ class DistributedPress
202
202
  # after the request is instantiated. No need to process
203
203
  # cookies for now. Uses the public key URL as a caching key so
204
204
  # we revalidate access on shared caches.
205
- options = { body: body, headers: headers, base_uri: url, parser: parser, stream_body: true, cache_key: public_key_url }
205
+ options = { body: body, headers: headers, base_uri: url, parser: parser, stream_body: true }
206
206
  options = HTTParty::ModuleInheritableAttributes.hash_deep_dup(self.class.default_options).merge(options)
207
207
  response_body = ''.dup
208
208
 
@@ -211,6 +211,14 @@ class DistributedPress
211
211
  end.perform do |fragment|
212
212
  fragment_to_body!(fragment, response_body)
213
213
  end.tap do |response|
214
+ # Brotli decompression is delayed until after full download
215
+ if response.headers['content-encoding'] == 'br'
216
+ ''.dup.tap do |inflated_response_body|
217
+ inflate_body!(response_body, inflated_response_body)
218
+ response_body = inflated_response_body
219
+ end
220
+ end
221
+
214
222
  next if response_body.empty?
215
223
 
216
224
  fix_response!(response, response_body)
@@ -275,16 +283,19 @@ class DistributedPress
275
283
  # tests, 2GB of zeroes were compressed to a 1.6KB fragment.
276
284
  #
277
285
  # @todo Maybe each_char is too slow?
278
- # @param fragment [HTTParty::ResponseFragment]
286
+ # @param body [String]
279
287
  # @param append_to [String]
280
- def inflate_fragment!(fragment, append_to)
281
- fragment_io = StringIO.new(fragment)
288
+ def inflate_body!(body, append_to)
289
+ body_io = StringIO.new(body)
282
290
 
283
- BRS::Stream::Reader.new(fragment_io, source_buffer_length: 256,
284
- destination_buffer_length: 1024).each_char do |char|
291
+ BRS::Stream::Reader.new(body_io, source_buffer_length: 256,
292
+ destination_buffer_length: 1024).each_char do |char|
285
293
  append_to << char
286
294
 
287
- raise ContentTooLargeError if append_to.bytesize > 1_000_000
295
+ if append_to.bytesize > 1_000_000
296
+ raise ContentTooLargeError,
297
+ "Content too large after inflating, stopped at #{append_to.bytesize} bytes!"
298
+ end
288
299
  end
289
300
  end
290
301
 
@@ -294,22 +305,16 @@ class DistributedPress
294
305
  # @param :fragment [HTTParty::ResponseFragment]
295
306
  # @param :append_to [String]
296
307
  def fragment_to_body!(fragment, append_to)
297
- case fragment.http_response['content-encoding']
298
- when 'br'
299
- # Raise an error rather than returning an empty body
300
- unless brotli?
301
- raise BrotliUnsupportedError,
302
- 'Server sent brotli-encoded response but ruby-brs gem is missing'
303
- end
304
-
305
- inflate_fragment!(fragment, append_to)
306
- else
307
- append_to << fragment
308
+ if fragment.http_response['content-encoding'] == 'br' && !brotli?
309
+ raise BrotliUnsupportedError, 'Server sent brotli-encoded response but ruby-brs gem is missing'
308
310
  end
309
311
 
310
- raise ContentTooLargeError if append_to.bytesize > 1_000_000
311
- rescue ContentTooLargeError
312
- raise ContentTooLargeError, "Content too large #{append_to.bytesize} bytes!"
312
+ append_to << fragment
313
+
314
+ return unless append_to.bytesize > 1_000_000
315
+
316
+ raise ContentTooLargeError,
317
+ "Content too large, stopped at #{append_to.bytesize} bytes!"
313
318
  end
314
319
 
315
320
  # Re-adds a streamed body to the response and caches it again so
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require_relative 'client'
5
+
6
+ class DistributedPress
7
+ module V1
8
+ module Social
9
+ # Manages the actor's followers on the Social Inbox
10
+ class Followers
11
+ # @return [DistributedPress::V1::Social::Client]
12
+ attr_reader :client
13
+
14
+ # @return [String]
15
+ attr_reader :actor
16
+
17
+ # @param :client [DistributedPress::V1::Social::Client]
18
+ # @param :actor [String]
19
+ def initialize(client:, actor:)
20
+ @client = client
21
+ @actor = actor
22
+ end
23
+
24
+ # Get the actor's inbox
25
+ #
26
+ # @return [HTTParty::Response]
27
+ def get
28
+ client.get(endpoint: endpoint)
29
+ end
30
+
31
+ #
32
+ #
33
+ # @param :id [String] Activity ID
34
+ # @return [HTTParty::Response]
35
+ def remove(id:)
36
+ client.delete(endpoint: "#{endpoint}/#{URI.encode_uri_component(id)}")
37
+ end
38
+
39
+ # Followers
40
+ #
41
+ # @return [String]
42
+ def endpoint
43
+ @endpoint ||= "/v1/#{actor}/followers"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -21,6 +21,23 @@ class DistributedPress
21
21
  @actor = actor
22
22
  end
23
23
 
24
+ # Creates a Social Inbox by uploading the keypair to it.
25
+ #
26
+ # @param actor_url [String] The URL where the Actor profile is hosted
27
+ # @return [HTTParty::Response]
28
+ def create(actor_url)
29
+ inbox_body = {
30
+ 'actorUrl' => actor_url,
31
+ 'publicKeyId' => "#{actor_url}#main-key",
32
+ 'keypair' => {
33
+ 'publicKeyPem' => client.public_key.public_to_pem,
34
+ 'privateKeyPem' => client.private_key.export
35
+ }
36
+ }
37
+
38
+ client.post(endpoint: "/v1/#{actor}", body: inbox_body)
39
+ end
40
+
24
41
  # Get the actor's inbox
25
42
  #
26
43
  # @return [HTTParty::Response]
@@ -3,5 +3,5 @@
3
3
  # API client
4
4
  class DistributedPress
5
5
  # Version
6
- VERSION = '0.4.0rc3'
6
+ VERSION = '0.4.1'
7
7
  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.4.0rc3
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - f
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-01 00:00:00.000000000 Z
11
+ date: 2024-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -311,7 +311,7 @@ files:
311
311
  - lib/distributed_press/v1/social/blocklist.rb
312
312
  - lib/distributed_press/v1/social/client.rb
313
313
  - lib/distributed_press/v1/social/dereferencer.rb
314
- - lib/distributed_press/v1/social/dereferencer.rb.orig
314
+ - lib/distributed_press/v1/social/followers.rb
315
315
  - lib/distributed_press/v1/social/hook.rb
316
316
  - lib/distributed_press/v1/social/inbox.rb
317
317
  - lib/distributed_press/v1/social/outbox.rb
@@ -351,9 +351,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
351
351
  version: '2.7'
352
352
  required_rubygems_version: !ruby/object:Gem::Requirement
353
353
  requirements:
354
- - - ">"
354
+ - - ">="
355
355
  - !ruby/object:Gem::Version
356
- version: 1.3.1
356
+ version: '0'
357
357
  requirements: []
358
358
  rubygems_version: 3.3.26
359
359
  signing_key:
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'addressable'
4
- require_relative 'reference'
5
-
6
- class DistributedPress
7
- module V1
8
- module Social
9
- # Fetches ActivityStreams from different instances by
10
- # instantiating clients.
11
- class Dereferencer
12
- # @return [DistributedPress::V1::Social::Client]
13
- attr_reader :client
14
-
15
- REFERENTIABLE_ATTRIBUTES =
16
- %w[
17
- actor
18
- owner
19
- attributedTo
20
- cc
21
- inReplyTo
22
- object
23
- replies
24
- to
25
- publicKey
26
-
27
- alsoKnownAs
28
- devices
29
- featured
30
- featuredTags
31
- followers
32
- following
33
- inbox
34
- movedTo
35
- outbox
36
-
37
- first
38
- items
39
- next
40
- orderedItems
41
- partOf
42
- prev
43
- ].freeze
44
-
45
- # @param :client [DistributedPress::V1::Social::Client]
46
- def initialize(client:)
47
- @client = client
48
- @parser =
49
- proc do |body, format|
50
- next HTTParty::Parser.call(body, format || :plain) unless body&.starts_with? '{'
51
-
52
- HTTParty::Parser.call(body, :json).tap do |object|
53
- reference_object! object
54
- end
55
- end
56
- end
57
-
58
- # Fetch a URI
59
- #
60
- # @param :uri [String, Addressable::URI]
61
- # @return [HTTParty::Response]
62
- def get(uri:)
63
- uri = uris(uri)
64
-
65
- clients(uri).get(endpoint: uri.path, parser: @parser)
66
- end
67
-
68
- # Gets a client for a URI
69
- #
70
- # @param :uri [Addressable::URI]
71
- # @return [DistributedPress::V1::Social::Client]
72
- def clients(uri)
73
- @clients ||= {}
74
- @clients[uri.origin] ||=
75
- client.class.new(
76
- url: uri.origin,
77
- public_key_url: client.public_key_url,
78
- private_key_pem: client.private_key.to_s,
79
- logger: client.logger,
80
- cache_store: client.class.cache_store
81
- )
82
- end
83
-
84
- # Gets a reference for a URI and indexes it by the complete
85
- # and normalized URI
86
- #
87
- # @param :uri [String, Addressable::URI]
88
- # @return [DistributedPress::V1::Social::Reference]
89
- def references(uri)
90
- @references ||= {}
91
- @references[uri.to_s] ||= Reference.new(uri: uri.to_s, dereferencer: self)
92
- end
93
-
94
- # Make sure we're getting a normalized Addressable::URI
95
- #
96
- # @param :uri [String, Addressable::URI]
97
- # @return [Addressable::URI]
98
- def uris(uri)
99
- @uris ||= {}
100
- @uris[uri.to_s] ||=
101
- (if uri.is_a? Addressable::URI
102
- uri
103
- else
104
- Addressable::URI.parse(uri)
105
- end).normalize
106
- end
107
-
108
- def reference_object!(object)
109
- REFERENTIABLE_ATTRIBUTES.each do |attribute|
110
- next unless object.key? attribute
111
-
112
- case object[attribute]
113
- when Array
114
- object[attribute].map! do |o|
115
- case o
116
- when Hash
117
- reference_object!(o)
118
- o
119
- when String then references(uris(o))
120
- end
121
- end
122
- when Hash
123
- reference_object!(object[attribute])
124
- when String
125
- object[attribute] = references(uris(object[attribute]))
126
- end
127
- end
128
- end
129
- end
130
- end
131
- end
132
- end