narou 3.1.9 → 3.1.10

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9da92655da0ae271cb9baf17ac878b0b58a15c84
4
- data.tar.gz: 04b4bc4a9feabacc589d02b1ec3e500c8d084f6b
3
+ metadata.gz: 6e8758049a5df12f1acf6eb0235bedf7678379f3
4
+ data.tar.gz: 1418c946aae5fc53c40c6b5ce4d8ae51cf780457
5
5
  SHA512:
6
- metadata.gz: 7ed156b7110edc879ebafb1b2d0c3fdf3437c2f8a16f6ccc3c10e57f9c39154a2409e4c6e325576b2cc9f4a0fccef2765fd022b7886461f149eb535206d540ab
7
- data.tar.gz: d5464c1f69e942af6ad68e33902f1d78ee487b3a36128210ab114b971c8620c7e9d1f91a3931380bb6480b79ff409a17c7762b7181a911197cd074fede6354df
6
+ metadata.gz: 3aa7541b6f853403360dd46dc356615561496df90ad036110f09966b9983041791e15fb22dce9ead4f3e0f7d19948947438ab208057071b6542b247bd55c3b81
7
+ data.tar.gz: 3fb44128d5306ff09a9d07b595976b73b652c66c8273dcb962e324a57a4d94a50cab6f0da0fa4de65192b045cb9ba8700f84cb6b2dda7bb83fcbf1410de959e7
@@ -2,6 +2,22 @@
2
2
  更新履歴 - ChangeLog
3
3
  ====================
4
4
 
5
+ 3.1.10: 2017/11/20
6
+ ------------------
7
+ #### 仕様変更
8
+ - httpでダウンロードしたとしても目次アドレスをhttpsに強制切り替えを行います
9
+ (SSL対応サイトのみ)
10
+
11
+ #### 修正内容
12
+ - アドレスがhttpとhttpsの違いだけで、同じ小説を別の小説として扱われてしまう
13
+ - gem ライブラリのアップデートにより mail コマンドが動かなくなっていた
14
+ - ハーメルンのアドレス変更に対応
15
+ - 「DLボタン設置」ブックマークレットをhttpsアドレス下でも動くように修正
16
+ + ヘルプページからブックマークレットの再取得が必要です。古いものは動きません
17
+ + 最近のブラウザじゃないとたぶん動きません
18
+ - Arcadiaでカテゴリがない古い小説をダウンロード出来ない場合がある
19
+
20
+
5
21
  3.1.9: 2017/10/19
6
22
  ------------------
7
23
  #### 修正内容
data/README.md CHANGED
@@ -33,6 +33,22 @@ Narou.rb ― 「小説家になろう」「小説を読もう!」ダウンロ
33
33
  更新履歴 - ChangeLog
34
34
  --------------------
35
35
 
36
+ 3.1.10: 2017/11/20
37
+ ------------------
38
+ #### 仕様変更
39
+ - httpでダウンロードしたとしても目次アドレスをhttpsに強制切り替えを行います
40
+ (SSL対応サイトのみ)
41
+
42
+ #### 修正内容
43
+ - アドレスがhttpとhttpsの違いだけで、同じ小説を別の小説として扱われてしまう
44
+ - gem ライブラリのアップデートにより mail コマンドが動かなくなっていた
45
+ - ハーメルンのアドレス変更に対応
46
+ - 「DLボタン設置」ブックマークレットをhttpsアドレス下でも動くように修正
47
+ + ヘルプページからブックマークレットの再取得が必要です。古いものは動きません
48
+ + 最近のブラウザじゃないとたぶん動きません
49
+ - Arcadiaでカテゴリがない古い小説をダウンロード出来ない場合がある
50
+
51
+
36
52
  3.1.9: 2017/10/19
37
53
  ------------------
38
54
  #### 修正内容
@@ -53,7 +53,7 @@ module Command
53
53
  when :ncode
54
54
  true
55
55
  when :url
56
- !!@site_settings.find { |s| s.multi_match(target, "url") }
56
+ !!@site_settings.find { |s| s.multi_match_once(target, "url") }
57
57
  else
58
58
  false
59
59
  end
@@ -133,7 +133,7 @@ module Command
133
133
 
134
134
  def alter_database_add_column_last_mail_date
135
135
  database = Database.instance
136
- database.each do |_, data|
136
+ database.each_value do |data|
137
137
  data["last_mail_date"] ||= Time.now
138
138
  end
139
139
  database.save_database
@@ -94,7 +94,7 @@ module Command
94
94
  def self.get_tag_list(ids = nil)
95
95
  database = Database.instance
96
96
  tag_list = Hash.new(0)
97
- database.each do |_, data|
97
+ database.each_value do |data|
98
98
  if ids.kind_of?(Array)
99
99
  next unless ids.include?(data["id"])
100
100
  end
@@ -15,7 +15,7 @@ module Command
15
15
 
16
16
  def self.create_version_string
17
17
  postfix = (Narou.commit_version ? "" : " (develop)")
18
- "#{::Version}#{postfix}"
18
+ "#{Narou::VERSION}#{postfix}"
19
19
  end
20
20
  end
21
21
  end
@@ -6,42 +6,19 @@
6
6
  require "fileutils"
7
7
  require "singleton"
8
8
  require "yaml"
9
+ require "forwardable"
9
10
  require_relative "narou"
10
11
  require_relative "inventory"
11
12
 
12
13
  class Database
13
14
  include Singleton
15
+ include Enumerable
16
+ extend Forwardable
14
17
 
15
18
  ARCHIVE_ROOT_DIR_PATH = "小説データ/"
16
19
  DATABASE_NAME = "database"
17
20
 
18
- def [](key)
19
- @database[key]
20
- end
21
-
22
- def []=(key, value)
23
- @database[key] = value
24
- end
25
-
26
- def each(&block)
27
- if block
28
- @database.each(&block)
29
- else
30
- @database.each
31
- end
32
- end
33
-
34
- def each_key(&block)
35
- if block
36
- @database.each_key(&block)
37
- else
38
- @database.each_key
39
- end
40
- end
41
-
42
- def delete(key)
43
- @database.delete(key)
44
- end
21
+ def_delegators :@database, :[], :[]=, :each, :each_key, :each_value, :delete
45
22
 
46
23
  def initialize
47
24
  refresh
@@ -86,16 +63,19 @@ class Database
86
63
  end
87
64
 
88
65
  def get_data(type, value)
89
- @database.each do |_, data|
66
+ @database.each_value do |data|
90
67
  return data if data[type] == value
91
68
  end
92
69
  nil
93
70
  end
94
71
 
95
- def get_id(type, value)
96
- data = get_data(type, value)
97
- if data
98
- return data["id"]
72
+ # SiteSetting を使って toc url を正規化してマッチングする。
73
+ # get_data("toc_url", url) だと、アドレスが仕様変更した場合に、
74
+ # 古いままのデータとマッチングしなくなるため
75
+ def get_data_by_toc_url(toc_url, site_setting)
76
+ @database.each_value do |data|
77
+ site_setting.multi_match_once(data["toc_url"], "url") or next
78
+ return data if site_setting["toc_url"] == toc_url
99
79
  end
100
80
  nil
101
81
  end
@@ -68,7 +68,7 @@ class Downloader
68
68
  toc_url = get_toc_url(target)
69
69
  setting = nil
70
70
  if toc_url
71
- setting = @@settings.find { |s| s.multi_match(toc_url, "url") }
71
+ setting = @@settings.find { |s| s.multi_match_once(toc_url, "url") }
72
72
  end
73
73
  setting
74
74
  end
@@ -103,19 +103,7 @@ class Downloader
103
103
  # 指定されたIDとかから小説の保存ディレクトリを取得
104
104
  #
105
105
  def self.get_novel_data_dir_by_target(target)
106
- target = Narou.alias_to_id(target)
107
- type = get_target_type(target)
108
- data = nil
109
- case type
110
- when :url, :ncode
111
- toc_url = get_toc_url(target)
112
- data = @@database.get_data("toc_url", toc_url)
113
- when :other
114
- data = @@database.get_data("title", target)
115
- when :id
116
- data = @@database[target.to_i]
117
- end
118
- return nil unless data
106
+ data = get_data_by_target(target) or return nil
119
107
  id = data["id"]
120
108
  file_title = data["file_title"] || data["title"] # 互換性維持のための処理
121
109
  use_subdirectory = data["use_subdirectory"] || false
@@ -136,16 +124,34 @@ class Downloader
136
124
  # target のIDを取得
137
125
  #
138
126
  def self.get_id_by_target(target)
139
- toc_url = get_toc_url(target) or return nil
140
- @@database.get_id("toc_url", toc_url)
127
+ data = get_data_by_target(target)
128
+ data && data["id"]
141
129
  end
142
130
 
143
131
  #
144
132
  # target からデータベースのデータを取得
145
133
  #
146
134
  def self.get_data_by_target(target)
147
- toc_url = get_toc_url(target) or return nil
148
- @@database.get_data("toc_url", toc_url)
135
+ target = Narou.alias_to_id(target)
136
+ case get_target_type(target)
137
+ when :url
138
+ setting = @@settings.find { |s| s.multi_match_once(target, "url") }
139
+ if setting
140
+ toc_url = setting["toc_url"]
141
+ return @@database.get_data_by_toc_url(toc_url, setting)
142
+ end
143
+ when :ncode
144
+ @@database.each_value do |data|
145
+ return data if data["toc_url"] =~ %r!#{target}/$!
146
+ end
147
+ when :id
148
+ data = @@database[target.to_i]
149
+ return data if data
150
+ when :other
151
+ data = @@database.get_data("title", target)
152
+ return data if data
153
+ end
154
+ nil
149
155
  end
150
156
 
151
157
  #
@@ -164,10 +170,10 @@ class Downloader
164
170
  target = Narou.alias_to_id(target)
165
171
  case get_target_type(target)
166
172
  when :url
167
- setting = @@settings.find { |s| s.multi_match(target, "url") }
173
+ setting = @@settings.find { |s| s.multi_match_once(target, "url") }
168
174
  return setting["toc_url"] if setting
169
175
  when :ncode
170
- @@database.each do |_, data|
176
+ @@database.each_value do |data|
171
177
  if data["toc_url"] =~ %r!#{target}/$!
172
178
  return data["toc_url"]
173
179
  end
@@ -222,7 +228,7 @@ class Downloader
222
228
  load_paths = [
223
229
  File.join(Narou.get_script_dir, NOVEL_SITE_SETTING_DIR, "*.yaml"),
224
230
  File.join(Narou.get_root_dir, NOVEL_SITE_SETTING_DIR, "*.yaml")
225
- ].join("\0")
231
+ ].uniq.join("\0")
226
232
  Dir.glob(load_paths) do |path|
227
233
  setting = SiteSetting.load_file(path)
228
234
  if setting["name"] == "小説家になろう"
@@ -48,6 +48,7 @@ class Mailer
48
48
  end
49
49
 
50
50
  def send(id, message, attached_file_path = nil)
51
+ gem "mail", "2.6.6"
51
52
  require "pony"
52
53
  @error_message = ""
53
54
  params = @options.dup
@@ -541,7 +541,7 @@ class NovelConverter
541
541
  # 目次情報からサイト設定を取得
542
542
  #
543
543
  def find_site_setting(toc_url)
544
- @@site_settings.find { |s| s.multi_match(toc_url, "url") }
544
+ @@site_settings.find { |s| s.multi_match_once(toc_url, "url") }
545
545
  end
546
546
 
547
547
  #
@@ -50,6 +50,11 @@ class SiteSetting
50
50
  match_data
51
51
  end
52
52
 
53
+ def multi_match_once(source, *keys)
54
+ clear
55
+ multi_match(source, *keys)
56
+ end
57
+
53
58
  def update_match_values(match_data)
54
59
  match_data.names.each do |name|
55
60
  @match_values[name] = match_data[name] || ""
@@ -57,16 +62,25 @@ class SiteSetting
57
62
  end
58
63
 
59
64
  def is_container?(value)
60
- value.is_a?(Hash) || value.is_a?(Array) || value.is_a?(Narou::API)
65
+ value.is_a?(Hash) || value.is_a?(Narou::API)
61
66
  end
62
67
 
63
68
  def replace_group_values(key, option_values = {})
64
- dest = option_values[key] || @match_values[key] || @yaml_setting[key]
65
- return dest if is_container?(dest)
66
- return dest unless dest.respond_to?(:gsub!)
67
- result = dest.dup
69
+ buf = option_values[key] || @match_values[key] || @yaml_setting[key]
70
+ return buf if is_container?(buf)
71
+ if buf.is_a?(Array)
72
+ buf.map do |dest|
73
+ do_replace(dest, option_values)
74
+ end
75
+ else
76
+ do_replace(buf, option_values)
77
+ end
78
+ end
79
+
80
+ def do_replace(dest, option_values)
81
+ return dest unless dest.respond_to?(:gsub)
68
82
  values = @yaml_setting.merge(@match_values).merge(option_values)
69
- result.gsub!(/\\\\k<(.+?)>/) do |match|
83
+ dest.gsub(/\\\\k<(.+?)>/) do |match|
70
84
  value = values[$1]
71
85
  if value
72
86
  value.gsub(/\\\\k<(.+?)>/) do
@@ -76,6 +90,5 @@ class SiteSetting
76
90
  match
77
91
  end
78
92
  end
79
- result
80
93
  end
81
94
  end
@@ -3,4 +3,6 @@
3
3
  # Copyright 2013 whiteleaf. All rights reserved.
4
4
  #
5
5
 
6
- Version = "3.1.9"
6
+ module Narou
7
+ VERSION = "3.1.10"
8
+ end
@@ -235,7 +235,7 @@ class Narou::AppServer < Sinatra::Base
235
235
  end
236
236
 
237
237
  def puts_hello_messages
238
- puts "<white>Narou.rb version #{::Version}</white>".termcolor
238
+ puts "<white>Narou.rb version #{Narou::VERSION}</white>".termcolor
239
239
  end
240
240
 
241
241
  def start_device_ejectable_event
@@ -291,6 +291,7 @@ class Narou::AppServer < Sinatra::Base
291
291
  # ===================================================================
292
292
 
293
293
  before do
294
+ headers "Cache-Control" => "no-cache" if $development
294
295
  @bootstrap_theme = case params["theme"]
295
296
  when nil
296
297
  Narou.get_theme
@@ -597,7 +598,8 @@ class Narou::AppServer < Sinatra::Base
597
598
  end
598
599
 
599
600
  post "/api/download" do
600
- targets = params["targets"] or pass
601
+ headers "Access-Control-Allow-Origin" => "*"
602
+ targets = params["targets"] or error("need a parameter: `targets'")
601
603
  targets = targets.kind_of?(Array) ? targets : targets.split
602
604
  pass if targets.size == 0
603
605
  Narou::Worker.push do
@@ -777,7 +779,7 @@ class Narou::AppServer < Sinatra::Base
777
779
  ids.map!(&:to_i)
778
780
  database = Database.instance
779
781
  tag_info = {}
780
- database.each do |_, data|
782
+ database.each_value do |data|
781
783
  tags = data["tags"] || []
782
784
  tags.each do |tag|
783
785
  tag_info[tag] ||= {
@@ -874,7 +876,7 @@ class Narou::AppServer < Sinatra::Base
874
876
  end
875
877
 
876
878
  # ダウンロード登録すると同時にグレーのボタン画像を返す
877
- get "/api/download4ie" do
879
+ get "/api/download4ssl" do
878
880
  Narou::Worker.push do
879
881
  CommandLine.run!(%W(download #{params["target"]}))
880
882
  @@push_server.send_all(:"table.reload")
@@ -882,14 +884,29 @@ class Narou::AppServer < Sinatra::Base
882
884
  redirect "/resources/images/dl_button1.gif"
883
885
  end
884
886
 
887
+ # ダウンロード済みかどうかで表示が変わる画像
888
+ get "/api/downloadable.gif" do
889
+ target = params["target"]
890
+ # 0: 未ダウンロード, 1: ダウンロード済み, 2: ダウンロード出来ない
891
+ number =
892
+ if target
893
+ Downloader.get_id_by_target(target) ? 1 : 0
894
+ else
895
+ 2
896
+ end
897
+ redirect "/resources/images/dl_button#{number}.gif"
898
+ end
899
+
885
900
  get "/api/validate_url_regexp_list" do
886
901
  json Downloader.load_settings.map { |setting|
887
- "(#{setting["url"].gsub(/\?<.+?>/, "?:").gsub("\\", "\\\\")})"
888
- }
902
+ Array(setting["url"]).map do |url|
903
+ "(#{url.gsub(/\?<.+?>/, "?:").gsub("\\", "\\\\")})"
904
+ end
905
+ }.flatten
889
906
  end
890
907
 
891
908
  get "/api/version/current.json" do
892
- json({ version: ::Version })
909
+ json({ version: Narou::VERSION })
893
910
  end
894
911
 
895
912
  get "/api/version/latest.json" do
@@ -1,72 +1,26 @@
1
1
  <%# vim: set ft=javascript : -%>
2
- (function() {
3
- // オフライン表記を先に消しておく
4
- var offline = document.getElementById("narourb-offline");
5
- offline.parentNode.removeChild(offline);
6
-
7
- // 対応小説投稿サイトに関する情報
8
- var site_settings = {
2
+ var insertButtonBookmarklet = (function() {
3
+ "DLボタン設置ブックマークレット v2.0";
4
+ var site_settings = [
9
5
  <%- Downloader.load_settings.each.with_index do |setting, i| -%>
10
- <%- next if setting["top_url"] == "http://novel.syosetu.org" -%>
11
- "<%= setting["domain"] %>": {
6
+ <% setting.clear %>
7
+ {
12
8
  <%- case setting["domain"] -%>
13
9
  <%- when "www.mai-net.net" -%>
14
10
  add_tail: "&n=0&count=1",
15
- <%- when "ncode.syosetu.com", "novel18.syosetu.com", "novel.syosetu.org" -%>
11
+ <%- when "ncode.syosetu.com", "novel18.syosetu.com", "syosetu.org" -%>
16
12
  add_tail: "/",
17
13
  <%- when "www.akatsuki-novels.com" -%>
18
14
  add_tail: "",
19
15
  <%- end -%>
20
- url: new RegExp('(<%= setting["url"].gsub(/\?<.+?>/, "?:").gsub("\\", "\\\\\\\\") %>)')
21
- }
22
- <%= i == Downloader.load_settings.length - 1 ? "" : "," %>
23
- <%- end -%>
24
- };
25
-
26
- // 管理している小説のURL一覧
27
- var manage_novel_urls = [
28
- <%-# バイナリーサーチ用にソートしておく -%>
29
- <%- Database.instance.get_object.values.sort_by { |v| v["toc_url"] }.each do |data| -%>
30
- '<%= data["toc_url"] %>',
16
+ url: [<%= Array(setting["url"]).map do |url|
17
+ %!new RegExp("^(#{url.gsub(/\?<.+?>/, "?:").gsub("\\", "\\\\\\\\")})")!
18
+ end.join(",") -%>]
19
+ }<%= i == Downloader.load_settings.length - 1 ? "" : "," %>
31
20
  <%- end -%>
32
21
  ];
33
22
 
34
- /*
35
- * バイナリーサーチ
36
- * 見つかったら見つかった位置のインデックス
37
- * 見つからなかったら-1を返す
38
- * array はソート済みである必要がある
39
- */
40
- var binarySearch = function(array, target) {
41
- if (array.length === 0) return -1;
42
- var left = 0, right = manage_novel_urls.length - 1;
43
- while (left < right) {
44
- var center = (left + right) / 2 | 0;
45
- if (array[center] < target)
46
- left = center + 1;
47
- else if (array[center] > target)
48
- right = center - 1;
49
- else
50
- return center;
51
- }
52
- if (array[left] === target) return left;
53
- return -1;
54
- };
55
-
56
- /*
57
- * 管理している小説のURLリストから検索
58
- */
59
- var searchRegisterURL = function(target) {
60
- var result = binarySearch(manage_novel_urls, target);
61
- if (result === -1)
62
- return null;
63
- return manage_novel_urls[result];
64
- };
65
-
66
- /*
67
- * IE10未満のために自力でフォームエンコード
68
- */
69
- var encodeHTMLForm = function(data) {
23
+ function encodeHTMLForm(data) {
70
24
  var params = [];
71
25
  for (var name in data) {
72
26
  var value = data[name];
@@ -74,11 +28,11 @@
74
28
  params.push(param);
75
29
  }
76
30
  return params.join("&").replace(/%20/g, "+");
77
- };
31
+ }
78
32
 
79
33
  var server_origin = '<%= "#{request.scheme}://#{env["SERVER_NAME"]}:#{env["SERVER_PORT"]}" %>';
80
34
 
81
- var createButtonElement = function(href) {
35
+ function createButtonElement(href) {
82
36
  var span = document.createElement("span");
83
37
  var img = document.createElement("img");
84
38
  var space = span.cloneNode();
@@ -89,45 +43,38 @@
89
43
  space.textContent = " ";
90
44
 
91
45
  var dl_listener = function(e) {
92
- var url = server_origin + "/api/download";
93
- try {
94
- var xhr = new XMLHttpRequest;
95
- xhr.open("POST", url);
96
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
97
- xhr.send(encodeHTMLForm({ targets: href }));
98
- img.src = server_origin + "/resources/images/dl_button1.gif";
99
- }
100
- catch(e) {
101
- // IE7モード(なろうのトップページをIEで見た場合)の時は xhr.open の時点で
102
- // 例外が発生してWEBUIサーバまでデータが飛ばないので、画像のURLにパラメータ
103
- // 仕込んでDLの通知を行う
104
- img.src = server_origin + "/api/download4ie?target=" + encodeURIComponent(href);
105
- }
106
- // 登録したらもう押せないようにイベントを削除
46
+ img.src = server_origin + "/api/download4ssl?target=" + encodeURIComponent(href);
107
47
  img.onclick = null;
108
48
  img.style.cursor = "default";
109
49
  return false;
110
50
  };
111
51
 
112
- if (searchRegisterURL(href)) {
113
- // すでにダンロード済みなら最初からグレー画像
114
- img.src = server_origin + "/resources/images/dl_button1.gif";
115
- img.style.cursor = "default";
116
- }
117
- else {
118
- img.src = server_origin + "/resources/images/dl_button0.gif";
119
- img.onclick = dl_listener;
120
- }
52
+ img.src = server_origin + "/api/downloadable.gif?target=" + encodeURIComponent(href);
53
+ img.onclick = dl_listener;
121
54
  return span;
122
55
  };
123
56
 
57
+ function matchLink(link, setting) {
58
+ var matched = false;
59
+ for (var x in setting.url) {
60
+ var url = setting.url[x];
61
+ if (link.href && link.href.toLowerCase().match(url)) {
62
+ var download_button = createButtonElement(RegExp.$1 + setting.add_tail);
63
+ link.parentNode.insertBefore(download_button, link);
64
+ matched = true;
65
+ break;
66
+ }
67
+ }
68
+ return matched;
69
+ }
70
+
124
71
  var links = document.getElementsByTagName("a");
125
- for (var i = 0; i < links.length; i++) {
72
+
73
+ for (var i in links) {
126
74
  var link = links[i];
127
- var setting = site_settings[link.hostname];
128
- if (setting && link.href.toLowerCase().match(setting.url)) {
129
- var download_button = createButtonElement(RegExp.$1 + setting.add_tail);
130
- link.parentNode.insertBefore(download_button, link);
75
+ for (var y in site_settings) {
76
+ var setting = site_settings[y];
77
+ if (matchLink(link, setting)) break;
131
78
  }
132
79
  }
133
- })();
80
+ });