bibi-cli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ module Bibi
2
+ module CLI
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,153 @@
1
+ require "dry/configurable"
2
+ require "xdg"
3
+ require "tomlrb"
4
+ require "uri"
5
+ require "epub/parser"
6
+ require "archive/zip"
7
+ require "aws-sdk-s3"
8
+ require "digest/md5"
9
+ require "base64"
10
+ require "erb"
11
+
12
+ class Bibi::Publish
13
+ extend Dry::Configurable
14
+
15
+ DEFAULT_MEDIA_TYPE = "application/octet-stream"
16
+
17
+ setting(:bibi, nil) {|value| URI(value) if value}
18
+ setting(:bookshelf, nil) {|value| URI(value) if value}
19
+ setting :page, true
20
+ setting :head_end
21
+ setting :body_end
22
+ setting(:endpoint, nil) {|value| URI(value) if value}
23
+
24
+ def initialize(profile: :default, dry_run: false, **options)
25
+ @profile = profile
26
+ load_config
27
+ update_config options
28
+ @dry_run = dry_run
29
+
30
+ $stderr.puts <<EOS
31
+ bibi: #{self.bibi}
32
+ bookshelf: #{self.bookshelf}
33
+ page: #{page?}
34
+ head_end: #{self.head_end}
35
+ body_end: #{self.body_end}
36
+ endpoint: #{endpoint}
37
+ EOS
38
+ end
39
+
40
+ def run(epub, name)
41
+ @epub = EPUB::Parser.parse(epub)
42
+ @name = name
43
+
44
+ raise "bibi or bookshelf URI is required." if bibi.nil? && bookshelf.nil?
45
+ raise "bibi URI is required when generating HTML" if page? && bibi.nil?
46
+
47
+ if config[:endpoint]
48
+ # `force_path_style` required to upload to MinIO server
49
+ Aws.config.update endpoint: config[:endpoint], force_path_style: true
50
+ end
51
+
52
+ upload_contents
53
+ upload_html if page?
54
+ end
55
+
56
+ private
57
+
58
+ def config
59
+ self.class.config
60
+ end
61
+
62
+ [:bibi, :head_end, :body_end, :endpoint].each do |name|
63
+ define_method name do
64
+ config[name]
65
+ end
66
+ end
67
+
68
+ def bookshelf
69
+ return config.bookshelf if config.bookshelf
70
+ return unless config.bibi
71
+ config.bibi + "bibi-bookshelf"
72
+ end
73
+
74
+ def page?
75
+ config.page
76
+ end
77
+
78
+ def dry_run?
79
+ !! @dry_run
80
+ end
81
+
82
+ def load_config
83
+ XDG::Config.new.all.uniq.reverse_each do |config_path|
84
+ path = File.join(config_path, "bibi", "publish.toml")
85
+ next unless File.file? path
86
+ c = Tomlrb.load_file(path, symbolize_keys: true)
87
+ next unless c[@profile]
88
+ $stderr.puts "Config loaded from #{path}"
89
+ update_config(c[@profile])
90
+ end
91
+ end
92
+
93
+ def update_config(c)
94
+ %i[bibi bookshelf head_end body_end endpoint].each do |name|
95
+ config[name] = c[name] unless c[name].nil?
96
+ end
97
+ config[:page] = c[:page] unless c[:page].nil?
98
+ end
99
+
100
+ def upload_contents
101
+ types = Hash.new {|hash, key| hash[key] = DEFAULT_MEDIA_TYPE}
102
+ @epub.resources.each do |item|
103
+ types[item.entry_name] = item.media_type
104
+ end
105
+
106
+ unless bookshelf.scheme == "s3"
107
+ raise "Currently, only s3 scheme is supported for bookshelf."
108
+ end
109
+ bucket = Aws::S3::Resource.new.bucket(bookshelf.host)
110
+ bookshelf_path = bookshelf.path[1..]
111
+
112
+ Archive::Zip.open @epub.epub_file do |archive|
113
+ archive.each do |entry|
114
+ next unless entry.file?
115
+ path = entry.zip_path.force_encoding("UTF-8");
116
+ type = types[path]
117
+ key = [bookshelf_path, @name, path].join("/")
118
+ content = entry.file_data.read
119
+ upload_to_s3 bucket, key, content, type
120
+ end
121
+ end
122
+ end
123
+
124
+ def upload_html
125
+ erb = ERB.new(html_template)
126
+ head_end_fragment = File.read(head_end) if head_end
127
+ body_end_fragment = File.read(body_end) if body_end
128
+ content = erb.result_with_hash({name: @name, title: @epub.title, head_end: head_end_fragment, body_end: body_end_fragment})
129
+ unless bibi.scheme == "s3"
130
+ raise "Currently, only s3 scheme is supported for bookshelf."
131
+ end
132
+ bucket = Aws::S3::Resource.new.bucket(bibi.host)
133
+ bibi_path = bibi.path[1..]
134
+ key = [bibi_path, "#{@name}.html"].join("/")
135
+ upload_to_s3 bucket, key, content, "text/html"
136
+ end
137
+
138
+ def html_template
139
+ template_path = File.join(__dir__, "publish/bibi.html.erb")
140
+ File.read(template_path)
141
+ end
142
+
143
+ def upload_to_s3(bucket, key, content, type)
144
+ object = bucket.object(key)
145
+ etag = Digest::MD5.hexdigest(content)
146
+ if object.exists? && object.etag == "\"#{etag}\"" # seriously?
147
+ $stderr.puts "Skipping #{object.public_url}"
148
+ return
149
+ end
150
+ $stderr.puts "Uploading#{dry_run? ? " (dry run)" : ""} #{object.public_url}"
151
+ object.put(body: content, content_type: type) unless dry_run?
152
+ end
153
+ end
@@ -0,0 +1,50 @@
1
+ <!DOCTYPE html>
2
+ <% include ERB::Util %>
3
+
4
+
5
+
6
+ <html id="bibi">
7
+
8
+
9
+ <head>
10
+
11
+ <meta charset="utf-8" />
12
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
13
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
14
+
15
+ <title><%=h title %></title>
16
+
17
+ <!-- # Bibi | EPUB Reader on your website. : © Satoru Matsushima - https://bibi.epub.link or https://github.com/satorumurmur/bibi / Licensed under the MIT License - https://github.com/satorumurmur/bibi/blob/master/LICENSE -->
18
+
19
+ <!-- 「わたしのことは『ビビ』と呼んでください。『ビビ』はわたしの名前なんです」 —— エレクトラ・パブリケーヌ『ビビのみぎくるぶし』 -->
20
+ <!-- 「まあ! それじゃあやっぱり、『ビビ』はわたしの“名前”だったのですね?」 —— ソフィア・パインアイランド『ビビさんたちのこと』 -->
21
+ <!-- 「このあたりにビビさんという人がいると聞いて来たのですが、あなたですか?」 —— ビビ・ララルー『ポケットに眼鏡』 -->
22
+
23
+ <link id="bibi-style" rel="stylesheet" href="resources/styles/bibi.css" />
24
+ <link id="bibi-dress" rel="stylesheet" href="wardrobe/everyday/bibi.dress.css" />
25
+ <script id="bibi-script" src="resources/scripts/bibi.js"></script>
26
+ <script id="bibi-preset" src="presets/default.js" data-bibi-bookshelf=""></script>
27
+ <%= head_end %>
28
+
29
+ </head>
30
+
31
+
32
+ <body data-bibi-book="<%=h name %>">
33
+
34
+ <div id="bibi-info">
35
+ <h1><%=h title %></h1>
36
+ <ul>
37
+ <li><a href="https://bibi.epub.link">Bibi | EPUB Reader on your website. (Official Website / Japanese)</a></li>
38
+ <li><a href="https://github.com/satorumurmur/bibi">Bibi on GitHub (English)</a></li>
39
+ </ul>
40
+ </div>
41
+
42
+ <div id="bibi-book-data" data-bibi-book-mimetype="application/epub+zip" hidden="hidden">
43
+ </div>
44
+
45
+ <%= body_end %>
46
+
47
+ </body>
48
+
49
+
50
+ </html>
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError => error
6
+ abort error.message
7
+ end
8
+
9
+ require 'test/unit'
10
+
11
+ class Test::Unit::TestCase
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'helper'
2
+ require 'bibi/publish'
3
+
4
+ class TestBibiCLI < Test::Unit::TestCase
5
+
6
+ def test_version
7
+ version = Bibi::CLI.const_get('VERSION')
8
+
9
+ assert !version.empty?, 'should have a VERSION constant'
10
+ end
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,246 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bibi-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kitaiti Makoto
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: archive-zip
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk-s3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dry-cli
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dry-configurable
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: epub-parser
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: tomlrb
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: xdg
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: asciidoctor
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: bundler
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubygems-tasks
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: test-unit
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: yard
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ description: Command-line tools to work with Bibi, incliding bibi publish which uploads
196
+ EPUB files to S3 and make them readable via web using Bibi a EPUB reader application.
197
+ email: KitaitiMakoto@gmail.com
198
+ executables:
199
+ - bibi
200
+ extensions: []
201
+ extra_rdoc_files: []
202
+ files:
203
+ - ".document"
204
+ - ".gitignore"
205
+ - ".yardopts"
206
+ - COPYING.txt
207
+ - ChangeLog.adoc
208
+ - Gemfile
209
+ - README.adoc
210
+ - README.ja.adoc
211
+ - Rakefile
212
+ - bibi-cli.gemspec
213
+ - bin/bibi
214
+ - lib/bibi/cli/commands.rb
215
+ - lib/bibi/cli/commands/publish.rb
216
+ - lib/bibi/cli/version.rb
217
+ - lib/bibi/publish.rb
218
+ - lib/bibi/publish/bibi.html.erb
219
+ - test/helper.rb
220
+ - test/test_bibi-cli.rb
221
+ homepage: https://gitlab.com/KitaitiMakoto/bibi-cli
222
+ licenses:
223
+ - AGPL-3.0
224
+ metadata: {}
225
+ post_install_message:
226
+ rdoc_options: []
227
+ require_paths:
228
+ - lib
229
+ required_ruby_version: !ruby/object:Gem::Requirement
230
+ requirements:
231
+ - - ">="
232
+ - !ruby/object:Gem::Version
233
+ version: '0'
234
+ required_rubygems_version: !ruby/object:Gem::Requirement
235
+ requirements:
236
+ - - ">="
237
+ - !ruby/object:Gem::Version
238
+ version: '0'
239
+ requirements: []
240
+ rubygems_version: 3.1.2
241
+ signing_key:
242
+ specification_version: 4
243
+ summary: Command-line tools to work with Bibi
244
+ test_files:
245
+ - test/helper.rb
246
+ - test/test_bibi-cli.rb