Module: Narou
- Extended by:
- Memoist, Mixin::Locker
- Defined in:
- lib/version.rb,
lib/input.rb,
lib/narou.rb,
lib/worker.rb,
lib/narou/api.rb,
lib/backtracer.rb,
lib/mixin/locker.rb,
lib/narou_logger.rb,
lib/web/pushserver.rb,
lib/web/web_worker.rb,
lib/mixin/output_error.rb,
lib/web/streaminginput.rb,
lib/web/settingmessages.rb,
lib/web/streaminglogger.rb,
lib/extensions/monkey_patches/pathname.rb
Overview
標準出力をフックする
$stdout を介した出力は echo イベントとして全てのクライアントへ送信される
Defined Under Namespace
Modules: Backtracer, Eventable, Input, LoggerModule, Mixin, MonkyPatches, ServerHelpers
Classes: API, AppServer, ConcurrencyConvertLogger, ConcurrencyDefaultLogger, Logger, LoggerError, NullIO, PushServer, StreamingLogger, WebWorker, Worker
Constant Summary
collapse
- LOCAL_SETTING_DIR_NAME =
".narou"
- GLOBAL_SETTING_DIR_NAME =
".narousetting"
- AOZORAEPUB3_JAR_NAME =
"AozoraEpub3.jar"
- AOZORAEPUB3_DIR =
"AozoraEpub3"
- PRESET_DIR =
"preset"
- MISC_DIR =
"misc"
- LOG_DIR =
"log"
- GLOBAL_REPLACE_NAME =
"replace.txt"
- EXIT_SUCCESS =
0
- EXIT_ERROR_CODE =
127
- EXIT_INTERRUPT =
126
- EXIT_REQUEST_REBOOT =
125
- MODIFIED_TAG =
"modified"
- LINE_HEIGHT_DEFAULT =
1.6
- UPDATE_SORT_KEYS =
{
"id" => "ID", "last_update" => "更新日", "title" => "タイトル", "author" => "作者名",
"new_arrivals_date" => "新着日", "general_lastup" => "最新話掲載日"
}
- VERSION =
"3.9.1"
- SETTING_VARIABLES_WEBUI_MESSAGES =
WEB UI > 環境設定画面で表示する各項目の説明 ここになければ元々の説明が表示される
{
"convert.multi-device" => "複数の端末用に同時に変換する。deviceよりも優先される。\nただのEPUBを出力したい場合はepubを指定",
"device" => "変換、送信対象の端末",
"difftool" => "%%ORIG%%。※WEB UIでは使われません",
"update.sort-by" => "アップデートを指定した項目順で行う",
"default.title_date_align" => "enable_add_date_to_title で付与する日付の位置",
"force.title_date_align" => "enable_add_date_to_title で付与する日付の位置",
"difftool.arg" => "difftoolで使う引数(指定しなければ単純に新旧ファイルを引数に呼び出す)\n" \
"特殊な変数\n" \
"<b>%NEW</b> : 最新データの差分用ファイルパス\n" \
"<b>%OLD</b> : 古い方の差分用ファイルパス",
"no-color" => "コンソールのカラー表示を無効にする\n※要サーバ再起動",
"economy" => "容量節約に関する設定",
"send.without-freeze" => "一括送信時に凍結された小説は対象外にする。(個別送信時は凍結済みでも送信可能)",
"server-digest-auth.enable" => "%%ORIG%%\n※digest-auth関連の設定を変更した場合サーバの再起動が必要",
"server-digest-auth.hashed-password" => "サーバのDigest認証のパスワードを、Realmを\"narou.rb\"としてハッシュにしたもの。\n" \
"https://tgws.plus/app/digest/ などで生成できる",
"concurrency" => "%%ORIG%% ※要サーバ再起動",
"logging" => "%%ORIG%%\n※要サーバ再起動",
"logging.format-filename" => "%%ORIG%%\n※要サーバ再起動",
"logging.format-timestamp" => "%%ORIG%%\n※要サーバ再起動",
}
- @@is_web =
false
Class Method Summary
collapse
lock, locked?, unlock
Class Method Details
.alias_to_id(target) ⇒ Object
target が alias だった場合はIDに変換する
全てのtarget照合系はこのメソッドを通過するので、ここで小文字にしてしまう
116
117
118
119
120
121
122
|
# File 'lib/narou.rb', line 116
def alias_to_id(target)
aliases = Inventory.load("alias")
if aliases[target]
return aliases[target]
end
target.is_a?(Numeric) ? target : target.downcase
end
|
.already_init? ⇒ Boolean
100
101
102
|
# File 'lib/narou.rb', line 100
def already_init?
root_dir.present?
end
|
.aozoraepub3_directory?(path) ⇒ Boolean
133
134
135
|
# File 'lib/narou.rb', line 133
def aozoraepub3_directory?(path)
create_aozoraepub3_jar_path(path).exist?
end
|
.aozoraepub3_path ⇒ Object
AozoraEpub3 の実行ファイル(.jar)のフルパス取得 検索順序
-
グローバルセッティング (global_setting aozoraepub3dir)
-
小説保存ディレクトリ(Narou.root_dir) 直下の AozoraEpub3
-
スクリプト保存ディレクトリ(Narou.script_dir) 直下の AozoraEpub3
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
# File 'lib/narou.rb', line 185
def aozoraepub3_path
global_setting_aozora_path = Inventory.load("global_setting", :global)["aozoraepub3dir"]
if global_setting_aozora_path
aozora_jar_path = create_aozoraepub3_jar_path(global_setting_aozora_path)
if aozora_jar_path.exist?
return aozora_jar_path
end
end
[Narou.root_dir, Narou.script_dir].each do |dir|
aozora_jar_path = create_aozoraepub3_jar_path(dir, AOZORAEPUB3_DIR)
return aozora_jar_path if aozora_jar_path.exist?
end
nil
end
|
.commit_version ⇒ Object
341
342
343
344
|
# File 'lib/narou.rb', line 341
def commit_version
cv_path = File.expand_path("commitversion", script_dir)
File.read(cv_path) if File.exist?(cv_path)
end
|
.concurrency_call(&block) ⇒ Object
同時実行が有効ならキューに積んで、無効なら普通に実行する
364
365
366
367
368
369
370
371
|
# File 'lib/narou.rb', line 364
def concurrency_call(&block)
if concurrency_enabled?
Worker.push(&block)
EXIT_SUCCESS
else
block.call
end
end
|
.concurrency_enabled? ⇒ Boolean
358
359
360
|
# File 'lib/narou.rb', line 358
def concurrency_enabled?
$stdout != $stdout2
end
|
.create_aozoraepub3_jar_path(*paths) ⇒ Object
129
130
131
|
# File 'lib/narou.rb', line 129
def create_aozoraepub3_jar_path(*paths)
Pathname(File.expand_path(File.join(*paths, AOZORAEPUB3_JAR_NAME)))
end
|
.create_novel_filename(novel_data, ext = "") ⇒ Object
書籍ファイル名を生成する convert.filename-to-ncode を設定している場合に novel_data に ncode、domain を 設定しない場合は id カラムが必須
rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
# File 'lib/narou.rb', line 208
def create_novel_filename(novel_data, ext = "")
filename_to_ncode = Inventory.load("local_setting")["convert.filename-to-ncode"]
novel_setting =
if novel_data["id"]
NovelSetting.load(novel_data["id"])
else
OpenStruct.new
end
if novel_setting.output_filename.present?
%!#{novel_setting.output_filename}#{ext}!
elsif filename_to_ncode
ncode = novel_data["ncode"]
domain = novel_data["domain"]
if !ncode || !domain
id = novel_data["id"]
unless id
raise ArgumentError, %!novel_data["id"] を設定して下さい!
end
site_setting = Downloader.get_sitesetting_by_target(id)
ncode = site_setting["ncode"]
domain = site_setting["domain"]
end
serialized_domain = domain.to_s.gsub(".", "_")
%!#{serialized_domain}_#{ncode}#{ext}!
else
author = Helper.replace_filename_special_chars(
novel_setting.novel_author.presence || novel_data["author"],
true
)
title = Helper.replace_filename_special_chars(
novel_setting.novel_title.presence || novel_data["title"],
true
)
filename = "[#{author}] #{title}#{ext}"
length_limit = Inventory.load["ebook-filename-length-limit"]
length_limit ? Helper.truncate_path(filename, length_limit, extname: ext) : filename
end
end
|
.economy?(mode) ⇒ Boolean
319
320
321
322
|
# File 'lib/narou.rb', line 319
def economy?(mode)
eco_modes = Inventory.load("local_setting")["economy"].to_s.split(",").map(&:strip)
eco_modes.include?(mode)
end
|
.get_device(device_name = nil) ⇒ Object
279
280
281
282
283
284
285
|
# File 'lib/narou.rb', line 279
def get_device(device_name = nil)
device_name ||= Inventory.load("local_setting")["device"]
if device_name && Device.exists?(device_name)
return Device.create(device_name)
end
nil
end
|
.get_ebook_file_paths(target, ext) ⇒ Object
253
254
255
256
257
258
259
260
261
|
# File 'lib/narou.rb', line 253
def get_ebook_file_paths(target, ext)
data = Downloader.get_data_by_target(target)
return nil unless data
dir = Downloader.get_novel_data_dir_by_target(target)
fname = create_novel_filename(data, ext)
base = File.basename(fname, ext)
get_ebook_file_paths_from_components(dir, base, ext)
end
|
.get_ebook_file_paths_from_components(dir, base, ext) ⇒ Object
263
264
265
266
267
268
269
270
271
|
# File 'lib/narou.rb', line 263
def get_ebook_file_paths_from_components(dir, base, ext)
paths = [File.join(dir, "#{base}#{ext}")]
index = 2
while File.exist?(path = File.join(dir, "#{base}_#{index}#{ext}"))
paths.push(Pathname(path))
index += 1
end
paths
end
|
.get_mobi_paths(target) ⇒ Object
rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/PerceivedComplexity
249
250
251
|
# File 'lib/narou.rb', line 249
def get_mobi_paths(target)
get_ebook_file_paths(target, ".mobi")
end
|
.get_theme_dir(name = nil) ⇒ Object
307
308
309
|
# File 'lib/narou.rb', line 307
def get_theme_dir(name = nil)
Pathname(File.join([script_dir, "lib/web/public/theme", name].compact))
end
|
.global_replace_pattern ⇒ Object
169
170
171
|
# File 'lib/narou.rb', line 169
def global_replace_pattern
@@global_replace_pattern_pairs ||= load_global_replace_pattern
end
|
.global_setting_dir ⇒ Object
75
76
77
78
79
80
81
82
83
|
# File 'lib/narou.rb', line 75
def global_setting_dir
if root_dir
dir = root_dir.join(GLOBAL_SETTING_DIR_NAME)
return dir if dir.directory?
end
dir = Pathname(GLOBAL_SETTING_DIR_NAME).expand_path("~")
dir.mkdir unless dir.exist?
dir
end
|
.kindlegen_path ⇒ Object
347
348
349
350
|
# File 'lib/narou.rb', line 347
def kindlegen_path
postfix = Helper.os_windows? ? ".exe" : ""
aozoraepub3_path.dirname.join("kindlegen#{postfix}")
end
|
.last_commit_year ⇒ Object
46
47
48
|
# File 'lib/narou.rb', line 46
def last_commit_year
2024
end
|
.latest_version ⇒ Object
Narou.rb gem の最新バージョン番号を取得する
rubygems公式APIによる取得は、WindowsでのSSL証明書問題で取得出来ない 環境があるため、gemコマンド経由で取得する
334
335
336
337
338
339
|
# File 'lib/narou.rb', line 334
def latest_version
response = `gem search ^narou$`.split("\n")
if response.last =~ /\Anarou \(([0-9.]+).*?\)\z/
$1
end
end
|
.line_height(default: LINE_HEIGHT_DEFAULT) ⇒ Object
353
354
355
356
|
# File 'lib/narou.rb', line 353
def line_height(default: LINE_HEIGHT_DEFAULT)
global_setting = Inventory.load("global_setting", :global)
global_setting["line-height"] || default
end
|
.load_global_replace_pattern ⇒ Object
155
156
157
158
159
160
161
162
163
164
165
166
167
|
# File 'lib/narou.rb', line 155
def load_global_replace_pattern
path = root_dir.join(GLOBAL_REPLACE_NAME)
pairs =
if path.exist?
Helper::CacheLoader.memo(path) do |text|
parse_replace_txt(text)
end
else
[]
end
@@global_replace_pattern_pairs = pairs
pairs
end
|
.local_setting_dir ⇒ Object
.log_dir ⇒ Object
91
92
93
|
# File 'lib/narou.rb', line 91
def log_dir
root_dir&.join(LOG_DIR)
end
|
.misc_dir ⇒ Object
273
274
275
|
# File 'lib/narou.rb', line 273
def misc_dir
root_dir.join(MISC_DIR)
end
|
.novel_frozen?(target) ⇒ Boolean
.novel_type_text(type) ⇒ Object
324
325
326
|
# File 'lib/narou.rb', line 324
def novel_type_text(type)
type == 2 ? "短編" : "連載"
end
|
.parse_replace_txt(text) ⇒ Object
137
138
139
140
141
142
143
144
145
146
147
148
|
# File 'lib/narou.rb', line 137
def parse_replace_txt(text)
pattern = []
text.each_line do |line|
line.sub!(/[\r\n]+\z/, "")
next if line[0] == ";" pair = line.split("\t", 2)
if pair.length == 2 && pair[0]
pattern << pair
end
end
pattern
end
|
.preset_dir ⇒ Object
95
96
97
|
# File 'lib/narou.rb', line 95
def preset_dir
script_dir&.join(PRESET_DIR)
end
|
.root_dir ⇒ Object
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
# File 'lib/narou.rb', line 50
def root_dir
root = nil
path = Dir.pwd
drive_letter = ""
if Helper.os_windows?
path.encode!(Encoding::UTF_8)
path.gsub!(/^[a-z]:/i, "")
drive_letter = $&
end
while path != ""
if File.directory?("#{drive_letter}#{path}/#{LOCAL_SETTING_DIR_NAME}")
root = drive_letter + path
break
end
path.gsub!(%r!/[^/]*$!, "")
end
Pathname(root) if root
end
|
.save_global_replace_pattern ⇒ Object
173
174
175
176
|
# File 'lib/narou.rb', line 173
def save_global_replace_pattern
path = root_dir.join(GLOBAL_REPLACE_NAME)
write_replace_txt(path, @@global_replace_pattern_pairs)
end
|
.script_dir ⇒ Object
86
87
88
|
# File 'lib/narou.rb', line 86
def script_dir
Pathname(__dir__).join("..").expand_path
end
|
.theme ⇒ Object
303
304
305
|
# File 'lib/narou.rb', line 303
def theme
Inventory.load("local_setting")["webui.theme"]
end
|
.theme_names ⇒ Object
311
312
313
314
315
316
|
# File 'lib/narou.rb', line 311
def theme_names
Dir.glob(get_theme_dir("*")).map do |path|
name = File.basename(path)
name == "fonts" ? nil : name
end.compact
end
|
.update_sort_key_summaries(left_space = 28) ⇒ Object
295
296
297
298
299
300
301
|
# File 'lib/narou.rb', line 295
def update_sort_key_summaries(left_space = 28)
summaries = { "KEY" => " 対象" }.merge(UPDATE_SORT_KEYS)
key_max_width = summaries.keys.max_by(&:length).length
summaries.map do |(key, summary)|
"#{" " * left_space}| #{key.center(key_max_width)} | #{summary}"
end.join("\n")
end
|
.web=(bool) ⇒ Object
287
288
289
|
# File 'lib/narou.rb', line 287
def web=(bool)
@@is_web = bool
end
|
.web? ⇒ Boolean
291
292
293
|
# File 'lib/narou.rb', line 291
def web?
@@is_web
end
|
.write_replace_txt(path, pairs) ⇒ Object
150
151
152
153
|
# File 'lib/narou.rb', line 150
def write_replace_txt(path, pairs)
buffer = pairs.each_with_object("\t").map(&:join).join("\n")
File.write(path, buffer)
end
|