bibi-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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