jnc_api 0.2.0 → 0.3.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.
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.