sideko_hacker_news 0.1.1 → 0.2.0

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sideko_hacker_news.rb +259 -118
  3. metadata +8 -43
  4. data/lib/schemas.rb +0 -157
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef178a860465610752cc33330438201f920004ba291de4b1096e78fb008195a8
4
- data.tar.gz: e4c4c378fd1c24431b2d317f8f939d5a5631ba2c638d2e298e9801e87915784a
3
+ metadata.gz: bd4caa1413f271609180311354ca586ea6ffe7ec01a70e94de54c14918ea19cf
4
+ data.tar.gz: 31087653cab1a2db2570ae271278e15a791fd00454cecdad3df2ce9ca3fa8f65
5
5
  SHA512:
6
- metadata.gz: 6fcf7a3adf6293e26f3ab4390eee3ac944bacc051759278ca77c041cbed515c404517a3067da18960ec30417b6506e92db1a9e7dfae3e34d3dd4be3caeb3b0b5
7
- data.tar.gz: ae27e4a6f5fd26bbf2672aaa65c06430c0610cf2d8779e555bd204fd46bb5720a6d7315875724dd5167f0a8e27d94dce92454a5241500460813d5bd78ba8c36e
6
+ metadata.gz: 30c22b2cfa6cea1f4c3874220b2dc165d802dc97173728e274635f490831bf8bf04a7160a0e66ca664ca343fdbb8f05054ab4c95c37e747a860b143c6ee84e0a
7
+ data.tar.gz: 141b84970c299dd058348d2a53e246032f03b235e790fff2b41614064fff9b2999a2c0aaa4c2b09d23e47acbb02263690a10e24b0fdbf98ed5e13af71001704f
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
  require 'json'
4
4
  require 'http'
5
- require_relative 'schemas'
6
5
 
7
6
  class RequestError < StandardError
8
7
  attr_reader :status_code, :method, :url, :data
@@ -21,40 +20,149 @@ class RequestError < StandardError
21
20
  end
22
21
  end
23
22
 
23
+ module AuthProvider
24
+ def add_auth(http_client, req_kwargs)
25
+ raise NotImplementedError, "You must implement the 'add_auth' method"
26
+ end
27
+ end
28
+
29
+ class AuthBasic
30
+ include AuthProvider
31
+
32
+ attr_accessor :username, :password
33
+
34
+ def initialize(username: nil, password: nil)
35
+ @username = username
36
+ @password = password
37
+ end
38
+
39
+ def add_auth(http_client, req_kwargs)
40
+ if !@username.nil? && !@password.nil?
41
+ http_client = http_client.basic_auth(user: @username, pass: @password)
42
+ end
43
+
44
+ return http_client, req_kwargs
45
+ end
46
+ end
47
+
48
+ class AuthBearer
49
+ include AuthProvider
50
+
51
+ attr_accessor :val
52
+
53
+ def initialize(val: nil)
54
+ @val = val
55
+ end
56
+
57
+ def add_auth(http_client, req_kwargs)
58
+ if !@val.nil?
59
+ headers = req_kwargs.fetch(:headers, {})
60
+ headers["Authorization"] = "Bearer " + @val
61
+ req_kwargs[:headers] = headers
62
+ end
63
+
64
+ return http_client, req_kwargs
65
+ end
66
+ end
67
+
68
+ class AuthKeyQuery
69
+ include AuthProvider
70
+
71
+ attr_accessor :query_name, :val
72
+
73
+ def initialize(query_name: nil, val: nil)
74
+ @query_name = query_name
75
+ @val = val
76
+ end
77
+
78
+ def add_auth(http_client, req_kwargs)
79
+ if !val.nil?
80
+ params = req_kwargs.fetch(:params, {})
81
+ params[query_name] = val
82
+ req_kwargs[:params] = params
83
+ end
84
+
85
+ return http_client, req_kwargs
86
+ end
87
+ end
88
+
89
+ class AuthKeyHeader
90
+ include AuthProvider
91
+
92
+ attr_accessor :header_name, :val
93
+
94
+ def initialize(header_name: nil, val: nil)
95
+ @header_name = header_name
96
+ @val = val
97
+ end
98
+
99
+ def add_auth(http_client, req_kwargs)
100
+ if !@val.nil?
101
+ headers = req_kwargs.fetch(:headers, {})
102
+ headers[@header_name] = @val
103
+ req_kwargs[:headers] = headers
104
+ end
105
+
106
+ return http_client, req_kwargs
107
+ end
108
+ end
109
+
110
+ class AuthKeyCookie
111
+ include AuthProvider
112
+
113
+ attr_accessor :cookie_name, :val
114
+
115
+ def initialize(cookie_name: nil, val: nil)
116
+ @cookie_name = cookie_name
117
+ @val = val
118
+ end
119
+
120
+ def add_auth(http_client, req_kwargs)
121
+ if !@val.nil?
122
+ http_client = http_client.cookies(@cookie_name => @val)
123
+ end
124
+
125
+ return http_client, req_kwargs
126
+ end
127
+ end
128
+
24
129
  class Client
25
- def initialize(base_url='https://hacker-news.firebaseio.com/v0')
26
- @_client = HTTP.persistent(nil)
130
+ def initialize(base_url: 'https://hacker-news.firebaseio.com/v0')
27
131
  @_base_url = base_url
132
+ # register auth providers
133
+ @_auth = {}
28
134
  end
29
135
 
30
- def _cast_array(input_array, target_class)
31
- casted = []
32
- input_array.each { |el|
33
- if el.class == Array
34
- casted.append(_cast_array(el, target_class))
35
- else
36
- casted.append(target_class.from_json!(JSON.generate(el)))
37
- end
38
- }
39
- casted
136
+ def _client_with_auth(auth_names, **req_kwargs)
137
+ http_client = HTTP
138
+ auth_names.each do |auth_name|
139
+ provider = @_auth[auth_name]
140
+ http_client, req_kwargs = provider.add_auth(http_client, req_kwargs) if provider
141
+ end
142
+
143
+ return http_client, req_kwargs
40
144
  end
41
145
 
42
146
  def get_ask_story_ids(print: nil)
43
- url = @_base_url + "/askstories.json"
44
- params = {}
147
+ _url = @_base_url + "/askstories.json"
148
+ _kwargs = {
149
+ params: {}
150
+ }
45
151
  if print != nil
46
- params[:print] = print
152
+ _kwargs[:params][:"print"] = print
47
153
  end
154
+ _http_client, _req_kwargs = self._client_with_auth(
155
+ [],
156
+ **_kwargs
157
+ )
48
158
 
49
159
 
50
- response = @_client.get(
51
- url,
52
- :params => params,
160
+ response = _http_client.get(
161
+ _url,
53
162
 
163
+ **_req_kwargs
54
164
  )
55
- if response.status.success?
56
- response = response.parse
57
- else
165
+ if !response.status.success?
58
166
  raise RequestError.new(
59
167
  status_code=response.status,
60
168
  method="get",
@@ -63,25 +171,29 @@ class Client
63
171
  )
64
172
  end
65
173
 
66
- response
174
+ return response.parse
67
175
  end
68
176
 
69
177
  def get_best_story_ids(print: nil)
70
- url = @_base_url + "/beststories.json"
71
- params = {}
178
+ _url = @_base_url + "/beststories.json"
179
+ _kwargs = {
180
+ params: {}
181
+ }
72
182
  if print != nil
73
- params[:print] = print
183
+ _kwargs[:params][:"print"] = print
74
184
  end
185
+ _http_client, _req_kwargs = self._client_with_auth(
186
+ [],
187
+ **_kwargs
188
+ )
75
189
 
76
190
 
77
- response = @_client.get(
78
- url,
79
- :params => params,
191
+ response = _http_client.get(
192
+ _url,
80
193
 
194
+ **_req_kwargs
81
195
  )
82
- if response.status.success?
83
- response = response.parse
84
- else
196
+ if !response.status.success?
85
197
  raise RequestError.new(
86
198
  status_code=response.status,
87
199
  method="get",
@@ -90,25 +202,29 @@ class Client
90
202
  )
91
203
  end
92
204
 
93
- response
205
+ return response.parse
94
206
  end
95
207
 
96
- def get_item(id:, print: nil)
97
- url = @_base_url + "/item/#{id}.json"
98
- params = {}
208
+ def get_item(id, print: nil)
209
+ _url = @_base_url + "/item/#{id}.json"
210
+ _kwargs = {
211
+ params: {}
212
+ }
99
213
  if print != nil
100
- params[:print] = print
214
+ _kwargs[:params][:"print"] = print
101
215
  end
216
+ _http_client, _req_kwargs = self._client_with_auth(
217
+ [],
218
+ **_kwargs
219
+ )
102
220
 
103
221
 
104
- response = @_client.get(
105
- url,
106
- :params => params,
222
+ response = _http_client.get(
223
+ _url,
107
224
 
225
+ **_req_kwargs
108
226
  )
109
- if response.status.success?
110
- response = response.parse
111
- else
227
+ if !response.status.success?
112
228
  raise RequestError.new(
113
229
  status_code=response.status,
114
230
  method="get",
@@ -117,26 +233,29 @@ class Client
117
233
  )
118
234
  end
119
235
 
120
- response = Item.from_dynamic!(response)
121
- response
236
+ return response.parse
122
237
  end
123
238
 
124
239
  def get_job_story_ids(print: nil)
125
- url = @_base_url + "/jobstories.json"
126
- params = {}
240
+ _url = @_base_url + "/jobstories.json"
241
+ _kwargs = {
242
+ params: {}
243
+ }
127
244
  if print != nil
128
- params[:print] = print
245
+ _kwargs[:params][:"print"] = print
129
246
  end
247
+ _http_client, _req_kwargs = self._client_with_auth(
248
+ [],
249
+ **_kwargs
250
+ )
130
251
 
131
252
 
132
- response = @_client.get(
133
- url,
134
- :params => params,
253
+ response = _http_client.get(
254
+ _url,
135
255
 
256
+ **_req_kwargs
136
257
  )
137
- if response.status.success?
138
- response = response.parse
139
- else
258
+ if !response.status.success?
140
259
  raise RequestError.new(
141
260
  status_code=response.status,
142
261
  method="get",
@@ -145,25 +264,29 @@ class Client
145
264
  )
146
265
  end
147
266
 
148
- response
267
+ return response.parse
149
268
  end
150
269
 
151
270
  def get_max_item_id(print: nil)
152
- url = @_base_url + "/maxitem.json"
153
- params = {}
271
+ _url = @_base_url + "/maxitem.json"
272
+ _kwargs = {
273
+ params: {}
274
+ }
154
275
  if print != nil
155
- params[:print] = print
276
+ _kwargs[:params][:"print"] = print
156
277
  end
278
+ _http_client, _req_kwargs = self._client_with_auth(
279
+ [],
280
+ **_kwargs
281
+ )
157
282
 
158
283
 
159
- response = @_client.get(
160
- url,
161
- :params => params,
284
+ response = _http_client.get(
285
+ _url,
162
286
 
287
+ **_req_kwargs
163
288
  )
164
- if response.status.success?
165
- response = response.parse
166
- else
289
+ if !response.status.success?
167
290
  raise RequestError.new(
168
291
  status_code=response.status,
169
292
  method="get",
@@ -172,25 +295,29 @@ class Client
172
295
  )
173
296
  end
174
297
 
175
- response
298
+ return response.parse
176
299
  end
177
300
 
178
301
  def get_new_story_ids(print: nil)
179
- url = @_base_url + "/newstories.json"
180
- params = {}
302
+ _url = @_base_url + "/newstories.json"
303
+ _kwargs = {
304
+ params: {}
305
+ }
181
306
  if print != nil
182
- params[:print] = print
307
+ _kwargs[:params][:"print"] = print
183
308
  end
309
+ _http_client, _req_kwargs = self._client_with_auth(
310
+ [],
311
+ **_kwargs
312
+ )
184
313
 
185
314
 
186
- response = @_client.get(
187
- url,
188
- :params => params,
315
+ response = _http_client.get(
316
+ _url,
189
317
 
318
+ **_req_kwargs
190
319
  )
191
- if response.status.success?
192
- response = response.parse
193
- else
320
+ if !response.status.success?
194
321
  raise RequestError.new(
195
322
  status_code=response.status,
196
323
  method="get",
@@ -199,25 +326,29 @@ class Client
199
326
  )
200
327
  end
201
328
 
202
- response
329
+ return response.parse
203
330
  end
204
331
 
205
332
  def get_show_story_ids(print: nil)
206
- url = @_base_url + "/showstories.json"
207
- params = {}
333
+ _url = @_base_url + "/showstories.json"
334
+ _kwargs = {
335
+ params: {}
336
+ }
208
337
  if print != nil
209
- params[:print] = print
338
+ _kwargs[:params][:"print"] = print
210
339
  end
340
+ _http_client, _req_kwargs = self._client_with_auth(
341
+ [],
342
+ **_kwargs
343
+ )
211
344
 
212
345
 
213
- response = @_client.get(
214
- url,
215
- :params => params,
346
+ response = _http_client.get(
347
+ _url,
216
348
 
349
+ **_req_kwargs
217
350
  )
218
- if response.status.success?
219
- response = response.parse
220
- else
351
+ if !response.status.success?
221
352
  raise RequestError.new(
222
353
  status_code=response.status,
223
354
  method="get",
@@ -226,25 +357,29 @@ class Client
226
357
  )
227
358
  end
228
359
 
229
- response
360
+ return response.parse
230
361
  end
231
362
 
232
363
  def get_top_story_ids(print: nil)
233
- url = @_base_url + "/topstories.json"
234
- params = {}
364
+ _url = @_base_url + "/topstories.json"
365
+ _kwargs = {
366
+ params: {}
367
+ }
235
368
  if print != nil
236
- params[:print] = print
369
+ _kwargs[:params][:"print"] = print
237
370
  end
371
+ _http_client, _req_kwargs = self._client_with_auth(
372
+ [],
373
+ **_kwargs
374
+ )
238
375
 
239
376
 
240
- response = @_client.get(
241
- url,
242
- :params => params,
377
+ response = _http_client.get(
378
+ _url,
243
379
 
380
+ **_req_kwargs
244
381
  )
245
- if response.status.success?
246
- response = response.parse
247
- else
382
+ if !response.status.success?
248
383
  raise RequestError.new(
249
384
  status_code=response.status,
250
385
  method="get",
@@ -253,25 +388,29 @@ class Client
253
388
  )
254
389
  end
255
390
 
256
- response
391
+ return response.parse
257
392
  end
258
393
 
259
394
  def get_updates(print: nil)
260
- url = @_base_url + "/updates.json"
261
- params = {}
395
+ _url = @_base_url + "/updates.json"
396
+ _kwargs = {
397
+ params: {}
398
+ }
262
399
  if print != nil
263
- params[:print] = print
400
+ _kwargs[:params][:"print"] = print
264
401
  end
402
+ _http_client, _req_kwargs = self._client_with_auth(
403
+ [],
404
+ **_kwargs
405
+ )
265
406
 
266
407
 
267
- response = @_client.get(
268
- url,
269
- :params => params,
408
+ response = _http_client.get(
409
+ _url,
270
410
 
411
+ **_req_kwargs
271
412
  )
272
- if response.status.success?
273
- response = response.parse
274
- else
413
+ if !response.status.success?
275
414
  raise RequestError.new(
276
415
  status_code=response.status,
277
416
  method="get",
@@ -280,26 +419,29 @@ class Client
280
419
  )
281
420
  end
282
421
 
283
- response = GetUpdatesJSONResponse.from_dynamic!(response)
284
- response
422
+ return response.parse
285
423
  end
286
424
 
287
- def get_user(id:, print: nil)
288
- url = @_base_url + "/user/#{id}.json"
289
- params = {}
425
+ def get_user(id, print: nil)
426
+ _url = @_base_url + "/user/#{id}.json"
427
+ _kwargs = {
428
+ params: {}
429
+ }
290
430
  if print != nil
291
- params[:print] = print
431
+ _kwargs[:params][:"print"] = print
292
432
  end
433
+ _http_client, _req_kwargs = self._client_with_auth(
434
+ [],
435
+ **_kwargs
436
+ )
293
437
 
294
438
 
295
- response = @_client.get(
296
- url,
297
- :params => params,
439
+ response = _http_client.get(
440
+ _url,
298
441
 
442
+ **_req_kwargs
299
443
  )
300
- if response.status.success?
301
- response = response.parse
302
- else
444
+ if !response.status.success?
303
445
  raise RequestError.new(
304
446
  status_code=response.status,
305
447
  method="get",
@@ -308,8 +450,7 @@ class Client
308
450
  )
309
451
  end
310
452
 
311
- response = User.from_dynamic!(response)
312
- response
453
+ return response.parse
313
454
  end
314
455
 
315
456
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sideko_hacker_news
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sideko
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-12 00:00:00.000000000 Z
11
+ date: 2023-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http
@@ -24,40 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 5.1.1
27
- - !ruby/object:Gem::Dependency
28
- name: dry-struct
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.6'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.6'
41
- - !ruby/object:Gem::Dependency
42
- name: dry-types
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.7'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 1.7.1
51
- type: :runtime
52
- prerelease: false
53
- version_requirements: !ruby/object:Gem::Requirement
54
- requirements:
55
- - - "~>"
56
- - !ruby/object:Gem::Version
57
- version: '1.7'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 1.7.1
61
27
  description: |
62
28
  Hacker News makes the public their data available in near real time.
63
29
  &gt; The v0 API is essentially a dump of our in-memory data structures. We know, what works great locally in memory isn&#x27;t so hot over the network. Many of the awkward things are just the way HN works internally... It&#x27;s not the ideal public API, but it&#x27;s the one we could release in the time we had
@@ -70,13 +36,12 @@ executables: []
70
36
  extensions: []
71
37
  extra_rdoc_files: []
72
38
  files:
73
- - lib/schemas.rb
74
39
  - lib/sideko_hacker_news.rb
75
- homepage:
40
+ homepage:
76
41
  licenses:
77
42
  - MIT
78
43
  metadata: {}
79
- post_install_message:
44
+ post_install_message:
80
45
  rdoc_options: []
81
46
  require_paths:
82
47
  - lib
@@ -91,8 +56,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
56
  - !ruby/object:Gem::Version
92
57
  version: '0'
93
58
  requirements: []
94
- rubygems_version: 3.4.10
95
- signing_key:
59
+ rubygems_version: 3.3.5
60
+ signing_key:
96
61
  specification_version: 4
97
- summary: sideko_hacker_news 0.1.0
62
+ summary: sideko_hacker_news 0.2.0
98
63
  test_files: []
data/lib/schemas.rb DELETED
@@ -1,157 +0,0 @@
1
-
2
- require 'json'
3
- require 'dry-types'
4
- require 'dry-struct'
5
-
6
- module Types
7
- include Dry.Types(default: :nominal)
8
-
9
- Integer = Strict::Integer
10
- Bool = Strict::Bool
11
- Hash = Strict::Hash
12
- String = Strict::String
13
- end
14
-
15
- class GetUpdatesJSONResponse < Dry::Struct
16
-
17
- # Changed items
18
- attribute :items, Types.Array(Types::Integer).optional
19
-
20
- # Changed profiles
21
- attribute :profiles, Types.Array(Types::String).optional
22
-
23
- def self.from_dynamic!(d)
24
- d = Types::Hash[d]
25
- new(
26
- items: d["items"],
27
- profiles: d["profiles"],
28
- )
29
- end
30
-
31
- def self.from_json!(json)
32
- from_dynamic!(JSON.parse(json))
33
- end
34
-
35
- def to_dynamic
36
- {
37
- "items" => items,
38
- "profiles" => profiles,
39
- }
40
- end
41
-
42
- def to_json(options = nil)
43
- JSON.generate(to_dynamic, options)
44
- end
45
- end
46
-
47
- class Item < Dry::Struct
48
- attribute :by, Types::String
49
- attribute :dead, Types::Bool.optional
50
- attribute :deleted, Types::Bool.optional
51
- attribute :descendants, Types::Integer.optional
52
- attribute :id, Types::Integer
53
- attribute :kids, Types.Array(Types::Integer).optional
54
- attribute :parent, Types::Integer.optional
55
- attribute :parts, Types.Array(Types::Integer).optional
56
- attribute :poll, Types::Integer.optional
57
- attribute :score, Types::Integer.optional
58
- attribute :text, Types::String.optional
59
- attribute :time, Types::Integer
60
- attribute :title, Types::String.optional
61
- attribute :item_type, Types::String
62
- attribute :url, Types::String.optional
63
-
64
- def self.from_dynamic!(d)
65
- d = Types::Hash[d]
66
- new(
67
- by: d.fetch("by"),
68
- dead: d["dead"],
69
- deleted: d["deleted"],
70
- descendants: d["descendants"],
71
- id: d.fetch("id"),
72
- kids: d["kids"],
73
- parent: d["parent"],
74
- parts: d["parts"],
75
- poll: d["poll"],
76
- score: d["score"],
77
- text: d["text"],
78
- time: d.fetch("time"),
79
- title: d["title"],
80
- item_type: d.fetch("type"),
81
- url: d["url"],
82
- )
83
- end
84
-
85
- def self.from_json!(json)
86
- from_dynamic!(JSON.parse(json))
87
- end
88
-
89
- def to_dynamic
90
- {
91
- "by" => by,
92
- "dead" => dead,
93
- "deleted" => deleted,
94
- "descendants" => descendants,
95
- "id" => id,
96
- "kids" => kids,
97
- "parent" => parent,
98
- "parts" => parts,
99
- "poll" => poll,
100
- "score" => score,
101
- "text" => text,
102
- "time" => time,
103
- "title" => title,
104
- "type" => item_type,
105
- "url" => url,
106
- }
107
- end
108
-
109
- def to_json(options = nil)
110
- JSON.generate(to_dynamic, options)
111
- end
112
- end
113
-
114
- class User < Dry::Struct
115
-
116
- # The user's optional self-description. HTML
117
- attribute :about, Types::String.optional
118
-
119
- # Creation date of the user, in Unix Time
120
- attribute :created, Types::Integer.optional
121
-
122
- attribute :id, Types::String.optional
123
-
124
- # The user's karma
125
- attribute :karma, Types::Integer.optional
126
-
127
- attribute :submitted, Types::Any.optional
128
-
129
- def self.from_dynamic!(d)
130
- d = Types::Hash[d]
131
- new(
132
- about: d["about"],
133
- created: d["created"],
134
- id: d["id"],
135
- karma: d["karma"],
136
- submitted: d["submitted"],
137
- )
138
- end
139
-
140
- def self.from_json!(json)
141
- from_dynamic!(JSON.parse(json))
142
- end
143
-
144
- def to_dynamic
145
- {
146
- "about" => about,
147
- "created" => created,
148
- "id" => id,
149
- "karma" => karma,
150
- "submitted" => submitted,
151
- }
152
- end
153
-
154
- def to_json(options = nil)
155
- JSON.generate(to_dynamic, options)
156
- end
157
- end