diff --git a/lib/helper.rb b/lib/helper.rb index 0de6a9e7..511f7dc8 100644 --- a/lib/helper.rb +++ b/lib/helper.rb @@ -400,28 +400,34 @@ def numeric_length(len) # end # class AsyncCommand - def self.exec(command, sleep_time = 0.5, &block) + def self.exec(*command, &block) looper = nil _pid = nil - status, stdout, stderr = systemu(command) do |pid| - _pid = pid - looper = Thread.new(pid) do |pid| + require "open3" + stdout_str = +"" + stderr_str = +"" + status = nil + Open3.popen3(*command) do |_stdin, stdout, stderr, wait_thr| + _pid = wait_thr.pid + looper = Thread.new(_pid) do |pid| loop do block.call if block - sleep(sleep_time) + sleep(0.5) next unless Narou::Worker.canceled? next unless Narou::WebWorker.canceled? - Process.kill("KILL", pid) - Process.detach(pid) + Process.kill("KILL", pid) rescue nil + Process.detach(pid) rescue nil break end end - looper.join - looper = nil + t_out = Thread.new { stdout.set_encoding(Encoding::UTF_8, Encoding::UTF_8, invalid: :replace, undef: :replace); stdout_str = stdout.read } + t_err = Thread.new { stderr.set_encoding(Encoding::UTF_8, Encoding::UTF_8, invalid: :replace, undef: :replace); stderr_str = stderr.read } + t_out.join + t_err.join + status = wait_thr.value + looper&.kill rescue nil end - stdout.force_encoding(Encoding::UTF_8) - stderr.force_encoding(Encoding::UTF_8) - return [stdout, stderr, status] + return [stdout_str, stderr_str, status] rescue RuntimeError => e raise unless e.message.include?("interrupted") process_kill(_pid) @@ -430,7 +436,7 @@ def self.exec(command, sleep_time = 0.5, &block) process_kill(_pid) raise ensure - looper&.kill + looper&.kill rescue nil end def self.process_kill(pid) diff --git a/lib/novelconverter.rb b/lib/novelconverter.rb index 1c12a469..0d038f79 100644 --- a/lib/novelconverter.rb +++ b/lib/novelconverter.rb @@ -173,20 +173,47 @@ def self.txt_to_epub(filename, dst_dir: nil, device: nil, verbose: false, yokoga if Helper.os_cygwin? abs_srcpath = Helper.convert_to_windows_path(abs_srcpath) end - Dir.chdir(aozoraepub3_dir) - command = %!java #{java_encoding} -cp #{aozoraepub3_basename} AozoraEpub3 -enc UTF-8 -of #{device_option} ! + - %!#{cover_option} #{dst_option} #{ext_option} #{yokogaki_option} "#{abs_srcpath}"! - if Helper.os_windows? - command = "cmd /c #{command}".encode(Encoding::Windows_31J) - end + temp_txt_name = "__temp_narou__.txt" + temp_epub_name = "__temp_narou__.epub" + temp_txt_path = File.join(src_dir, temp_txt_name) + temp_epub_path = File.join(src_dir, temp_epub_name) + target_epub_basename = File.basename(abs_srcpath, ".txt") + (device&.name == "Kobo" ? device.ebook_file_ext : ".epub") + target_epub_path = dst_dir ? File.join(File.expand_path(dst_dir), target_epub_basename) : File.join(src_dir, target_epub_basename) + FileUtils.cp(abs_srcpath, temp_txt_path) + + java_cmd = File.exist?(File.join(aozoraepub3_dir, "jre", "bin", "java.exe")) ? File.join(aozoraepub3_dir, "jre", "bin", "java.exe") : "java" + command = [ + java_cmd, + "-Dfile.encoding=UTF-8", + "-Dsun.jnu.encoding=UTF-8", + "-Dstdout.encoding=UTF-8", + "-Dstderr.encoding=UTF-8", + "-Dsun.stdout.encoding=UTF-8", + "-Dsun.stderr.encoding=UTF-8", + "-cp", aozoraepub3_path.to_s, + "AozoraEpub3", + "-enc", "UTF-8", + "-of" + ] + command.concat(["-device", "kindle"]) if device&.name == "Kindle" + command.concat(["-ext", device.ebook_file_ext]) if device&.name == "Kobo" + command.concat(["-c", "0"]) if cover_filename + command << "-hor" if yokogaki + command << temp_txt_name + + Dir.chdir(src_dir) activate_dakuten_font_files if use_dakuten_font stream_io.print "AozoraEpub3でEPUBに変換しています" begin - res = Helper::AsyncCommand.exec(command) do + res = Helper::AsyncCommand.exec(*command) do stream_io.print "." end + if File.exist?(temp_epub_path) + FileUtils.mv(temp_epub_path, target_epub_path) + end ensure Dir.chdir(pwd) + FileUtils.rm_f(temp_txt_path) inactivate_dakuten_font_files if use_dakuten_font end diff --git a/webnovel/ncode.syosetu.com.yaml b/webnovel/ncode.syosetu.com.yaml index 970f166a..cc3a3a53 100644 --- a/webnovel/ncode.syosetu.com.yaml +++ b/webnovel/ncode.syosetu.com.yaml @@ -61,44 +61,39 @@ narou_api_url: https://api.syosetu.com/novelapi/api/ novel_info_url: \\k/novelview/infotop/ncode/\\k/ # タイトル -t:

(?.+?)</a></h1> +t: |- + <h1 class="p-infotop-title">\s*<a href=".+?">(?<title>.+?)</a>\s*</h1> # novel_type 小説種別 -nt: <span id="noveltype(?:.*?)">(?<novel_type>.+?)</span> +nt: <span class="p-infotop-type__type[^"]*">(?<novel_type>.+?)</span> novel_type_string: 連載中: 1 完結済: 3 短編: 2 # general_all_no 掲載話数 -ga: </span>全(?<general_all_no>\d+)エピソード +ga: 全(?<general_all_no>\d+)エピソード # story あらすじ -s: <td class="ex">(?<story>.+?)</td> +s: |- + <dt class="p-infotop-data__title">あらすじ</dt>\s*<dd class="p-infotop-data__value">(?<story>.+?)</dd> # general_firstup 初回掲載日 gf: |- - <th>掲載日</th> - <td>(?<general_firstup>.+?)</td> + <dt class="p-infotop-data__title">掲載日</dt>\s*<dd class="p-infotop-data__value">(?<general_firstup>.+?)</td>|<dt class="p-infotop-data__title">掲載日</dt>\s*<dd class="p-infotop-data__value">(?<general_firstup>.+?)</dd> # novelupdated_at 小説の更新時刻。連載小説だと書いてないので最終掲載日で代用 nu: |- - <th>(?:最終更新日|最新掲載日|最終掲載日)</th> - <td>(?: - )?(?<novelupdated_at>.+?)(?: - )?</td> + <dt class="p-infotop-data__title">(?:最終更新日|最新掲載日|最終掲載日)</dt>\s*<dd class="p-infotop-data__value">(?<novelupdated_at>.+?)</dd> # general_lastup 最終掲載日 gl: |- - <th>(?:最新掲載日|最終掲載日)</th> - <td>(?<general_lastup>.+?)</td> + <dt class="p-infotop-data__title">(?:最新掲載日|最終掲載日)</dt>\s*<dd class="p-infotop-data__value">(?<general_lastup>.+?)</dd> # writer 作者名 w: |- - <th>作者名</th> - <td>(?:<a href=".+?">)?(?<writer>.+?)(?:</a>)?.?</td> + <dt class="p-infotop-data__title">作者名</dt>\s*<dd class="p-infotop-data__value">\s*(?:<a href=".+?">)?(?<writer>.+?)(?:</a>)?\s*</dd> # length 文字数 l: |- - <th>文字数</th> - <td>(?<length>.+?)文字</td> + <dt class="p-infotop-data__title">文字数</dt>\s*<dd class="p-infotop-data__value">(?<length>.+?)文字</dd> diff --git a/webnovel/novel18.syosetu.com.yaml b/webnovel/novel18.syosetu.com.yaml index da1fb55e..3612b217 100644 --- a/webnovel/novel18.syosetu.com.yaml +++ b/webnovel/novel18.syosetu.com.yaml @@ -66,44 +66,39 @@ narou_api_url: https://api.syosetu.com/novel18api/api/ novel_info_url: \\k<top_url>/novelview/infotop/ncode/\\k<ncode>/ # タイトル -t: <h1><a href=".+?">(?<title>.+?)</a></h1> +t: |- + <h1 class="p-infotop-title">\s*<a href=".+?">(?<title>.+?)</a>\s*</h1> # novel_type 小説種別 -nt: <span id="noveltype(?:.*?)">(?<novel_type>.+?)</span> +nt: <span class="p-infotop-type__type[^"]*">(?<novel_type>.+?)</span> novel_type_string: 連載中: 1 完結済: 3 短編: 2 # general_all_no 掲載話数 -ga: </span>全(?<general_all_no>\d+)エピソード +ga: 全(?<general_all_no>\d+)エピソード # story あらすじ -s: <td class="ex">(?<story>.+?)</td> +s: |- + <dt class="p-infotop-data__title">あらすじ</dt>\s*<dd class="p-infotop-data__value">(?<story>.+?)</dd> # general_firstup 初回掲載日 gf: |- - <th>掲載日</th> - <td>(?<general_firstup>.+?)</td> + <dt class="p-infotop-data__title">掲載日</dt>\s*<dd class="p-infotop-data__value">(?<general_firstup>.+?)</dd> # novelupdated_at 小説の更新時刻。連載小説だと書いてないので最終掲載日で代用 nu: |- - <th>(?:最終更新日|最新掲載日|最終掲載日)</th> - <td>(?: - )?(?<novelupdated_at>.+?)(?: - )?</td> + <dt class="p-infotop-data__title">(?:最終更新日|最新掲載日|最終掲載日)</dt>\s*<dd class="p-infotop-data__value">(?<novelupdated_at>.+?)</dd> # general_lastup 最終掲載日 gl: |- - <th>(?:最新掲載日|最終掲載日)</th> - <td>(?<general_lastup>.+?)</td> + <dt class="p-infotop-data__title">(?:最新掲載日|最終掲載日)</dt>\s*<dd class="p-infotop-data__value">(?<general_lastup>.+?)</dd> # writer 作者名 w: |- - <th>作者名</th> - <td>(?:<a href=".+?">)?(?<writer>.+?)(?:</a>)?.?</td> + <dt class="p-infotop-data__title">作者名</dt>\s*<dd class="p-infotop-data__value">\s*(?:<a href=".+?">)?(?<writer>.+?)(?:</a>)?\s*</dd> # length 文字数 l: |- - <th>文字数</th> - <td>(?<length>.+?)文字</td> + <dt class="p-infotop-data__title">文字数</dt>\s*<dd class="p-infotop-data__value">(?<length>.+?)文字</dd>