sideko_hacker_news 0.1.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 +7 -0
- data/lib/schemas.rb +157 -0
- data/lib/sideko_hacker_news.rb +316 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ef178a860465610752cc33330438201f920004ba291de4b1096e78fb008195a8
|
4
|
+
data.tar.gz: e4c4c378fd1c24431b2d317f8f939d5a5631ba2c638d2e298e9801e87915784a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6fcf7a3adf6293e26f3ab4390eee3ac944bacc051759278ca77c041cbed515c404517a3067da18960ec30417b6506e92db1a9e7dfae3e34d3dd4be3caeb3b0b5
|
7
|
+
data.tar.gz: ae27e4a6f5fd26bbf2672aaa65c06430c0610cf2d8779e555bd204fd46bb5720a6d7315875724dd5167f0a8e27d94dce92454a5241500460813d5bd78ba8c36e
|
data/lib/schemas.rb
ADDED
@@ -0,0 +1,157 @@
|
|
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
|
@@ -0,0 +1,316 @@
|
|
1
|
+
# Generated by Sideko (sideko.dev)
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'json'
|
4
|
+
require 'http'
|
5
|
+
require_relative 'schemas'
|
6
|
+
|
7
|
+
class RequestError < StandardError
|
8
|
+
attr_reader :status_code, :method, :url, :data
|
9
|
+
|
10
|
+
def initialize(status_code, method, url, message)
|
11
|
+
@status_code = status_code
|
12
|
+
@method = method
|
13
|
+
@url = url
|
14
|
+
begin
|
15
|
+
@data = JSON.parse(message)
|
16
|
+
rescue
|
17
|
+
@data = message
|
18
|
+
end
|
19
|
+
|
20
|
+
super("received #{status_code} from #{method} #{url} with #{message}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Client
|
25
|
+
def initialize(base_url='https://hacker-news.firebaseio.com/v0')
|
26
|
+
@_client = HTTP.persistent(nil)
|
27
|
+
@_base_url = base_url
|
28
|
+
end
|
29
|
+
|
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
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_ask_story_ids(print: nil)
|
43
|
+
url = @_base_url + "/askstories.json"
|
44
|
+
params = {}
|
45
|
+
if print != nil
|
46
|
+
params[:print] = print
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
response = @_client.get(
|
51
|
+
url,
|
52
|
+
:params => params,
|
53
|
+
|
54
|
+
)
|
55
|
+
if response.status.success?
|
56
|
+
response = response.parse
|
57
|
+
else
|
58
|
+
raise RequestError.new(
|
59
|
+
status_code=response.status,
|
60
|
+
method="get",
|
61
|
+
url=url,
|
62
|
+
message=response.reason,
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
response
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_best_story_ids(print: nil)
|
70
|
+
url = @_base_url + "/beststories.json"
|
71
|
+
params = {}
|
72
|
+
if print != nil
|
73
|
+
params[:print] = print
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
response = @_client.get(
|
78
|
+
url,
|
79
|
+
:params => params,
|
80
|
+
|
81
|
+
)
|
82
|
+
if response.status.success?
|
83
|
+
response = response.parse
|
84
|
+
else
|
85
|
+
raise RequestError.new(
|
86
|
+
status_code=response.status,
|
87
|
+
method="get",
|
88
|
+
url=url,
|
89
|
+
message=response.reason,
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
response
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_item(id:, print: nil)
|
97
|
+
url = @_base_url + "/item/#{id}.json"
|
98
|
+
params = {}
|
99
|
+
if print != nil
|
100
|
+
params[:print] = print
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
response = @_client.get(
|
105
|
+
url,
|
106
|
+
:params => params,
|
107
|
+
|
108
|
+
)
|
109
|
+
if response.status.success?
|
110
|
+
response = response.parse
|
111
|
+
else
|
112
|
+
raise RequestError.new(
|
113
|
+
status_code=response.status,
|
114
|
+
method="get",
|
115
|
+
url=url,
|
116
|
+
message=response.reason,
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
response = Item.from_dynamic!(response)
|
121
|
+
response
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_job_story_ids(print: nil)
|
125
|
+
url = @_base_url + "/jobstories.json"
|
126
|
+
params = {}
|
127
|
+
if print != nil
|
128
|
+
params[:print] = print
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
response = @_client.get(
|
133
|
+
url,
|
134
|
+
:params => params,
|
135
|
+
|
136
|
+
)
|
137
|
+
if response.status.success?
|
138
|
+
response = response.parse
|
139
|
+
else
|
140
|
+
raise RequestError.new(
|
141
|
+
status_code=response.status,
|
142
|
+
method="get",
|
143
|
+
url=url,
|
144
|
+
message=response.reason,
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
response
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_max_item_id(print: nil)
|
152
|
+
url = @_base_url + "/maxitem.json"
|
153
|
+
params = {}
|
154
|
+
if print != nil
|
155
|
+
params[:print] = print
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
response = @_client.get(
|
160
|
+
url,
|
161
|
+
:params => params,
|
162
|
+
|
163
|
+
)
|
164
|
+
if response.status.success?
|
165
|
+
response = response.parse
|
166
|
+
else
|
167
|
+
raise RequestError.new(
|
168
|
+
status_code=response.status,
|
169
|
+
method="get",
|
170
|
+
url=url,
|
171
|
+
message=response.reason,
|
172
|
+
)
|
173
|
+
end
|
174
|
+
|
175
|
+
response
|
176
|
+
end
|
177
|
+
|
178
|
+
def get_new_story_ids(print: nil)
|
179
|
+
url = @_base_url + "/newstories.json"
|
180
|
+
params = {}
|
181
|
+
if print != nil
|
182
|
+
params[:print] = print
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
response = @_client.get(
|
187
|
+
url,
|
188
|
+
:params => params,
|
189
|
+
|
190
|
+
)
|
191
|
+
if response.status.success?
|
192
|
+
response = response.parse
|
193
|
+
else
|
194
|
+
raise RequestError.new(
|
195
|
+
status_code=response.status,
|
196
|
+
method="get",
|
197
|
+
url=url,
|
198
|
+
message=response.reason,
|
199
|
+
)
|
200
|
+
end
|
201
|
+
|
202
|
+
response
|
203
|
+
end
|
204
|
+
|
205
|
+
def get_show_story_ids(print: nil)
|
206
|
+
url = @_base_url + "/showstories.json"
|
207
|
+
params = {}
|
208
|
+
if print != nil
|
209
|
+
params[:print] = print
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
response = @_client.get(
|
214
|
+
url,
|
215
|
+
:params => params,
|
216
|
+
|
217
|
+
)
|
218
|
+
if response.status.success?
|
219
|
+
response = response.parse
|
220
|
+
else
|
221
|
+
raise RequestError.new(
|
222
|
+
status_code=response.status,
|
223
|
+
method="get",
|
224
|
+
url=url,
|
225
|
+
message=response.reason,
|
226
|
+
)
|
227
|
+
end
|
228
|
+
|
229
|
+
response
|
230
|
+
end
|
231
|
+
|
232
|
+
def get_top_story_ids(print: nil)
|
233
|
+
url = @_base_url + "/topstories.json"
|
234
|
+
params = {}
|
235
|
+
if print != nil
|
236
|
+
params[:print] = print
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
response = @_client.get(
|
241
|
+
url,
|
242
|
+
:params => params,
|
243
|
+
|
244
|
+
)
|
245
|
+
if response.status.success?
|
246
|
+
response = response.parse
|
247
|
+
else
|
248
|
+
raise RequestError.new(
|
249
|
+
status_code=response.status,
|
250
|
+
method="get",
|
251
|
+
url=url,
|
252
|
+
message=response.reason,
|
253
|
+
)
|
254
|
+
end
|
255
|
+
|
256
|
+
response
|
257
|
+
end
|
258
|
+
|
259
|
+
def get_updates(print: nil)
|
260
|
+
url = @_base_url + "/updates.json"
|
261
|
+
params = {}
|
262
|
+
if print != nil
|
263
|
+
params[:print] = print
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
response = @_client.get(
|
268
|
+
url,
|
269
|
+
:params => params,
|
270
|
+
|
271
|
+
)
|
272
|
+
if response.status.success?
|
273
|
+
response = response.parse
|
274
|
+
else
|
275
|
+
raise RequestError.new(
|
276
|
+
status_code=response.status,
|
277
|
+
method="get",
|
278
|
+
url=url,
|
279
|
+
message=response.reason,
|
280
|
+
)
|
281
|
+
end
|
282
|
+
|
283
|
+
response = GetUpdatesJSONResponse.from_dynamic!(response)
|
284
|
+
response
|
285
|
+
end
|
286
|
+
|
287
|
+
def get_user(id:, print: nil)
|
288
|
+
url = @_base_url + "/user/#{id}.json"
|
289
|
+
params = {}
|
290
|
+
if print != nil
|
291
|
+
params[:print] = print
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
response = @_client.get(
|
296
|
+
url,
|
297
|
+
:params => params,
|
298
|
+
|
299
|
+
)
|
300
|
+
if response.status.success?
|
301
|
+
response = response.parse
|
302
|
+
else
|
303
|
+
raise RequestError.new(
|
304
|
+
status_code=response.status,
|
305
|
+
method="get",
|
306
|
+
url=url,
|
307
|
+
message=response.reason,
|
308
|
+
)
|
309
|
+
end
|
310
|
+
|
311
|
+
response = User.from_dynamic!(response)
|
312
|
+
response
|
313
|
+
end
|
314
|
+
|
315
|
+
|
316
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sideko_hacker_news
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sideko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-10-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: http
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.1.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
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
|
+
description: |
|
62
|
+
Hacker News makes the public their data available in near real time.
|
63
|
+
> The v0 API is essentially a dump of our in-memory data structures. We know, what works great locally in memory isn't so hot over the network. Many of the awkward things are just the way HN works internally... It's not the ideal public API, but it's the one we could release in the time we had
|
64
|
+
|
65
|
+
This documentation and SDK libraries have been generated by [Sideko](https://sideko.dev) which has no affiliation with Hacker News. Everything you see is generated from an OpenAPI specification.
|
66
|
+
|
67
|
+
Install and try the free beta SDK generator on our [Github](https://github.com/Sideko-Inc/sideko).
|
68
|
+
email: team@sideko.dev
|
69
|
+
executables: []
|
70
|
+
extensions: []
|
71
|
+
extra_rdoc_files: []
|
72
|
+
files:
|
73
|
+
- lib/schemas.rb
|
74
|
+
- lib/sideko_hacker_news.rb
|
75
|
+
homepage:
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubygems_version: 3.4.10
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: sideko_hacker_news 0.1.0
|
98
|
+
test_files: []
|