narou 2.9.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of narou might be problematic. Click here for more details.

Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/.reek +34 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +9 -1
  6. data/ChangeLog.md +90 -0
  7. data/Gemfile +4 -0
  8. data/README.md +85 -8
  9. data/lib/command/convert.rb +1 -1
  10. data/lib/command/list.rb +59 -73
  11. data/lib/command/list/novel_decorator.rb +107 -0
  12. data/lib/command/send.rb +23 -13
  13. data/lib/command/setting.rb +5 -1
  14. data/lib/command/update.rb +104 -138
  15. data/lib/command/update/general_lastup_updater.rb +105 -0
  16. data/lib/command/update/interval.rb +29 -0
  17. data/lib/command/web.rb +1 -1
  18. data/lib/commandbase.rb +24 -17
  19. data/lib/converterbase.rb +10 -5
  20. data/lib/database.rb +16 -5
  21. data/lib/device.rb +5 -1
  22. data/lib/device/library/linux.rb +68 -8
  23. data/lib/downloader.rb +24 -23
  24. data/lib/extension.rb +16 -3
  25. data/lib/helper.rb +26 -3
  26. data/lib/html.rb +1 -1
  27. data/lib/inspector.rb +9 -0
  28. data/lib/inventory.rb +20 -6
  29. data/lib/logger.rb +8 -2
  30. data/lib/mailer.rb +2 -1
  31. data/lib/narou.rb +28 -18
  32. data/lib/narou/api.rb +62 -31
  33. data/lib/novelconverter.rb +8 -1
  34. data/lib/novelinfo.rb +8 -7
  35. data/lib/novelsetting.rb +1 -0
  36. data/lib/progressbar.rb +6 -2
  37. data/lib/sitesetting.rb +2 -1
  38. data/lib/version.rb +1 -1
  39. data/lib/web/appserver.rb +72 -9
  40. data/lib/web/public/resources/narou.library.js +130 -13
  41. data/lib/web/public/resources/narou.ui.js +96 -9
  42. data/lib/web/settingmessages.rb +2 -1
  43. data/lib/web/views/_about.haml +15 -2
  44. data/lib/web/views/index.haml +12 -3
  45. data/lib/web/views/layout.haml +2 -1
  46. data/lib/web/views/style.scss +12 -0
  47. data/narou.gemspec +88 -11
  48. data/narou.rb +7 -1
  49. data/preset/mail_setting.yaml +40 -6
  50. data/webnovel/kakuyomu.jp.yaml +8 -8
  51. metadata +95 -139
  52. data/spec/README.txt +0 -4
  53. data/spec/convert_spec.rb +0 -119
  54. data/spec/converterbase_spec.rb +0 -298
  55. data/spec/data/convert_test/auto_indent/correct_test_auto_indent.txt +0 -28
  56. data/spec/data/convert_test/auto_indent/test_auto_indent.txt +0 -32
  57. data/spec/data/convert_test/auto_join_bracket/correct_test_auto_join_bracket.txt +0 -24
  58. data/spec/data/convert_test/auto_join_bracket/test_auto_join_bracket.txt +0 -28
  59. data/spec/data/convert_test/auto_join_line/correct_test_auto_join_line.txt +0 -43
  60. data/spec/data/convert_test/auto_join_line/test_auto_join_line.txt +0 -59
  61. data/spec/data/convert_test/convert_page_break/correct_test_convert_page_break.txt +0 -22
  62. data/spec/data/convert_test/convert_page_break/setting.ini +0 -5
  63. data/spec/data/convert_test/convert_page_break/test_convert_page_break.txt +0 -60
  64. data/spec/data/convert_test/double_dash_to_image/correct_test_double_dash_to_image.txt +0 -14
  65. data/spec/data/convert_test/double_dash_to_image/setting.ini +0 -1
  66. data/spec/data/convert_test/double_dash_to_image/test_double_dash_to_image.txt +0 -12
  67. data/spec/data/convert_test/english/correct_test_english.txt +0 -27
  68. data/spec/data/convert_test/english/test_english.txt +0 -27
  69. data/spec/data/convert_test/force_indent_special_chapter/correct_test_force_indent_special_chapter.txt +0 -64
  70. data/spec/data/convert_test/force_indent_special_chapter/test_force_indent_special_chapter.txt +0 -61
  71. data/spec/data/convert_test/horizontal_ellipsis/correct_test_horizontal_ellipsis.txt +0 -53
  72. data/spec/data/convert_test/horizontal_ellipsis/test_horizontal_ellipsis.txt +0 -57
  73. data/spec/data/convert_test/insert_separator/correct_test_insert_separator.txt +0 -13
  74. data/spec/data/convert_test/insert_separator/setting.ini +0 -3
  75. data/spec/data/convert_test/insert_separator/test_insert_separator.txt +0 -12
  76. data/spec/data/convert_test/insert_separator_and_replace_txt/correct_test_insert_separator_and_replace_txt.txt +0 -12
  77. data/spec/data/convert_test/insert_separator_and_replace_txt/setting.ini +0 -3
  78. data/spec/data/convert_test/insert_separator_and_replace_txt/test_insert_separator_and_replace_txt.txt +0 -11
  79. data/spec/data/convert_test/kanji_num/correct_test_kanji_num.txt +0 -50
  80. data/spec/data/convert_test/kanji_num/test_kanji_num.txt +0 -56
  81. data/spec/data/convert_test/nonokagi/correct_test_nonokagi.txt +0 -30
  82. data/spec/data/convert_test/nonokagi/test_nonokagi.txt +0 -34
  83. data/spec/data/convert_test/replace/correct_test_replace.txt +0 -13
  84. data/spec/data/convert_test/replace/test_replace.txt +0 -14
  85. data/spec/data/convert_test/ruby/correct_test_ruby.txt +0 -161
  86. data/spec/data/convert_test/ruby/test_ruby.txt +0 -205
  87. data/spec/data/convert_test/ruby_youon/correct_test_ruby_youon.txt +0 -13
  88. data/spec/data/convert_test/ruby_youon/setting.ini +0 -2
  89. data/spec/data/convert_test/ruby_youon/test_ruby_youon.txt +0 -14
  90. data/spec/data/convert_test/sesame/correct_test_sesame.txt +0 -41
  91. data/spec/data/convert_test/sesame/test_sesame.txt +0 -52
  92. data/spec/data/convert_test/to_odd_leader/correct_test_to_odd_leader.txt +0 -21
  93. data/spec/data/convert_test/to_odd_leader/test_to_odd_leader.txt +0 -21
  94. data/spec/data/html_test.html +0 -5
  95. data/spec/data/html_test.txt +0 -4
  96. data/spec/data/test.ini +0 -10
  97. data/spec/device_spec.rb +0 -39
  98. data/spec/downloader_spec.rb +0 -37
  99. data/spec/eventable_spec.rb +0 -172
  100. data/spec/exit_code_spec.rb +0 -67
  101. data/spec/generator/convert_spec_gen.rb +0 -96
  102. data/spec/generator/num_to_kanji_test_gen.rb +0 -33
  103. data/spec/helper_spec.rb +0 -90
  104. data/spec/html_spec.rb +0 -83
  105. data/spec/ini_spec.rb +0 -145
  106. data/spec/input_spec.rb +0 -76
  107. data/spec/logger_spec.rb +0 -92
  108. data/spec/novelinfo_spec.rb +0 -15
  109. data/spec/novelsetting_spec.rb +0 -35
  110. data/spec/num_to_kanji_spec.rb +0 -2482
  111. data/spec/spec_helper.rb +0 -16
  112. data/spec/worker_spec.rb +0 -75
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2013 whiteleaf. All rights reserved.
4
+ #
5
+
6
+ require_relative "../../narou/api"
7
+
8
+ module Command
9
+ class Update < CommandBase
10
+ class GeneralLastupUpdater
11
+ def initialize(options)
12
+ @options = options
13
+ @database = Database.instance
14
+ @narou_novels = Hash.new { |hash, key| hash[key] = [] }
15
+ @other_novels = []
16
+ prepare
17
+ end
18
+
19
+ def save
20
+ @database.save_database
21
+ end
22
+
23
+ def prepare
24
+ @database.each_key do |id|
25
+ next if Narou.novel_frozen?(id)
26
+ setting = Downloader.get_sitesetting_by_target(id)
27
+ if setting["narou_api_url"]
28
+ @narou_novels[setting["narou_api_url"]] << setting["ncode"]
29
+ else
30
+ @other_novels << id
31
+ end
32
+ setting.clear
33
+ end
34
+ end
35
+
36
+ def update_narou_novels
37
+ @narou_novels.each do |api_url, ncodes|
38
+ api = Narou::API.new(api_url: api_url, ncodes: ncodes, of: "nu-gl")
39
+ api.request.each do |result|
40
+ ncode = result["ncode"]
41
+ data = Downloader.get_data_by_target(ncode)
42
+ last_check_date = data["last_check_date"] || data["last_update"]
43
+ if result["novelupdated_at"] > last_check_date
44
+ data["novelupdated_at"] = result["novelupdated_at"]
45
+ data["general_lastup"] = result["general_lastup"]
46
+ tags = data["tags"] ||= []
47
+ tags << Narou::MODIFIED_TAG unless tags.include?(Narou::MODIFIED_TAG)
48
+ end
49
+ data["last_check_date"] = Time.now
50
+ end
51
+ @other_novels += api.private_novels
52
+ end
53
+ end
54
+
55
+ def update_other_novels
56
+ progressbar = ProgressBar.new(@other_novels.size - 1)
57
+ interval = Interval.new(@options["interval"])
58
+
59
+ @other_novels.each_with_index do |id, index|
60
+ progressbar.output(index)
61
+ interval.wait
62
+ begin
63
+ setting = Downloader.get_sitesetting_by_target(id)
64
+ info = NovelInfo.load(setting)
65
+ dates = if info
66
+ {
67
+ "novelupdated_at" => info["novelupdated_at"],
68
+ "general_lastup" => info["general_lastup"]
69
+ }
70
+ else
71
+ # 小説情報ページがない場合は目次から取得する
72
+ get_latest_dates(id)
73
+ end
74
+ rescue OpenURI::HTTPError, Errno::ECONNRESET
75
+ setting.clear
76
+ next
77
+ end
78
+ data = @database[id]
79
+ data.merge!(dates)
80
+ last_check_date = data["last_check_date"] || data["last_update"]
81
+ if data["novelupdated_at"] > last_check_date
82
+ tags = @database[id]["tags"] ||= []
83
+ tags << Narou::MODIFIED_TAG unless tags.include?(Narou::MODIFIED_TAG)
84
+ end
85
+ data["last_check_date"] = Time.now
86
+ setting.clear
87
+ end
88
+ ensure
89
+ progressbar.clear if progressbar
90
+ end
91
+
92
+ # オンラインの目次からgeneral_lastupを取得する
93
+ # ただし、toc.yaml に最新話が存在し、かつsubdateが設定されていたらそれを使う
94
+ def get_latest_dates(target)
95
+ downloader = Downloader.new(target)
96
+ old_toc = downloader.load_toc_file
97
+ downloader.get_latest_table_of_contents(old_toc, through_error: true)
98
+ {
99
+ "novelupdated_at" => downloader.get_novelupdated_at,
100
+ "general_lastup" => downloader.get_general_lastup
101
+ }
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2013 whiteleaf. All rights reserved.
4
+ #
5
+
6
+ module Command
7
+ class Update < CommandBase
8
+ class Interval
9
+ MIN = 2.5 # 作品間ウェイトの最低秒数(処理時間含む)
10
+ FORCE_WAIT_TIME = 2.0 # 強制待機時間
11
+
12
+ def initialize(interval)
13
+ @time = Time.now - MIN
14
+ interval = interval.to_f
15
+ @interval_time = interval >= MIN ? interval : MIN
16
+ end
17
+
18
+ def wait
19
+ wait_time = Time.now - @time
20
+ sleep(@interval_time - wait_time) if wait_time < @interval_time
21
+ @time = Time.now
22
+ end
23
+
24
+ def force_wait
25
+ sleep(FORCE_WAIT_TIME)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -92,7 +92,7 @@ module Command
92
92
  rescue Interrupt => e
93
93
  # 中断されてコンソールへの入力が可能になってから、WEBrick が終了するまで
94
94
  # タイムラグがあって表示がごちゃまぜになるので、終わるのを少し待つ
95
- sleep 3
95
+ sleep 2
96
96
  end
97
97
  end
98
98
  end
@@ -4,6 +4,7 @@
4
4
  #
5
5
 
6
6
  require "optparse"
7
+ require "termcolorlight"
7
8
  require_relative "web/worker"
8
9
 
9
10
  module Command
@@ -69,27 +70,33 @@ module Command
69
70
  #
70
71
  def tagname_to_ids(array)
71
72
  database = Database.instance
72
- tag_index = Hash.new { [] }
73
- database.each do |id, data|
74
- tags = data["tags"] || []
75
- tags.each do |tag|
76
- tag_index[tag] |= [id]
77
- end
78
- end
79
- array.map! { |arg|
80
- if arg =~ /^[0-9]+$/
73
+ tag_index = database.tag_indexies
74
+ all_ids = database.ids
75
+ expanded_array = array.map { |arg|
76
+ if arg =~ /\A\d+\z/
81
77
  # 優先度はID>タグのため、数字のみ指定されたら
82
78
  # そのIDが存在した場合はIDとみなす
83
- next arg if database[arg.to_i]
84
- end
85
- if arg =~ /^tag:(.+)$/
86
- # tag:タグ名 は直接タグと指定できる形式
87
- # (数字タグとIDがかぶった場合にタグを指定出来るようにするもの)
88
- arg = $1
79
+ id = arg.to_i
80
+ next id if database[id]
89
81
  end
90
- ids = tag_index[arg]
82
+ ids =
83
+ case arg
84
+ when /\Atag:(.+)\z/
85
+ # tag:タグ名 は直接タグと指定できる形式
86
+ # (数字タグとIDがかぶった場合にタグを指定出来るようにするもの)
87
+ arg = $1
88
+ tag_index[$1]
89
+ when /\A\^tag:(.+)\z/
90
+ # ^tag:タグ名 は除外タグ指定
91
+ arg = $1
92
+ indexies = tag_index[$1]
93
+ indexies.empty? ? [] : all_ids - indexies
94
+ else
95
+ tag_index[arg]
96
+ end
91
97
  ids.empty? ? arg : ids
92
- }.flatten!
98
+ }.flatten.uniq
99
+ array.replace(expanded_array)
93
100
  end
94
101
 
95
102
  #
@@ -345,7 +345,7 @@ class ConverterBase
345
345
  data.replace(NKF.nkf("-wWX", data).tr("\u2014", "―"))
346
346
  end
347
347
 
348
- # ミュート(ノノカギ)化する記号定義
348
+ # ミニュート(ノノカギ)化する記号定義
349
349
  SINGLE_MINUTE_FAMILY = %!‘’'!
350
350
  DOUBLE_MINUTE_FAMILY = %!“”〝〟"!
351
351
 
@@ -353,11 +353,11 @@ class ConverterBase
353
353
  # 半角記号を全角に変換
354
354
  #
355
355
  def symbols_to_zenkaku(data)
356
+ # MEMO: シングルミニュートを表示出来るフォントはほとんど無いためダブルにする
356
357
  data.gsub!(/[#{SINGLE_MINUTE_FAMILY}]([^"\n]+?)[#{SINGLE_MINUTE_FAMILY}]/, "〝\\1〟")
357
- # MEMO: シングルミュートを表示出来るフォントはほとんど無いためダブルにする
358
358
  data.gsub!(/[#{DOUBLE_MINUTE_FAMILY}]([^"\n]+?)[#{DOUBLE_MINUTE_FAMILY}]/, "〝\\1〟")
359
359
  data.tr!("-=+/*《》'\"%$#&!?<><>()|‐,._;:\[\]{}",
360
- "-=+/*≪≫’〝%$#&!?〈〉〈〉()|-,._;:[]")
360
+ "-=+/*≪≫’〝%$#&!?〈〉〈〉()|-,._;:[]{}")
361
361
  data.gsub!("\\", "¥")
362
362
  data
363
363
  end
@@ -484,6 +484,7 @@ class ConverterBase
484
484
  # たまに見かける誤字対策
485
485
  data.gsub!(/。 /, "。")
486
486
  data.gsub!(/([?!])。/, "\\1")
487
+ data.gsub!(/([?!])、/, "\\1")
487
488
  end
488
489
 
489
490
  #
@@ -1416,6 +1417,10 @@ class ConverterBase
1416
1417
 
1417
1418
  def double_dash_to_image(text, output_text_dir)
1418
1419
  return text unless @setting.enable_double_dash_to_image
1420
+ # サブタイトルの中の場合は無視する
1421
+ # (サブタイトルは文字を大きくしているので、画像の位置がずれてしまうため)
1422
+ return text if @text_type == "subtitle"
1423
+
1419
1424
  begin
1420
1425
  # AozoraEpub3 は相対パスじゃないとエラーになるので相対パスに変換
1421
1426
  dash_paths = dash_image_relative_paths(Narou.get_preset_dir, output_text_dir)
@@ -1425,7 +1430,7 @@ class ConverterBase
1425
1430
  # 違う場合、相対パスを計算できなくなる。そのための対処として、.narou ディレクトリ
1426
1431
  # に画像データをコピーし、同一ドライブ内で相対パスを取れるようにする
1427
1432
  copy_dash_images_to_local_setting_dir
1428
- dash_paths = dash_image_relative_paths(Narou.get_local_setting_dir, output_text_dir)
1433
+ dash_paths = dash_image_relative_paths(Narou.local_setting_dir, output_text_dir)
1429
1434
  else
1430
1435
  raise
1431
1436
  end
@@ -1449,7 +1454,7 @@ class ConverterBase
1449
1454
 
1450
1455
  def copy_dash_images_to_local_setting_dir
1451
1456
  DASH_FILES.each do |name|
1452
- path = File.join(Narou.get_local_setting_dir, name)
1457
+ path = File.join(Narou.local_setting_dir, name)
1453
1458
  unless File.exist?(path)
1454
1459
  FileUtils.copy(File.join(Narou.get_preset_dir, name), path)
1455
1460
  end
@@ -15,10 +15,6 @@ class Database
15
15
  ARCHIVE_ROOT_DIR_PATH = "小説データ/"
16
16
  DATABASE_NAME = "database"
17
17
 
18
- if Narou.already_init?
19
- @@archive_root_path = File.expand_path(File.join(Narou.get_root_dir, ARCHIVE_ROOT_DIR_PATH))
20
- end
21
-
22
18
  def [](key)
23
19
  @database[key]
24
20
  end
@@ -69,7 +65,7 @@ class Database
69
65
  # 小説格納用のルートディレクトリを取得
70
66
  #
71
67
  def self.archive_root_path
72
- @@archive_root_path
68
+ @archive_root_path ||= File.expand_path(File.join(Narou.get_root_dir, ARCHIVE_ROOT_DIR_PATH))
73
69
  end
74
70
 
75
71
  def save_database
@@ -80,6 +76,10 @@ class Database
80
76
  @database
81
77
  end
82
78
 
79
+ def ids
80
+ @database.keys
81
+ end
82
+
83
83
  def novel_exists?(id)
84
84
  return nil if id.nil?
85
85
  @database.keys.include?(id.to_i)
@@ -114,4 +114,15 @@ class Database
114
114
  values
115
115
  end
116
116
  end
117
+
118
+ def tag_indexies
119
+ result = Hash.new { [] }
120
+ @database.each do |id, data|
121
+ tags = data["tags"] || []
122
+ tags.each do |tag|
123
+ result[tag.to_s] |= [id]
124
+ end
125
+ end
126
+ result
127
+ end
117
128
  end
@@ -104,7 +104,11 @@ class Device
104
104
  end
105
105
 
106
106
  def ejectable?
107
- Device.support_eject? && connecting?
107
+ if Device.respond_to?(:ejectable?)
108
+ Device.ejectable?(@device_module::VOLUME_NAME)
109
+ else
110
+ Device.support_eject? && connecting?
111
+ end
108
112
  end
109
113
 
110
114
  def find_documents_directory(device_root_dir)
@@ -2,17 +2,77 @@
2
2
  #
3
3
  # Copyright 2013 whiteleaf. All rights reserved.
4
4
  #
5
+ # rubocop:disable Lint/AssignmentInCondition
5
6
 
6
- module Device::Library
7
- module Linux
8
- def get_device_root_dir(volume_name)
9
- %w(/media /mnt).each do |mount_root|
10
- path = File.join(mount_root, volume_name)
11
- if File.directory?(path)
12
- return path
7
+ require "etc"
8
+
9
+ class Device
10
+ module Library
11
+ module Linux
12
+ username = Etc.getpwuid(Process.euid).name
13
+ @@mount_roots = %w(/media /mnt)
14
+ @@mount_roots << "/run/media/" + username # udisks2 による自動マウント(デフォルトの場所)
15
+ @@mount_roots << "/media/" + username # udisks2 による自動マウント(Ubuntuの場合)
16
+
17
+ # :reek:UtilityFunction
18
+ def get_device_root_dir(volume_name)
19
+ @@mount_roots.each do |mount_root|
20
+ path = File.join(mount_root, volume_name)
21
+ if File.directory?(path)
22
+ return path
23
+ end
24
+ end
25
+ nil
26
+ end
27
+
28
+ # 端末のデバイスファイル名と uhelper オプションの値を取得
29
+ def device_mount_info(volume_name)
30
+ device_root = get_device_root_dir(volume_name)
31
+ raise Device::CantEject, "端末が接続されていません" unless device_root
32
+
33
+ pattern = %r!^(/dev/[^ ]+) .* #{device_root} .*\Wuhelper=(\w+)!
34
+ open("|mount") do |io|
35
+ while line = io.gets
36
+ if line =~ pattern
37
+ return [$1, $2]
38
+ end
39
+ end
40
+ end
41
+ [nil, nil]
42
+ end
43
+
44
+ def ejectable?(volume_name)
45
+ case device_mount_info(volume_name)[1]
46
+ when "udisks", "udisks2"
47
+ true
48
+ else
49
+ false
50
+ end
51
+ rescue Device::CantEject
52
+ false
53
+ end
54
+
55
+ def eject(volume_name)
56
+ device, uhelper = device_mount_info(volume_name)
57
+
58
+ case uhelper
59
+ when "udisks"
60
+ commands = ["udisks --unmount #{device}",
61
+ "udisks --detach #{device.chop}"]
62
+ when "udisks2"
63
+ commands = ["udisksctl unmount -b #{device} --no-user-interaction",
64
+ "udisksctl power-off -b #{device.chop} --no-user-interaction"]
65
+ else
66
+ raise Device::CantEject, "udisks または udisks2 によって自動マウントされたデバイスではありません。"
67
+ end
68
+
69
+ commands.each do |command|
70
+ status, _stdout, stderr = systemu(command)
71
+ unless status.success?
72
+ raise Device::CantEject, "#{command}: #{stderr.strip}"
73
+ end
13
74
  end
14
75
  end
15
- nil
16
76
  end
17
77
  end
18
78
  end
@@ -13,7 +13,6 @@ require_relative "template"
13
13
  require_relative "database"
14
14
  require_relative "inventory"
15
15
  require_relative "eventable"
16
- require_relative "narou/api"
17
16
  require_relative "html"
18
17
  require_relative "input"
19
18
 
@@ -214,10 +213,17 @@ class Downloader
214
213
  #
215
214
  # 小説サイトの定義ファイルを全部読み込む
216
215
  #
216
+ # スクリプト同梱の設定ファイルを読み込んだあと、ユーザの小説の管理ディレクトリ内にある
217
+ # webnovel ディレクトリからも定義ファイルを読み込む
218
+ #
217
219
  def self.load_settings
218
220
  settings = @@__settings_cache ||= []
219
221
  return settings unless settings.empty?
220
- Dir.glob(File.join(Narou.get_script_dir, NOVEL_SITE_SETTING_DIR, "*.yaml")) do |path|
222
+ load_paths = [
223
+ File.join(Narou.get_script_dir, NOVEL_SITE_SETTING_DIR, "*.yaml"),
224
+ File.join(Narou.get_root_dir, NOVEL_SITE_SETTING_DIR, "*.yaml")
225
+ ].join("\0")
226
+ Dir.glob(load_paths) do |path|
221
227
  setting = SiteSetting.load_file(path)
222
228
  if setting["name"] == "小説家になろう"
223
229
  @@narou = setting
@@ -261,7 +267,8 @@ class Downloader
261
267
  # サブディレクトリ名を生成
262
268
  #
263
269
  def self.create_subdirecotry_name(title)
264
- title.start_with?("n") ? title[1..2] : title[0..1]
270
+ name = title.start_with?("n") ? title[1..2] : title[0..1]
271
+ name.strip
265
272
  end
266
273
 
267
274
  if Narou.already_init?
@@ -364,6 +371,7 @@ class Downloader
364
371
  def run_download
365
372
  old_toc = @new_novel ? nil : load_toc_file
366
373
  latest_toc = get_latest_table_of_contents(old_toc)
374
+ latest_toc_subtitles = latest_toc["subtitles"]
367
375
  unless latest_toc
368
376
  @stream.error @setting["toc_url"] + " の目次データが取得出来ませんでした"
369
377
  return :failed
@@ -381,12 +389,12 @@ class Downloader
381
389
  end
382
390
  init_raw_dir
383
391
  if old_toc.empty? || @force
384
- update_subtitles = latest_toc["subtitles"]
392
+ update_subtitles = latest_toc_subtitles
385
393
  else
386
- update_subtitles = update_body_check(old_toc["subtitles"], latest_toc["subtitles"])
394
+ update_subtitles = update_body_check(old_toc["subtitles"], latest_toc_subtitles)
387
395
  end
388
396
 
389
- if old_toc.empty? && update_subtitles.count == 0
397
+ if old_toc.empty? && update_subtitles.size.zero?
390
398
  @stream.error "#{@setting['title']} の目次がありません"
391
399
  return :failed
392
400
  end
@@ -414,7 +422,7 @@ class Downloader
414
422
  end
415
423
  update_database
416
424
  :ok
417
- when old_toc["subtitles"].size > latest_toc["subtitles"].size
425
+ when old_toc["subtitles"].size > latest_toc_subtitles.size
418
426
  # 削除された節がある(かつ更新がない)場合
419
427
  @stream.puts "#{id_and_title} は一部の話が削除されています"
420
428
  :ok
@@ -430,6 +438,9 @@ class Downloader
430
438
  else
431
439
  :none
432
440
  end
441
+
442
+ @@database[@id]["general_all_no"] = latest_toc_subtitles.size
443
+
433
444
  save_novel_data(TOC_FILE_NAME, latest_toc)
434
445
  tags = @new_novel ? [] : @@database[@id]["tags"] || []
435
446
  if novel_end?
@@ -628,11 +639,7 @@ class Downloader
628
639
  end
629
640
 
630
641
  def get_novel_status
631
- novel_status = if false # @setting["narou_api_url"]
632
- Narou::API.new(@setting, "nt-e")
633
- else
634
- NovelInfo.load(@setting)
635
- end
642
+ novel_status = NovelInfo.load(@setting, of: "nt-e")
636
643
  unless novel_status
637
644
  novel_status = {
638
645
  "novel_type" => NOVEL_TYPE_SERIES,
@@ -687,7 +694,7 @@ class Downloader
687
694
  #
688
695
  def get_title
689
696
  return @title if @title
690
- @title = @setting["title"]
697
+ @title = @setting["title"] || @@database[@id]["title"]
691
698
  if @setting["title_strip_pattern"]
692
699
  @title = @title.gsub(/#{@setting["title_strip_pattern"]}/, "").gsub(/^[ \s]*(.+?)[ \s]*?$/, "\\1")
693
700
  end
@@ -736,7 +743,7 @@ class Downloader
736
743
  @setting = s
737
744
  toc_url = @setting["toc_url"]
738
745
  end
739
- toc_source = Helper.restor_entity(Helper.pretreatment_source(toc_fp.read, @setting["encoding"]))
746
+ toc_source = Helper.restore_entity(Helper.pretreatment_source(toc_fp.read, @setting["encoding"]))
740
747
  raise DownloaderNotFoundError if Downloader.detect_error_message(@setting, toc_source)
741
748
  end
742
749
  rescue DownloaderForceRedirect
@@ -757,13 +764,7 @@ class Downloader
757
764
  toc_source = get_toc_source
758
765
  return nil unless toc_source
759
766
  @setting.multi_match(toc_source, "tcode")
760
- #if @setting["narou_api_url"]
761
- if false
762
- # なろうAPIの出力がおかしいので直るまで使用中止
763
- info = Narou::API.new(@setting, "t-s-gf-gl-nu-w")
764
- else
765
- info = NovelInfo.load(@setting, toc_source)
766
- end
767
+ info = NovelInfo.load(@setting, toc_source: toc_source)
767
768
  if info
768
769
  raise DownloaderNotFoundError unless info["title"]
769
770
  @setting["title"] = info["title"]
@@ -1089,7 +1090,7 @@ class Downloader
1089
1090
  end
1090
1091
  raw = download_raw_data(subtitle_url)
1091
1092
  if @setting["is_narou"]
1092
- raw = Helper.restor_entity(raw)
1093
+ raw = Helper.restore_entity(raw)
1093
1094
  save_raw_data(raw, subtitle_info)
1094
1095
  element = extract_elements_in_section(raw, subtitle_info["subtitle"])
1095
1096
  element["data_type"] = "text"
@@ -1136,7 +1137,7 @@ narou s download.wait-steps=5
1136
1137
  cookie = @setting["cookie"] || ""
1137
1138
  begin
1138
1139
  open_uri_options = make_open_uri_options("Cookie" => cookie, allow_redirections: :safe)
1139
- open(url, open_uri_options) do |fp|
1140
+ open(url, "r:#{@setting["encoding"]}", open_uri_options) do |fp|
1140
1141
  raw = Helper.pretreatment_source(fp.read, @setting["encoding"])
1141
1142
  end
1142
1143
  rescue OpenURI::HTTPError => e