lknovel 0.0.5 → 0.0.6

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.
data/CHANGELOG CHANGED
@@ -5,3 +5,5 @@
5
5
  0.0.4: Remove unnecessary require, check if cover image exist in template and
6
6
  crop
7
7
  0.0.5: Fix lots of errors detected by epubcheck
8
+ 0.0.6: Add --chapter-theads/--image-theads cli options, support download a
9
+ whole series
data/README.md CHANGED
@@ -37,10 +37,16 @@ manually using the package manager. For Debian/Ubuntu:
37
37
  ## Usage
38
38
 
39
39
  $ lknovel -h
40
- Usage: lknovel [options] url
40
+ Usage: lknovel [options] URL ...
41
+
42
+ URL can be:
43
+ http://lknovel.lightnovel.cn/main/vollist/?.html
44
+ http://lknovel.lightnovel.cn/main/book/?.html
41
45
 
42
46
  Specific options:
43
47
  -k, --[no-]keep Keep temporary files
48
+ -t, --chapter-theads THREADS Chapter download threads(4)
49
+ -T, --image-theads THREADS Image download threads(5)
44
50
  -q, --[no-]quiet Run quietly
45
51
 
46
52
  Common options:
@@ -1,6 +1,7 @@
1
1
  require 'erb'
2
2
  require 'fileutils'
3
3
  require 'gepub'
4
+ require 'lknovel/series'
4
5
  require 'lknovel/volume'
5
6
  require 'optparse'
6
7
  require 'ostruct'
@@ -11,16 +12,31 @@ module Lknovel
11
12
  def self.parse(args)
12
13
  options = OpenStruct.new
13
14
  options.verbose = true
15
+ options.chapter_theads = 4
16
+ options.image_theads = 5
14
17
  options.keep = false
15
18
 
16
19
  opt_parser = OptionParser.new do |opts|
17
- opts.banner = 'Usage: lknovel [options] url'
20
+ opts.banner = "Usage: lknovel [options] URL ...\n\n"
21
+ opts.banner << "URL can be:\n"
22
+ opts.banner << " http://lknovel.lightnovel.cn/main/vollist/?.html\n"
23
+ opts.banner << " http://lknovel.lightnovel.cn/main/book/?.html\n"
18
24
  opts.separator "\nSpecific options:"
19
25
 
20
26
  opts.on('-k', '--[no-]keep', 'Keep temporary files') do |k|
21
27
  options.keep = k
22
28
  end
23
29
 
30
+ opts.on('-t', '--chapter-theads THREADS', Integer,
31
+ "Chapter download threads(#{options.chapter_theads})") do |ct|
32
+ options.chapter_theads = ct
33
+ end
34
+
35
+ opts.on('-T', '--image-theads THREADS', Integer,
36
+ "Image download threads(#{options.image_theads})") do |it|
37
+ options.image_theads = it
38
+ end
39
+
24
40
  opts.on('-q', '--[no-]quiet', 'Run quietly') do |q|
25
41
  options.verbose = !q
26
42
  end
@@ -54,15 +70,34 @@ module Lknovel
54
70
 
55
71
  def run
56
72
  ARGV.each do |url|
57
- process_volume(url)
73
+ if url.start_with?('http://lknovel.lightnovel.cn/main/book/')
74
+ volume = Volume.new(url)
75
+ process_volume(volume)
76
+ elsif url.start_with?('http://lknovel.lightnovel.cn/main/vollist/')
77
+ series = Series.new(url)
78
+ series.parse
79
+ series.volumes.each do |volume|
80
+ process_volume(volume)
81
+ end
82
+ else
83
+ puts "Unsupported url: #{url}"
84
+ end
58
85
  end
59
86
  end
60
87
 
61
- def process_volume(url)
62
- volume = Volume.new(url)
88
+ def process_volume(volume)
89
+ volume.parse
90
+ if File.exists?("#{volume.path}.epub")
91
+ puts "Skip: #{volume.path}.epub"
92
+ puts
93
+ return
94
+ end
95
+ puts "Start: #{volume.title}"
63
96
 
64
- parallel_verbose(volume.chapters, title: 'Chapters',
65
- verbose: @options.verbose) do |chapter|
97
+ parallel_verbose(volume.chapters,
98
+ title: 'Chapters',
99
+ threads: @options.chapter_theads,
100
+ verbose: @options.verbose) do |chapter|
66
101
  chapter.parse
67
102
  chapter.title
68
103
  end
@@ -79,8 +114,10 @@ module Lknovel
79
114
  end
80
115
  end
81
116
 
82
- parallel_verbose(images, title: 'Images',
83
- verbose: @options.verbose) do |image|
117
+ parallel_verbose(images,
118
+ title: 'Images',
119
+ threads: @options.image_theads,
120
+ verbose: @options.verbose) do |image|
84
121
  image.download
85
122
  image.file
86
123
  end
@@ -119,8 +156,12 @@ module Lknovel
119
156
  contributor volume.illustrator, 'ill'
120
157
 
121
158
  resources(:workdir => volume.path) {
122
- cover_image = File.join(IMAGE_DIR, volume.cover_image)
123
- cover_image cover_image
159
+ if volume.cover_image
160
+ cover_image = File.join(IMAGE_DIR, volume.cover_image)
161
+ cover_image cover_image
162
+ else
163
+ cover_image = nil
164
+ end
124
165
  file \
125
166
  "#{STYLESHEET_DIR}/default.css" => "#{STYLESHEET_PATH}/default.css"
126
167
  images = Dir.glob("#{IMAGE_DIR}/*").select {|x| x != cover_image}
@@ -138,6 +179,7 @@ module Lknovel
138
179
  builder.generate_epub("#{volume.path}.epub")
139
180
  FileUtils.rm_r volume.path unless @options.keep
140
181
  puts "Finish: #{volume.path}.epub"
182
+ puts
141
183
 
142
184
  end
143
185
 
@@ -17,6 +17,7 @@ img {
17
17
 
18
18
  ol li {
19
19
  padding-top: 15px;
20
+ list-style-type: none;
20
21
  }
21
22
 
22
23
  .page-break {
@@ -14,9 +14,9 @@ module Lknovel
14
14
  attr_reader :url, :title, :content
15
15
 
16
16
  def initialize(url, options = {})
17
- @options = {:title => nil}.merge(options)
17
+ options = {:title => nil}.merge(options)
18
18
  @url = url
19
- @title = @options[:title]
19
+ @title = options[:title]
20
20
  end
21
21
 
22
22
  def parse
@@ -1,5 +1,5 @@
1
1
  module Lknovel
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  MODULE_PATH = File.expand_path('..', __FILE__)
4
4
  TEMPLATE_PATH = File.join(MODULE_PATH, 'templates')
5
5
  STYLESHEET_PATH = File.join(MODULE_PATH, 'assets', 'stylesheets')
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ require 'lknovel/utils'
3
+ require 'lknovel/volume'
4
+ require 'nokogiri'
5
+ require 'open-uri'
6
+
7
+ module Lknovel
8
+ class Series
9
+ attr_reader :volumes
10
+
11
+ def initialize(url)
12
+ @url = url
13
+ end
14
+
15
+ def parse
16
+ page = retryable do
17
+ Nokogiri::HTML(open(@url))
18
+ end
19
+
20
+ @volumes = page.css('dl dd h2.ft-24 strong a').map do |x|
21
+ volume_title = x.text.split("\r\n")[-1].strip
22
+ volume_url = x['href']
23
+ Volume.new(volume_url, title: volume_title)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -33,7 +33,8 @@ def parallel_verbose(items, options = {}, &block)
33
33
  msg = "\r#{opts[:title]}: 0/#{items.size} ..."
34
34
  STDERR.write msg
35
35
  end
36
- Parallel.each_with_index(items, :in_threads => 5) do |item, index|
36
+ Parallel.each_with_index(items,
37
+ :in_threads => opts[:threads]) do |item, index|
37
38
  extra_msg = block.call(item, index)
38
39
  if opts[:verbose]
39
40
  # get previous console output length, aware of wide chars
@@ -14,9 +14,10 @@ module Lknovel
14
14
 
15
15
  attr_accessor :cover_image
16
16
 
17
- def initialize(url)
17
+ def initialize(url, options = {})
18
+ options = {:title => nil}.merge(options)
18
19
  @url = url
19
- parse
20
+ @title = options[:title]
20
21
  end
21
22
 
22
23
  def parse
@@ -1,10 +1,11 @@
1
- begin
1
+ CI = !!ENV['TRAVIS']
2
+
3
+ if CI
2
4
  require 'coveralls'
3
5
  Coveralls.wear!
4
- rescue LoadError
5
6
  end
6
7
 
7
8
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
8
9
 
9
10
  require 'minitest/autorun'
10
- require 'pry-rescue/minitest'
11
+ require 'pry-rescue/minitest' unless CI
@@ -13,12 +13,9 @@ describe Lknovel::Image do
13
13
  image.file.must_equal '20120808202600_62961.jpg'
14
14
  end
15
15
 
16
- it 'download' do
16
+ it 'download and crop' do
17
17
  image.download(TMP)
18
18
  File.exists?(File.join(TMP, image.file)).must_equal true
19
- end
20
-
21
- it 'crop' do
22
19
  cover_image = File.join(TMP, 'cover.jpg')
23
20
  cropped = image.crop(cover_image, '52%x100%+0+0', :dir => TMP) { |w, h| w > h * 1.5 }
24
21
  cropped.must_equal true
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ require 'minitest_helper'
3
+ require 'lknovel/series'
4
+
5
+ describe Lknovel::Series do
6
+
7
+ series = Lknovel::Series.new('http://lknovel.lightnovel.cn/main/vollist/615.html')
8
+ series.parse
9
+
10
+ it 'volume[0]' do
11
+ volume = series.volumes[0]
12
+ volume.url.must_equal 'http://lknovel.lightnovel.cn/main/book/2123.html'
13
+ end
14
+
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lknovel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-20 00:00:00.000000000 Z
12
+ date: 2014-03-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -145,6 +145,7 @@ files:
145
145
  - lib/lknovel/chapter.rb
146
146
  - lib/lknovel/image.rb
147
147
  - lib/lknovel/meta.rb
148
+ - lib/lknovel/series.rb
148
149
  - lib/lknovel/templates/chapter.html.erb
149
150
  - lib/lknovel/templates/front.html.erb
150
151
  - lib/lknovel/utils.rb
@@ -154,6 +155,7 @@ files:
154
155
  - test/test_lknovel.rb
155
156
  - test/test_lknovel_chapter.rb
156
157
  - test/test_lknovel_image.rb
158
+ - test/test_lknovel_series.rb
157
159
  - test/test_lknovel_volume.rb
158
160
  homepage: https://github.com/azuwis/ruby-lknovel
159
161
  licenses:
@@ -185,5 +187,6 @@ test_files:
185
187
  - test/test_lknovel.rb
186
188
  - test/test_lknovel_chapter.rb
187
189
  - test/test_lknovel_image.rb
190
+ - test/test_lknovel_series.rb
188
191
  - test/test_lknovel_volume.rb
189
192
  has_rdoc: