narou 1.7.2 → 2.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 (100) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +1 -0
  3. data/ChangeLog.md +35 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE.txt +100 -0
  6. data/README.md +28 -39
  7. data/lib/color.rb +0 -2
  8. data/lib/command.rb +1 -0
  9. data/lib/command/convert.rb +33 -4
  10. data/lib/command/diff.rb +5 -4
  11. data/lib/command/download.rb +9 -1
  12. data/lib/command/flag.rb +2 -2
  13. data/lib/command/list.rb +1 -1
  14. data/lib/command/mail.rb +3 -3
  15. data/lib/command/remove.rb +2 -1
  16. data/lib/command/send.rb +7 -6
  17. data/lib/command/setting.rb +39 -95
  18. data/lib/command/tag.rb +25 -13
  19. data/lib/command/update.rb +6 -1
  20. data/lib/command/version.rb +5 -1
  21. data/lib/command/web.rb +111 -0
  22. data/lib/commandbase.rb +5 -2
  23. data/lib/commandline.rb +16 -0
  24. data/lib/converterbase.rb +20 -14
  25. data/lib/device.rb +5 -4
  26. data/lib/downloader.rb +68 -39
  27. data/lib/eventable.rb +72 -0
  28. data/lib/helper.rb +105 -37
  29. data/lib/ini.rb +2 -1
  30. data/lib/input.rb +68 -0
  31. data/lib/inventory.rb +4 -0
  32. data/lib/kindlestrip.rb +2 -2
  33. data/lib/logger.rb +41 -19
  34. data/lib/narou.rb +10 -0
  35. data/lib/narou/api.rb +1 -1
  36. data/lib/novelconverter.rb +8 -21
  37. data/lib/novelsetting.rb +79 -4
  38. data/lib/version.rb +1 -1
  39. data/lib/web/all.rb +12 -0
  40. data/lib/web/appserver.rb +612 -0
  41. data/lib/web/helper4web.rb +15 -0
  42. data/lib/web/progressbar4web.rb +32 -0
  43. data/lib/web/public/favicon.ico +0 -0
  44. data/lib/web/public/resources/bootbox.min.js +6 -0
  45. data/lib/web/public/resources/common.ui.js +143 -0
  46. data/lib/web/public/resources/dataTables.colVis.js +1113 -0
  47. data/lib/web/public/resources/help/rect_select.png +0 -0
  48. data/lib/web/public/resources/help/ssmain.png +0 -0
  49. data/lib/web/public/resources/help/tag.png +0 -0
  50. data/lib/web/public/resources/jquery.moveto.js +44 -0
  51. data/lib/web/public/resources/jquery.outerclick.js +60 -0
  52. data/lib/web/public/resources/jquery.slidenavbar.js +89 -0
  53. data/lib/web/public/resources/narou.library.js +815 -0
  54. data/lib/web/public/resources/narou.ui.js +993 -0
  55. data/lib/web/public/resources/perfect-scrollbar.min.css +5 -0
  56. data/lib/web/public/resources/perfect-scrollbar.min.js +4 -0
  57. data/lib/web/public/resources/shortcut.js +223 -0
  58. data/lib/web/public/resources/sort_asc.png +0 -0
  59. data/lib/web/public/resources/sort_desc.png +0 -0
  60. data/lib/web/public/resources/toggle-switch.css +322 -0
  61. data/lib/web/public/robots.txt +3 -0
  62. data/lib/web/public/test/jquery.outerclick.html +72 -0
  63. data/lib/web/pushserver.rb +110 -0
  64. data/lib/web/settingmessages.rb +14 -0
  65. data/lib/web/streaminginput.rb +103 -0
  66. data/lib/web/streaminglogger.rb +52 -0
  67. data/lib/web/views/about.haml +11 -0
  68. data/lib/web/views/help.haml +105 -0
  69. data/lib/web/views/index.haml +245 -0
  70. data/lib/web/views/js/widget.erb +74 -0
  71. data/lib/web/views/layout.haml +49 -0
  72. data/lib/web/views/novels/setting.haml +177 -0
  73. data/lib/web/views/settings.haml +115 -0
  74. data/lib/web/views/style.scss +737 -0
  75. data/lib/web/views/widget.haml +39 -0
  76. data/lib/web/web-socket-ruby/.gitignore +1 -0
  77. data/lib/web/web-socket-ruby/README.txt +75 -0
  78. data/lib/web/web-socket-ruby/lib/web_socket.rb +601 -0
  79. data/lib/web/web-socket-ruby/samples/chat_server.rb +58 -0
  80. data/lib/web/web-socket-ruby/samples/echo_server.rb +33 -0
  81. data/lib/web/web-socket-ruby/samples/stdio_client.rb +25 -0
  82. data/lib/web/worker.rb +87 -0
  83. data/narou.gemspec +36 -3
  84. data/narou.rb +8 -6
  85. data/preset/ncode.syosetu.com/n8725k/converter.rb +2 -1
  86. data/spec/data/convert_test/replace/correct_test_replace.txt +1 -1
  87. data/spec/data/convert_test/replace/test_replace.txt +1 -1
  88. data/spec/data/convert_test/ruby/correct_test_ruby.txt +18 -1
  89. data/spec/data/convert_test/ruby/test_ruby.txt +18 -0
  90. data/spec/downloader_spec.rb +37 -0
  91. data/spec/eventable_spec.rb +172 -0
  92. data/spec/exit_code_spec.rb +67 -0
  93. data/spec/helper_spec.rb +72 -0
  94. data/spec/input_spec.rb +76 -0
  95. data/spec/logger_spec.rb +53 -0
  96. data/spec/novelsetting_spec.rb +35 -0
  97. data/spec/worker_spec.rb +56 -0
  98. data/template/ibunko_novel.txt.erb +2 -2
  99. data/template/novel.txt.erb +2 -2
  100. metadata +213 -29
@@ -0,0 +1,3 @@
1
+ User-agent: *
2
+ Disallow: /
3
+
@@ -0,0 +1,72 @@
1
+ <!DOCTYPE html>
2
+ <html lang="ja">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <meta name="author" content="whiteleaf">
8
+ <meta name="robots" content="none">
9
+
10
+ <title>test jquery.outerclick.js</title>
11
+
12
+ <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
13
+ <!--[if lt IE 9]>
14
+ <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
15
+ <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
16
+ <![endif]-->
17
+
18
+ <style>
19
+ #container {
20
+ margin: 0 auto;
21
+ margin-top: 50px;
22
+ }
23
+ #menu {
24
+ border: 1px solid black;
25
+ background-color: orange;
26
+ font-size: 2em;
27
+ width: 300px;
28
+ height: 200px;
29
+ }
30
+ #menu2 {
31
+ border: 1px solid black;
32
+ background-color: pink;
33
+ font-size: 1.5em;
34
+ width: 300px;
35
+ height: 200px;
36
+ margin-top: 40px;
37
+ }
38
+ </style>
39
+ </head>
40
+ <body>
41
+
42
+ <div id="container">
43
+ <div id="menu">
44
+ このメニューの外側をクリックするとイベント発生
45
+ </div>
46
+
47
+ <div id="menu2">
48
+ <div class="item">
49
+ 要素を内包したメニューの外側をクリックするとイベント発生
50
+ </div>
51
+ <div class="item">
52
+ アイテム2
53
+ </div>
54
+ <div class="item">
55
+ アイテム3
56
+ </div>
57
+ </div>
58
+ </div>
59
+
60
+ <script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
61
+ <script src="/resources/jquery.outerclick.js"></script>
62
+
63
+ <script type="text/javascript">
64
+ $(document).ready(function() {
65
+ $("#menu, #menu2").outerClick(function() {
66
+ console.log($(this).attr("id") + "の外側がクリックされました")
67
+ });
68
+ });
69
+ </script>
70
+ </body>
71
+ </html>
72
+
@@ -0,0 +1,110 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2013 whiteleaf. All rights reserved.
4
+ #
5
+
6
+ require "json"
7
+ require_relative "web-socket-ruby/lib/web_socket"
8
+ require_relative "../eventable"
9
+
10
+ module Narou
11
+ class PushServer
12
+ include Singleton
13
+ include Eventable
14
+
15
+ HISTORY_SAVED_COUNT = 30 # 保存する履歴の数
16
+
17
+ attr_accessor :port, :host
18
+ attr_reader :accepted_domains, :connections
19
+
20
+ def accepted_domains=(domains)
21
+ @accepted_domains = domains.kind_of?(Array) ? domains : [domains]
22
+ end
23
+
24
+ def initialize
25
+ @accepted_domains = ["*"]
26
+ @port = 31000
27
+ @connections = []
28
+ clear_history
29
+ end
30
+
31
+ def run
32
+ @server = WebSocketServer.new({
33
+ accepted_domains: @accepted_domains,
34
+ port: @port,
35
+ host: @host
36
+ })
37
+ Thread.new do
38
+ @server.run do |ws|
39
+ begin
40
+ ws.handshake
41
+ que = Queue.new
42
+ @connections.push(que)
43
+
44
+ @history.compact.each do |message|
45
+ ws.send(JSON.generate(echo: message))
46
+ end
47
+
48
+ thread = Thread.new do
49
+ while true
50
+ data = que.pop
51
+ ws.send(data)
52
+ end
53
+ end
54
+
55
+ while data = ws.receive
56
+ begin
57
+ JSON.parse(data).each do |name, value|
58
+ trigger(name, value, ws)
59
+ end
60
+ rescue JSON::ParserError => e
61
+ ws.send(JSON.generate(echo: e.message))
62
+ end
63
+ end
64
+ rescue Errno::ECONNRESET => e
65
+ ensure
66
+ @connections.delete(que)
67
+ thread.terminate if thread
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ #
74
+ # PushServer を停止させる
75
+ #
76
+ def quit
77
+ @server.quit
78
+ end
79
+
80
+ def clear_history
81
+ @history = [nil] * HISTORY_SAVED_COUNT
82
+ # Sinatra で get "/" { clear_history } とかやった場合に [nil,nil...] な配列データが
83
+ # 渡されないようにするため(配列は Sinatra にとって特別なデータ)
84
+ true
85
+ end
86
+
87
+ #
88
+ # 接続している全てのクライアントに対してメッセージを送信
89
+ #
90
+ def send_all(data)
91
+ if data.kind_of?(Symbol)
92
+ # send_all(:"events.name") としてイベント名だけで送りたい場合の対応
93
+ data = { data => true }
94
+ end
95
+ json = JSON.generate(data)
96
+ @connections.each do |queue_of_connection|
97
+ queue_of_connection.push(json)
98
+ end
99
+ # echo 以外のイベントは履歴に保存しない
100
+ message = data[:echo]
101
+ if message
102
+ @history.push(message)
103
+ @history.shift
104
+ end
105
+ rescue JSON::GeneratorError => e
106
+ STDERR.puts $@.shift + ": #{e.message} (#{e.class})"
107
+ end
108
+ end
109
+ end
110
+
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2013 whiteleaf. All rights reserved.
4
+ #
5
+
6
+ module Narou
7
+ # WEB UI > 環境設定画面で表示する各項目の説明
8
+ # ここになければ元々の説明が表示される
9
+ SETTING_VARIABLES_WEBUI_MESSAGES = {
10
+ "device" => "変換、送信対象の端末(" + Device::DEVICES.keys.join(", ") + ")",
11
+ "difftool" => "Diffで使うツールのパスを指定する\n※WEB UIでは使われません"
12
+ }
13
+ end
14
+
@@ -0,0 +1,103 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2013 whiteleaf. All rights reserved.
4
+ #
5
+
6
+ require "thread"
7
+
8
+ module Narou
9
+ #
10
+ # 入力確認機能を WEB UI 用に差し替える
11
+ #
12
+ module Input
13
+ module_function
14
+
15
+ TIMEOUT_FOR_PONG = 2 # モーダルの生存確認を送って返答を待つ時間(s)
16
+
17
+ @@modal_id = 0
18
+ @@mutex = Mutex.new
19
+
20
+ def create_modal_id
21
+ id = nil
22
+ @@mutex.synchronize do
23
+ id = @@modal_id
24
+ @@modal_id += 1
25
+ end
26
+ id
27
+ end
28
+
29
+ #
30
+ # クライアント(ブラウザ)にユーザ入力用のモーダルを表示要求する
31
+ #
32
+ # 返事がなかった場合は nil を返す
33
+ #
34
+ def request_show_modal_for_client(modal_name, send_data)
35
+ pushserver = PushServer.instance
36
+ id = create_modal_id
37
+ que = Queue.new
38
+ ponged = true
39
+ pong_event_id = "pong.modal.#{id}"
40
+ answer_event_id = "answer.modal.#{id}"
41
+
42
+ answer_handler = ->(value, connection) do
43
+ if value.kind_of?(Hash)
44
+ que.push(value["result"])
45
+ else
46
+ que.push(nil)
47
+ end
48
+ end
49
+ pong_handler = ->(value, connection) do
50
+ ponged = true
51
+ end
52
+
53
+ pushserver.on(pong_event_id, &pong_handler)
54
+ pushserver.on(answer_event_id, &answer_handler)
55
+
56
+ th = Thread.new do
57
+ while ponged
58
+ ponged = false
59
+ # クライアントにpingを飛ばしてモーダルの生存確認をする
60
+ pushserver.send_all("ping.modal" => { id: id })
61
+ # クライアントからの受信確認を待つ
62
+ sleep TIMEOUT_FOR_PONG
63
+ end
64
+ # 応答なし
65
+ que.push(nil)
66
+ end
67
+
68
+ send_data[:id] = id
69
+ pushserver.send_all(modal_name => send_data)
70
+
71
+ result = que.pop
72
+ th.kill
73
+
74
+ pushserver.off(pong_event_id, &pong_handler)
75
+ pushserver.off(answer_event_id, &answer_handler)
76
+ pushserver.send_all("hide.modal" => { id: id })
77
+
78
+ result
79
+ end
80
+
81
+ def confirm(message, default = false, nontty_default = true)
82
+ result = request_show_modal_for_client("modal.confirm", message: message + "?")
83
+ if result.nil?
84
+ default
85
+ else
86
+ result
87
+ end
88
+ end
89
+
90
+ def choose(title, message, choices)
91
+ result = request_show_modal_for_client("modal.choose", {
92
+ title: title, message: message,
93
+ choices: choices.dup.tap { |h| h.delete(:default) }
94
+ })
95
+ if choices.include?(result)
96
+ result
97
+ else
98
+ choices[:default] || choices.first[0]
99
+ end
100
+ end
101
+ end
102
+ end
103
+
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2013 whiteleaf. All rights reserved.
4
+ #
5
+
6
+ class String
7
+ if $disable_color
8
+ def termcolor
9
+ TermColorLight.strip_tag(self, false)
10
+ end
11
+ else
12
+ require "termcolorlight/html"
13
+
14
+ def termcolor
15
+ TermColorLight.to_html(self)
16
+ end
17
+ end
18
+ end
19
+
20
+ #
21
+ # 標準出力をフックする
22
+ #
23
+ # $stdout を介した出力は echo イベントとして全てのクライアントへ送信される
24
+ #
25
+ class Narou::StreamingLogger < StringIO
26
+ include Narou::LoggerModule
27
+
28
+ def initialize(push_server = nil)
29
+ super()
30
+ @push_server = push_server
31
+ end
32
+
33
+ def tty?
34
+ false
35
+ end
36
+
37
+ def push_streaming(str)
38
+ unless @is_silent
39
+ @push_server.send_all(echo: str) if @push_server
40
+ end
41
+ end
42
+
43
+ def write(str)
44
+ str = str.to_s
45
+ if str.encoding == Encoding::ASCII_8BIT
46
+ str.force_encoding(Encoding::UTF_8)
47
+ end
48
+ super(str)
49
+ push_streaming(str)
50
+ end
51
+ end
52
+
@@ -0,0 +1,11 @@
1
+ %div(style="text-align:center")
2
+ %h1
3
+ %strong Narou.rb
4
+ %div
5
+ Version #{@narourb_version}<br>
6
+ Copyright 2013 whiteleaf. All rights reserved.
7
+ .well.well-sm(style="font-size:80%")
8
+ #{@ruby_version}<br>
9
+ #{env["HTTP_USER_AGENT"]}
10
+
11
+
@@ -0,0 +1,105 @@
1
+ :javascript
2
+ var local_initialize_function = function($) {
3
+ $("[data-toggle=tooltip]").tooltip({
4
+ animation: false,
5
+ container: "body",
6
+ });
7
+
8
+ var bookmarklet = function(d,e,u) {
9
+ u='#{request.scheme}://#{env["SERVER_NAME"]}:#{env["SERVER_PORT"]}'+
10
+ '/js/widget.js?mode=download&t='+Date.now();
11
+ e=d.createElement('script');
12
+ e.charset='utf-8';
13
+ e.src=u;
14
+ d.body.appendChild(e);
15
+ };
16
+
17
+ function createBookmarkletStrings(proc) {
18
+ return ("javascript:(" + proc + ")(document)").replace(/ {2,}|\n/g, "");
19
+ }
20
+
21
+ $("#bookmarklet").attr("href", createBookmarkletStrings(bookmarklet));
22
+ };
23
+
24
+ .navbar.navbar-default.navbar-fixed-top(role="navigation")
25
+ .container
26
+ .navbar-header
27
+ %button.navbar-toggle(type="button")
28
+ %span.sr-only Toggle navigation
29
+ %span.icon-bar
30
+ %span.icon-bar
31
+ %span.icon-bar
32
+ %a.navbar-brand(href="#" data-move-to="top") Narou.rb WEB UI
33
+ #bs-navbar-collapse-1.collapse.navbar-collapse
34
+ %ul.nav.navbar-nav
35
+ %li
36
+ %a(href="/settings") 環境設定
37
+ %li.active
38
+ %a(href="/help") ヘルプ
39
+ %li
40
+ %a(href="/") 戻る
41
+ %p#queue-text.navbar-text.navbar-right(data-toggle="tooltip" title="キューに積まれた処理の数" data-placement="bottom")
42
+ %span.glyphicon.glyphicon-inbox
43
+ %span#queue 0
44
+ #help-container.container.theme-showcase(role="main")
45
+ %h2 ブックマークレット
46
+ %p 小説掲載サイトを表示したまま直接ダウンロード出来るブックマークレットです。<br> |
47
+ 下記のリンクをブックマークに登録して、ダウンロードしたい小説のページで実行して下さい。(WEB UI起動中に限ります)<br> |
48
+ ブックマークバーにドラッグ&ドロップしたり、右クリックからブックマークにいれると簡単です。 |
49
+ %p
50
+ %a#bookmarklet(onclick="return false")
51
+ %big
52
+ %u Narou.rbでダウンロード
53
+
54
+ %p
55
+ %small 基本的に小説ページ内にダウンロード中の表示が出ますが、IEを使っていてかつ小説家になろうの小説をダウンロードしようとした場合のみ、技術的制約から別ウィンドウが開きます。
56
+
57
+ %hr
58
+
59
+ %h2 画面の簡単な説明
60
+ %img#ss-main(src="/resources/help/ssmain.png" class="img-thumbnail")
61
+ %h4
62
+ タイトルロゴ
63
+ .badge.number 1
64
+ %div
65
+ %p クリックすることでページ上部に移動することができます
66
+
67
+ %h4
68
+ 操作ボタン
69
+ .badge.number 2
70
+ %div
71
+ %p 押すことで各種操作を行うことが出来ます。Freeze, Remove, Convert, Other ボタンはひとつ以上の小説を選択していないと押すことは出来ません。また、Update, Send ボタンは小説をひとつも選択してない場合は全小説が対象に、選択しているときは選択した小説が対象になります。
72
+ %p 各種操作は一旦キューに積まれ、順番に処理されます(Update 中に Convert を押しても、更新処理が終わるまでは変換はされない)。現在のキュー数は画面右上の<code>*1</code>で分かります。
73
+
74
+ %h4
75
+ 検索ボックス
76
+ .badge.number 3
77
+ %div
78
+ %p このボックスに入力することで、小説一覧から小説を絞り込む事ができます。小説一覧に見えている項目は全て検索対象で、日付等も対象になります。半角スペースで区切ることで、複数の単語で絞り込むことが出来ます。
79
+
80
+ %h4
81
+ 小説一覧テーブル
82
+ .badge.number 4
83
+ %div
84
+ %p 現在管理している小説の一覧が表示されます。クリックすると選択状態になり、各種操作の対象となります。
85
+ %p テーブル上部の項目名をクリックすると、その項目でソートすることが出来ます。また、項目名を左右にドラッグ&ドロップすることで、項目の順番を入れ替えることが出来ます。
86
+ %p 表示項目はカスタマイズすることが可能です。上部メニューの「表示>表示する項目を設定」から各種項目の表示・非表示を選択出来ます。
87
+ %p 1ページに表示する件数を調整する場合は<code>*2</code>で行うことが出来ます。
88
+ %p 上記の各種設定はブラウザに保存され、開き直した場合も同じ状態が復元されます。デフォルトの状態に戻す場合はメニューの「表示>表示設定を全てリセット」を実行します。
89
+
90
+ %h4 タグ
91
+ %div
92
+ %img#ss-tag(src="/resources/help/tag.png" class="img-thumbnail")
93
+ %p 小説にタグが設定されている場合、タグ欄に表示されます。そのタグをクリックすることで絞込ができるようになっています。タグを絞り込んだ状態で、さらに検索ボックスから検索することも可能です。
94
+ %p タグの絞込状態を解除するにはメニューのタグから解除ボタンを押すか、タグの右側にある小さな空白ラベルをクリックすることでも解除することが出来ます。
95
+
96
+ %h4 シングル選択モード
97
+ %div
98
+ %p デフォルトの選択方法で、小説一覧をクリックしてひとつずつ選択するモードです。
99
+
100
+ %h4 範囲選択モード
101
+ %div
102
+ %img#ss-rect-select(src="/resources/help/rect_select.png" class="img-thumbnail")
103
+ %p 一度に複数の小説を選択する場合に便利なモードです。始点をクリックしたあと終点をクリックして範囲を確定するか、始点から終点までをドラッグすることで範囲を決めることが出来ます。
104
+ %p 範囲が確定された際にメニューが表示されるので、選択や解除等を選択します。反転は現在の選択状態を逆転させます。
105
+