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
@@ -8,18 +8,20 @@ require "time"
8
8
  require_relative "html"
9
9
 
10
10
  class NovelInfo
11
- REFRESH_INTERVAL = 10 * 60 # キャッシュを捨てて再取得するまでの時間(s)
11
+ REFRESH_INTERVAL = 10 # キャッシュを捨てて再取得するまでの時間(s)
12
+ DEFAULT_OF = "t-nt-ga-s-gf-nu-gl-w"
12
13
  @@novel_info_parameters = {}
13
14
 
14
- def self.load(setting, toc_source = nil)
15
- info = new(setting, toc_source)
15
+ def self.load(setting, toc_source: nil, of: DEFAULT_OF)
16
+ info = new(setting, toc_source, of)
16
17
  info.parse_novel_info
17
18
  end
18
19
 
19
- def initialize(setting, toc_source = nil)
20
+ def initialize(setting, toc_source = nil, of = DEFAULT_OF)
20
21
  @setting = setting
21
22
  @ncode = @setting["ncode"]
22
23
  @toc_source = toc_source
24
+ @of = of
23
25
  @@novel_info_parameters[@setting["name"]] ||= {}
24
26
  end
25
27
 
@@ -35,8 +37,7 @@ class NovelInfo
35
37
  end
36
38
  need_reload = true
37
39
  end
38
- of = "t-nt-ga-s-gf-nu-gl-w"
39
- request_output_parameters = of.split("-")
40
+ request_output_parameters = @of.split("-")
40
41
  info_source = ""
41
42
 
42
43
  if @setting["novel_info_url"] == @setting["toc_url"] && @toc_source && !need_reload
@@ -47,7 +48,7 @@ class NovelInfo
47
48
  cookie = @setting["cookie"] || ""
48
49
  open_uri_options = make_open_uri_options("Cookie" => cookie, allow_redirections: :safe)
49
50
  open(info_url, open_uri_options) do |fp|
50
- info_source = Helper.restor_entity(Helper.pretreatment_source(fp.read, @setting["encoding"]))
51
+ info_source = Helper.restore_entity(Helper.pretreatment_source(fp.read, @setting["encoding"]))
51
52
  raise Downloader::DownloaderNotFoundError if Downloader.detect_error_message(@setting, info_source)
52
53
  end
53
54
  end
@@ -389,6 +389,7 @@ $s 2045年までの残り時間(10分単位の4桁の36進数)
389
389
  $t 小説のタイトル
390
390
  $ns 小説が掲載されているサイト名
391
391
  $nt 小説種別(短編 or 連載)
392
+ $ntag 小説のタグをカンマ区切りにしたもの
392
393
  EOS
393
394
  },
394
395
  {
@@ -15,7 +15,7 @@ class ProgressBar
15
15
  end
16
16
 
17
17
  def output(num)
18
- return if $debug
18
+ return if silence?
19
19
  if num > @max
20
20
  raise OverRangeError, "`#{num}` over `#{@max}(max)`"
21
21
  end
@@ -28,11 +28,15 @@ class ProgressBar
28
28
  end
29
29
 
30
30
  def clear
31
- return if $debug
31
+ return if silence?
32
32
  STDOUT.print " " * 79 + "\r"
33
33
  end
34
34
 
35
35
  def calc_ratio(num)
36
36
  num / @max
37
37
  end
38
+
39
+ def silence?
40
+ $debug || ENV["NAROU_ENV"] == "test"
41
+ end
38
42
  end
@@ -4,6 +4,7 @@
4
4
  #
5
5
 
6
6
  require "yaml"
7
+ require_relative "narou/api"
7
8
 
8
9
  class SiteSetting
9
10
  def self.load_file(path)
@@ -56,7 +57,7 @@ class SiteSetting
56
57
  end
57
58
 
58
59
  def is_container?(value)
59
- value.kind_of?(Hash) || value.kind_of?(Array)
60
+ value.is_a?(Hash) || value.is_a?(Array) || value.is_a?(Narou::API)
60
61
  end
61
62
 
62
63
  def replace_group_values(key, option_values = {})
@@ -3,4 +3,4 @@
3
3
  # Copyright 2013 whiteleaf. All rights reserved.
4
4
  #
5
5
 
6
- Version = "2.9.5"
6
+ Version = "3.0.0"
@@ -28,6 +28,15 @@ module Narou::ServerHelpers
28
28
  end.join(" ")
29
29
  end
30
30
 
31
+ #
32
+ # タグをHTMLで装飾する(除外タグ指定用)
33
+ #
34
+ def decorate_exclusion_tags(tags)
35
+ tags.sort.map do |tag|
36
+ %!<span class="tag label label-#{Command::Tag.get_color(tag)}" data-exclusion-tag="#{escape_html(tag)}">^tag:#{escape_html(tag)}</span>!
37
+ end.join(" ")
38
+ end
39
+
31
40
  #
32
41
  # Rubyバージョンを構築
33
42
  #
@@ -103,7 +112,7 @@ module Narou::ServerHelpers
103
112
  end
104
113
 
105
114
  def notepad_text_path
106
- File.join(Narou.get_local_setting_dir, "notepad.txt")
115
+ File.join(Narou.local_setting_dir, "notepad.txt")
107
116
  end
108
117
  end
109
118
 
@@ -190,10 +199,16 @@ class Narou::AppServer < Sinatra::Base
190
199
  def self.my_ipaddress
191
200
  @@__ipaddress ||= -> {
192
201
  udp = UDPSocket.new
193
- udp.connect("128.0.0.0", 7)
194
- adrs = Socket.unpack_sockaddr_in(udp.getsockname)[1]
195
- udp.close
196
- adrs
202
+ begin
203
+ # 128.0.0.0 への送信に使用されるNICのアドレスを取得
204
+ udp.connect("128.0.0.0", 7)
205
+ Socket.unpack_sockaddr_in(udp.getsockname)[1]
206
+ rescue Errno::ENETUNREACH
207
+ # 128.0.0.0 へのルーティングがないとき
208
+ "127.0.0.1"
209
+ ensure
210
+ udp.close
211
+ end
197
212
  }.call
198
213
  end
199
214
 
@@ -201,6 +216,7 @@ class Narou::AppServer < Sinatra::Base
201
216
  super
202
217
  puts_hello_messages
203
218
  start_device_ejectable_event
219
+ fill_general_all_no_in_database
204
220
  end
205
221
 
206
222
  def puts_hello_messages
@@ -221,6 +237,23 @@ class Narou::AppServer < Sinatra::Base
221
237
  end
222
238
  end
223
239
 
240
+ def general_all_no_by_toc(id)
241
+ toc = Downloader.new(id).load_toc_file
242
+ return nil unless toc
243
+ toc["subtitles"].size
244
+ end
245
+
246
+ # 話数の設定されていない小説の話数を取得して埋める
247
+ def fill_general_all_no_in_database
248
+ modified = false
249
+ Database.instance.each do |id, data|
250
+ next if data["general_all_no"]
251
+ data["general_all_no"] = general_all_no_by_toc(id)
252
+ modified = true
253
+ end
254
+ Database.instance.save_database if modified
255
+ end
256
+
224
257
  # ===================================================================
225
258
  # ルーティング
226
259
  # ===================================================================
@@ -504,7 +537,10 @@ class Narou::AppServer < Sinatra::Base
504
537
  download: %!<a href="/novels/#{id}/download" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-download-alt"></span></a>!,
505
538
  frozen: Narou.novel_frozen?(id),
506
539
  new_arrivals_date: data["new_arrivals_date"].tap { |m| break m.to_i if m },
507
- general_lastup: data["general_lastup"].tap { |m| break m.to_i if m }
540
+ general_lastup: data["general_lastup"].tap { |m| break m.to_i if m },
541
+ # 掲載話数
542
+ general_all_no: data["general_all_no"],
543
+ last_check_date: data["last_check_date"].tap { |m| break m.to_i if m },
508
544
  }
509
545
  end
510
546
  json json_objects
@@ -551,6 +587,22 @@ class Narou::AppServer < Sinatra::Base
551
587
  end
552
588
  end
553
589
 
590
+ post "/api/update_by_tag" do
591
+ tags = params["tags"] || []
592
+ exclusion_tags = params["exclusion_tags"] || []
593
+ tag_params = tags.map do |tag|
594
+ "tag:#{tag}"
595
+ end
596
+ tag_params += exclusion_tags.map do |tag|
597
+ "^tag:#{tag}"
598
+ end
599
+ pass if tag_params.empty?
600
+ Narou::Worker.push do
601
+ CommandLine.run!(["update", tag_params])
602
+ @@push_server.send_all(:"table.reload")
603
+ end
604
+ end
605
+
554
606
  post "/api/send" do
555
607
  ids = select_valid_novel_ids(params["ids"]) || []
556
608
  Narou::Worker.push do
@@ -666,7 +718,7 @@ class Narou::AppServer < Sinatra::Base
666
718
  result
667
719
  end
668
720
 
669
- post "/api/taginfo.json" do
721
+ get "/api/taginfo.json" do
670
722
  ids = select_valid_novel_ids(params["ids"]) or pass
671
723
  ids.map!(&:to_i)
672
724
  database = Database.instance
@@ -677,7 +729,8 @@ class Narou::AppServer < Sinatra::Base
677
729
  tag_info[tag] ||= {
678
730
  count: 0,
679
731
  tag: tag,
680
- html: decorate_tags([tag])
732
+ html: decorate_tags([tag]),
733
+ exclusion_html: params["with_exclusion"] ? decorate_exclusion_tags([tag]) : ""
681
734
  }
682
735
  if ids.include?(data["id"])
683
736
  tag_info[tag][:count] += 1
@@ -717,9 +770,19 @@ class Narou::AppServer < Sinatra::Base
717
770
  end
718
771
 
719
772
  post "/api/update_general_lastup" do
773
+ option = params["option"]
774
+ option = nil if option == "all"
775
+ is_update_modified = params["is_update_modified"] == "true"
720
776
  Narou::Worker.push do
721
- CommandLine.run!(["update", "--gl"])
777
+ CommandLine.run!(["update", "--gl", option].compact)
722
778
  @@push_server.send_all(:"table.reload")
779
+ @@push_server.send_all(:"tag.updateCanvas")
780
+ if is_update_modified
781
+ puts "<yellow>#{Narou::MODIFIED_TAG} タグの付いた小説を更新します</yellow>".termcolor
782
+ CommandLine.run!(["update", "tag:#{Narou::MODIFIED_TAG}"])
783
+ @@push_server.send_all(:"table.reload")
784
+ @@push_server.send_all(:"tag.updateCanvas")
785
+ end
723
786
  end
724
787
  end
725
788
 
@@ -572,12 +572,39 @@ var Narou = (function() {
572
572
  }
573
573
  },
574
574
 
575
+ _restoreUpdateGeneralLastupChecked: function() {
576
+ return storage.get("update_general_lastup_checked") || {
577
+ narou: true, other: false, updateModified: false
578
+ };
579
+ },
580
+
581
+ _storeUpdateGeneralLastupChecked: function(checkedObject) {
582
+ storage.set("update_general_lastup_checked", checkedObject);
583
+ storage.save();
584
+ },
585
+
586
+ _updateGeneralLastupHtmlRenderer: _.template(
587
+ (function () {/*
588
+ <p>凍結済みを除く各小説の最新話掲載日のみを確認して反映させます。<br>
589
+ なろうAPIを使える小説はAPIを使用して一括で確認するので、高速に掲載日を調べることが出来ます。その他の小説はひとつずつ確認するので時間がかかります。</p>
590
+ <ul><li>検索除外されている小説はAPIでは確認出来ません。</li>
591
+ <li>最新話掲載日は通常のUpdateでも更新されています。</li>
592
+ <li>更新が確認された小説には<code>modified</code>タグが自動で追加されます。Updateすることで削除されます。(ジャンルなどのNarou.rbが見ていない情報だけが変更されても更新されたとみなされます)</li>
593
+ <li>“実際に小説のデータが修正されてからなろうAPIに反映されるまで平均5分程度(最大2時間)の誤差があります。”<span class="text-muted">(<a href="http://dev.syosetu.com/man/api/" target="_blank">公式サイト</a>から引用)</span></li></ul>
594
+ <p class="text-right">
595
+ <label><input type="checkbox" id="update-gl-narou" <% if (narou) { %>checked<% } %>> なろう小説をAPIで確認</label>
596
+ &nbsp;&nbsp;&nbsp;<label><input type="checkbox" id="update-gl-other" <% if (other) { %>checked<% } %>> その他の小説を確認</label><br>
597
+ <label><input type="checkbox" id="update-gl-and-update-modified" <% if (updateModified) { %>checked<% } %>> 確認後にmodifiedタグが付いた小説をUpdate</label>
598
+ </p>
599
+ */}).toString().replace(/(\n)/g, '').split('*')[1]
600
+ ),
601
+
575
602
  updateGeneralLastup: function() {
603
+ var self = this;
604
+ var checkedObject = this._restoreUpdateGeneralLastupChecked();
576
605
  bootbox.dialog({
577
- title: "最新話掲載日の更新",
578
- message: "凍結済みを除く各小説の最新話掲載日のみを更新して反映させます。<br>" +
579
- "最新話掲載日は通常時のUpdateでも更新されるので、手動で更新する必要は基本的にはありません。<br>" +
580
- "掲載日だけを調べて、選択的にUpdateをかけるなど、用途を理解した上で小説サイトのサーバーに負荷をかけない範囲でご利用下さい。",
606
+ title: "最新話掲載日の確認",
607
+ message: this._updateGeneralLastupHtmlRenderer(checkedObject),
581
608
  backdrop: true,
582
609
  buttons: {
583
610
  cancel: {
@@ -585,21 +612,47 @@ var Narou = (function() {
585
612
  className: "btn-default",
586
613
  },
587
614
  main: {
588
- label: "更新する",
615
+ label: "確認する",
589
616
  className: "btn-primary",
590
617
  callback: function() {
591
- $.post("/api/update_general_lastup");
618
+ var glNarou = $("#update-gl-narou").is(":checked");
619
+ var glOther = $("#update-gl-other").is(":checked");
620
+ var isUpdateModified = $("#update-gl-and-update-modified").is(":checked");
621
+ self._storeUpdateGeneralLastupChecked({
622
+ narou: glNarou, other: glOther, updateModified: isUpdateModified
623
+ });
624
+ if (!glNarou && !glOther) return;
625
+ var option = glNarou && glOther && "all";
626
+ if (!option && glNarou) option = "narou";
627
+ if (!option && glOther) option = "other";
628
+ $.post("/api/update_general_lastup", { option: option, is_update_modified: isUpdateModified });
592
629
  }
593
630
  },
594
631
  }
595
632
  });
596
633
  },
597
634
 
635
+ updateGeneralLastupNarou: function() {
636
+ $.post("/api/update_general_lastup", { option: "narou", is_update_modified: false });
637
+ },
638
+
639
+ updateGeneralLastupOther: function() {
640
+ $.post("/api/update_general_lastup", { option: "other", is_update_modified: false });
641
+ },
642
+
643
+ updateGeneralLastupUpdateModified: function() {
644
+ $.post("/api/update_by_tag", { tags: ["modified"] });
645
+ },
646
+
598
647
  updateForce: function() {
599
648
  var ids = this._getSelectedIds(arguments);
600
649
  $.post("/api/update", { ids: ids, force: true });
601
650
  },
602
651
 
652
+ updateByTag: function() {
653
+ UpdateByTagBox.open();
654
+ },
655
+
603
656
  send: function() {
604
657
  var ids = this._getSelectedIds(arguments);
605
658
  $.post("/api/send", { "ids": ids });
@@ -1092,11 +1145,11 @@ var Narou = (function() {
1092
1145
  var str = sprintf(
1093
1146
  "%(current)s %(exclude_flag)stag:%(tag_name)s",
1094
1147
  {
1095
- current: this.myfilter.val(),
1096
- exclude_flag: exclude ? "-" : "",
1148
+ current: _.trimEnd(this.myfilter.val()),
1149
+ exclude_flag: exclude ? "^" : "",
1097
1150
  tag_name: tag_name
1098
1151
  });
1099
- this.myfilter.val(str.trim());
1152
+ this.myfilter.val(_.trimStart(str) + " ");
1100
1153
  }
1101
1154
  else {
1102
1155
  this.removeAllTagsByFilter();
@@ -1119,7 +1172,7 @@ var Narou = (function() {
1119
1172
  var words = string.split(/\s+/);
1120
1173
  result.normal =
1121
1174
  _.filter(words, function(word) {
1122
- if (word.match(/^(-?)tag:(.+)$/i)) {
1175
+ if (word.match(/^([-^]?)tag:(.+)$/i)) {
1123
1176
  var exclude_flag = !!RegExp.$1;
1124
1177
  var tag_name = RegExp.$2;
1125
1178
  if (exclude_flag)
@@ -1149,8 +1202,8 @@ var Narou = (function() {
1149
1202
  },
1150
1203
 
1151
1204
  _searchFn: function() {
1152
- var filter_string = this.myfilter.val().trim();
1153
- var words = this.splitFilter(filter_string);
1205
+ var filter_string = this.myfilter.val();
1206
+ var words = this.splitFilter(_.trim(filter_string));
1154
1207
  var normal_words = words.normal;
1155
1208
 
1156
1209
  this.clearTagCaches();
@@ -1279,7 +1332,7 @@ var Narou = (function() {
1279
1332
  }
1280
1333
  }
1281
1334
 
1282
- $.post("/api/taginfo.json", { ids: ids }, function(taginfo) {
1335
+ $.get("/api/taginfo.json", { ids: ids }, function(taginfo) {
1283
1336
  _.each(taginfo, function(info) {
1284
1337
  var label = $('<label><input type="checkbox" data-tagname="' + info.tag.replace(/"/g, "&quot;") +
1285
1338
  '" data-default-checkstate=' + calcState(info.count) + '> ' + info.html + '&nbsp;&nbsp;</label>');
@@ -1385,6 +1438,70 @@ var Narou = (function() {
1385
1438
  },
1386
1439
  });
1387
1440
 
1441
+ /*************************************************************************
1442
+ * タグを指定して更新ダイアログ
1443
+ *************************************************************************/
1444
+ var UpdateByTagBox = {
1445
+ open: function() {
1446
+ this._createEditorField(function(field) {
1447
+ bootbox.dialog({
1448
+ title: "タグを指定してアップデート",
1449
+ message: field,
1450
+ buttons: {
1451
+ cancel: {
1452
+ label: "キャンセル",
1453
+ className: "btn-default",
1454
+ },
1455
+ main: {
1456
+ label: "更新する",
1457
+ className: "btn-primary",
1458
+ callback: function() {
1459
+ var tags = [];
1460
+ var exclusion_tags = [];
1461
+ $("#update-by-tag-field input[type=checkbox]").each(function(i, v) {
1462
+ if ($(v).is(":checked")) {
1463
+ var tagname = $(v).data("tagname");
1464
+ var exclusion_tagname = $(v).data("exclusionTagname");
1465
+ if (tagname)
1466
+ tags.push(tagname);
1467
+ else if (exclusion_tagname)
1468
+ exclusion_tags.push(exclusion_tagname);
1469
+ }
1470
+ });
1471
+ $.post("/api/update_by_tag", {
1472
+ tags: tags,
1473
+ exclusion_tags: exclusion_tags
1474
+ });
1475
+ }
1476
+ }
1477
+ }
1478
+ });
1479
+ });
1480
+ },
1481
+
1482
+ _createEditorField: function(callback) {
1483
+ var field = $("<div id=update-by-tag-field class=form-group>");
1484
+ $.get("/api/taginfo.json", { ids: [0], with_exclusion: true }, function(taginfo) {
1485
+ var div = $("<div><p>更新したい小説のタグにチェックを入れて下さい。</p>");
1486
+ _.each(taginfo, function(info) {
1487
+ var label = $('<label><input type="checkbox" data-tagname="' + info.tag.replace(/"/g, "&quot;") + '"> ' +
1488
+ info.html + '&nbsp;&nbsp;</label>');
1489
+ div.append(label);
1490
+ });
1491
+ field.append(div);
1492
+ field.append("<p><br></p>");
1493
+ div = $("<div><p>除外タグを指定して更新したいものがあればチェックを入れて下さい。</p>");
1494
+ _.each(taginfo, function(info) {
1495
+ var exclusion_label = $('<label><input type="checkbox" data-exclusion-tagname="' + info.tag.replace(/"/g, "&quot;") + '"> ' +
1496
+ info.exclusion_html + '&nbsp;&nbsp;</label>');
1497
+ div.append(exclusion_label);
1498
+ });
1499
+ field.append(div);
1500
+ callback(field);
1501
+ });
1502
+ },
1503
+ };
1504
+
1388
1505
  /*************************************************************************
1389
1506
  * ドラッグ&ドロップ関係
1390
1507
  *************************************************************************/