jnc_api 0.2.0 → 0.3.0

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: 7bb496cf77ffdd9ffb87bd9d7d33a897546d32f2266d07bb1daab3620d48e235
4
- data.tar.gz: 6b8bad8863037477e53977329d39149839769a61d5443f530b647510a8ab0924
3
+ metadata.gz: 3974d29ba88445303cbe19210402f6b3acfb1ad8aa9ca9ee5f662025f04a9ab0
4
+ data.tar.gz: b50c7ba9e5ff1666565241497a974c35fef74ba957037d476d0a169d317b4ad9
5
5
  SHA512:
6
- metadata.gz: 24f6fa7999c012f0870e23d9fec16e3dc6076306da1cc84e7a470a831bdf9e6d56eef338440c3d7dc5ba1b05196657280c9d0f11f093898b5646e78317d53658
7
- data.tar.gz: 798236a71e88c3b8b50c0b8a789fcd6b0f31304a5039274b65d945612c71ee0a042ce93d8356b2665605f342d8b29c1b4a514300b9987b17e16c7af04be98cde
6
+ metadata.gz: f5849dc5efaf3877966a24d1d399e41b1aaacece2969a9e1dcd05924c38712b1906f24d249b3a11144fb888f3edfaea4de1f6e96180463aab5cf64555a875901
7
+ data.tar.gz: 0ed4905c22b8ae2ea72d125bab66df8ff544879ecb6f8196afa853457aab45bf5246220c423066566422963d6fbde0bca0fb0775d67f496f757d36f5c25b423a
@@ -46,8 +46,26 @@ ActiveRecord::Schema.define do
46
46
  t.timestamps
47
47
  end
48
48
  end
49
+
50
+ unless table_exists?(:manga_parts)
51
+ create_table :manga_parts, force: :cascade do |t|
52
+ t.integer :part_id, null: false
53
+ t.text :uuid
54
+ t.text :ngtoken
55
+ t.text :kgtoken
56
+ t.text :webpub
57
+ t.timestamps
58
+ end
59
+ end
60
+
49
61
  end
50
62
 
51
63
  class Part < ActiveRecord::Base
64
+ has_many :manga_parts
52
65
  serialize :crypt_data, coder: JSON
53
66
  end
67
+
68
+ class MangaPart < ActiveRecord::Base
69
+ belongs_to :part
70
+ serialize :webpub, coder: JSON
71
+ end
@@ -23,7 +23,7 @@ gemfile do
23
23
  gem "activerecord", "~> 7.1", require: "active_record"
24
24
  gem "sqlite3", "~> 1.4", require: "sqlite3"
25
25
  gem "addressable", "~> 2.8", require: "addressable"
26
- gem 'optparse', require: "optparse"
26
+ gem "optparse", require: "optparse"
27
27
 
28
28
  gem "jnc_api", path: "../..", require: "jnc_api"
29
29
  end
@@ -55,18 +55,22 @@ def assign_part_from_json(part, p)
55
55
  part.series_type = p["type"]
56
56
  part.legacy_id = p["partLegacyId"]
57
57
  part.title = p["partTitle"]
58
- part.updated = p["updated"]
59
58
  part.clear_data = p["clearData"]
60
59
  end
61
60
 
62
61
  options = {}
63
- OptionParser.new do |opts|
64
- opts.on("--slug=SLUG", "Only download this part as identified by the slug") do |s|
65
- options[:slug] = s
62
+ OptionParser
63
+ .new do |opts|
64
+ opts.on(
65
+ "--slug=SLUG",
66
+ "Only download this part as identified by the slug"
67
+ ) { |s| options[:slug] = s }
66
68
  end
67
- end.parse!
69
+ .parse!
68
70
 
69
- user_id = JSON.parse(api.me)["legacyId"]
71
+ me = api.me
72
+ puts me
73
+ user_id = JSON.parse(me)["legacyId"]
70
74
 
71
75
  if options[:slug]
72
76
  opt_slug = options[:slug]
@@ -74,6 +78,7 @@ if options[:slug]
74
78
  part = Part.find_or_create_by(slug: opt_slug)
75
79
 
76
80
  assign_part_from_json(part, p)
81
+ part.updated = p["updated"]
77
82
 
78
83
  part.save!
79
84
 
@@ -96,39 +101,51 @@ else
96
101
 
97
102
  # skip items if the feed item is already seen
98
103
  if part.date_published &&
99
- item["date_published"].to_datetime == part.date_published.to_datetime
104
+ item["date_published"].to_datetime == part.date_published.to_datetime
100
105
  puts "Skipping part #{part.slug} (feed item already seen)"
106
+
101
107
  next
102
108
  end
103
109
 
104
- sleep 3
110
+ puts "sleeping for 5s"
111
+ sleep 5
105
112
 
106
113
  p = JSON.parse(api.parts_data(slug))
107
-
108
114
  assign_part_from_json(part, p)
109
115
 
110
- part.image = item["image"]
111
- part.date_published = item["date_published"]
112
-
113
- part.save!
114
-
115
- # skip items that are not novels e.g. manga
116
- # we currently have no way to decode the manga parts
117
- if p["type"] != "NOVEL"
118
- puts "Skipping part #{part.slug} (not NOVEL type unsupported)"
119
- next
120
- end
121
-
122
116
  # skip items if the part is already up-to-date
123
117
  if part.data && p["updated"].to_datetime == part.updated.to_datetime
124
118
  puts "Skipping part #{part.slug} (feed item updated)"
119
+
125
120
  next
126
121
  end
127
122
 
128
- e = api.embed(p["partLegacyId"])
123
+ # note: we currently have no way to descramble the manga parts
124
+ if p["type"] == "MANGA"
125
+ puts "part #{part.slug} is manga, downloading webpub"
126
+ tokens = JSON.parse(api.manga_parts(part.legacy_id))
127
+ manga_part = part.manga_parts.find_or_create_by(uuid: tokens["uuid"])
128
+ manga_part.uuid = tokens["uuid"]
129
+ manga_part.ngtoken = tokens["ngtoken"]
130
+ manga_part.kgtoken = tokens["kgtoken"]
131
+
132
+ puts tokens
133
+ puts "sleeping for 30s"
134
+ sleep 5
135
+
136
+ manga_part.webpub = api.webpub(tokens["uuid"], tokens["ngtoken"])
137
+ manga_part.save!
138
+ else
139
+ e = api.embed(p["partLegacyId"])
140
+
141
+ part.data = e
142
+ part.crypt_data = p["cryptData"]
143
+ end
144
+
145
+ part.image = item["image"]
146
+ part.date_published = item["date_published"]
147
+ part.updated = p["updated"]
129
148
 
130
- part.data = e
131
- part.crypt_data = p["cryptData"]
132
149
  part.save!
133
150
 
134
151
  puts "Updated part #{part.slug}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JncApi
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/jnc_api.rb CHANGED
@@ -32,7 +32,7 @@ module JncApi
32
32
  embed: "https://labs.j-novel.club/embed/",
33
33
  completion: "https://labs.j-novel.club/app/v1/me/completion",
34
34
  manga_parts: "https://api.j-novel.club/api/mangaParts",
35
- webpub: "https://m11.j-novel.club/nebel/wp",
35
+ webpub: "https://m11.j-novel.club/nebel/wp"
36
36
  }
37
37
 
38
38
  class Api
@@ -44,7 +44,7 @@ module JncApi
44
44
  routes[:login] + "?format=json",
45
45
  body:
46
46
  JSON.generate(
47
- {"login" => login, "password" => password, "slim" => true}
47
+ { "login" => login, "password" => password, "slim" => true }
48
48
  ),
49
49
  headers: {
50
50
  "Content-Type" => "application/json"
@@ -61,8 +61,15 @@ module JncApi
61
61
  def initialize(routes: V1_ROUTES, token: nil)
62
62
  @routes = routes
63
63
  @token = token
64
- @default_headers = {"Content-Type" => "application/json"}
65
- @bearer = {"Authorization" => "Bearer #{@token}"}
64
+ @default_headers = {
65
+ "User-Agent" =>
66
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0",
67
+ "Accept" =>
68
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
69
+ "Accept-Language" => "en-US,en;q=0.5",
70
+ "Content-Type" => "application/json"
71
+ }
72
+ @bearer = { "Authorization" => "Bearer #{@token}" }
66
73
  end
67
74
 
68
75
  def series_list(limit: 500, skip: 0)
@@ -163,9 +170,10 @@ module JncApi
163
170
  # we can't seem to use bearer tokens for the manga endpoints
164
171
  def manga_parts(part_id)
165
172
  response =
166
- HTTParty.get(
167
- @routes[:manga_parts] + "/#{part_id}/token?access_token=#{@token}",
168
- )
173
+ HTTParty.get(
174
+ @routes[:manga_parts] + "/#{part_id}/token?access_token=#{@token}",
175
+ headers: @default_headers
176
+ )
169
177
 
170
178
  if response.success?
171
179
  response.body
@@ -178,10 +186,12 @@ module JncApi
178
186
  # likely for cheaper static hosting (as long as the locations are
179
187
  # difficult to guess such as uuid)
180
188
  def webpub(uuid, ngtoken)
181
- response = HTTParty.post(
182
- @routes[:webpub] + "/#{part_id}",
183
- body: ngtoken,
184
- )
189
+ response =
190
+ HTTParty.post(
191
+ @routes[:webpub] + "/#{uuid}",
192
+ body: ngtoken,
193
+ headers: @default_headers
194
+ )
185
195
 
186
196
  if response.success?
187
197
  response.body
@@ -189,6 +199,5 @@ module JncApi
189
199
  raise Error.new(response.inspect)
190
200
  end
191
201
  end
192
-
193
202
  end
194
203
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jnc_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - parasquid
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-02 00:00:00.000000000 Z
11
+ date: 2024-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -71,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
71
  - !ruby/object:Gem::Version
72
72
  version: '0'
73
73
  requirements: []
74
- rubygems_version: 3.4.6
74
+ rubygems_version: 3.4.20
75
75
  signing_key:
76
76
  specification_version: 4
77
77
  summary: Light wrapper for the J-Novel Club API.