class Bibi::Publish

Constants

DEFAULT_MEDIA_TYPE

Public Class Methods

new(profile: :default, dry_run: false, **options) click to toggle source
# File lib/bibi/publish.rb, line 24
  def initialize(profile: :default, dry_run: false, **options)
    @profile = profile
    load_config
    update_config options
    @dry_run = dry_run

    $stderr.puts <<EOS
bibi: #{self.bibi}
bookshelf: #{self.bookshelf}
page: #{page?}
head_end: #{self.head_end}
body_end: #{self.body_end}
endpoint: #{endpoint}
EOS
  end

Public Instance Methods

run(epub, name) click to toggle source
# File lib/bibi/publish.rb, line 40
def run(epub, name)
  @epub = EPUB::Parser.parse(epub)
  @name = name

  raise "bibi or bookshelf URI is required." if bibi.nil? && bookshelf.nil?
  raise "bibi URI is required when generating HTML" if page? && bibi.nil?

  if config[:endpoint]
    # `force_path_style` required to upload to MinIO server
    Aws.config.update endpoint: config[:endpoint], force_path_style: true
  end

  upload_contents
  upload_html if page?
end

Private Instance Methods

bookshelf() click to toggle source
# File lib/bibi/publish.rb, line 68
def bookshelf
  return config.bookshelf if config.bookshelf
  return unless config.bibi
  config.bibi + "bibi-bookshelf"
end
config() click to toggle source
# File lib/bibi/publish.rb, line 58
def config
  self.class.config
end
dry_run?() click to toggle source
# File lib/bibi/publish.rb, line 78
def dry_run?
  !! @dry_run
end
html_template() click to toggle source
# File lib/bibi/publish.rb, line 138
def html_template
  template_path = File.join(__dir__, "publish/bibi.html.erb")
  File.read(template_path)
end
load_config() click to toggle source
# File lib/bibi/publish.rb, line 82
def load_config
  XDG::Config.new.all.uniq.reverse_each do |config_path|
    path = File.join(config_path, "bibi", "publish.toml")
    next unless File.file? path
    c = Tomlrb.load_file(path, symbolize_keys: true)
    next unless c[@profile]
    $stderr.puts "Config loaded from #{path}"
    update_config(c[@profile])
  end
end
page?() click to toggle source
# File lib/bibi/publish.rb, line 74
def page?
  config.page
end
update_config(c) click to toggle source
# File lib/bibi/publish.rb, line 93
def update_config(c)
  %i[bibi bookshelf head_end body_end endpoint].each do |name|
    config[name] = c[name] unless c[name].nil?
  end
  config[:page] = c[:page] unless c[:page].nil?
end
upload_contents() click to toggle source
# File lib/bibi/publish.rb, line 100
def upload_contents
  types = Hash.new {|hash, key| hash[key] = DEFAULT_MEDIA_TYPE}
  @epub.resources.each do |item|
    types[item.entry_name] = item.media_type
  end

  unless bookshelf.scheme == "s3"
    raise "Currently, only s3 scheme is supported for bookshelf."
  end
  bucket = Aws::S3::Resource.new.bucket(bookshelf.host)
  bookshelf_path = bookshelf.path[1..]

  Archive::Zip.open @epub.epub_file do |archive|
    archive.each do |entry|
      next unless entry.file?
      path = entry.zip_path.force_encoding("UTF-8");
      type = types[path]
      key = [bookshelf_path, @name, path].join("/")
      content = entry.file_data.read
      upload_to_s3 bucket, key, content, type
    end
  end
end
upload_html() click to toggle source
# File lib/bibi/publish.rb, line 124
def upload_html
  erb = ERB.new(html_template)
  head_end_fragment = File.read(head_end) if head_end
  body_end_fragment = File.read(body_end) if body_end
  content = erb.result_with_hash({name: @name, title: @epub.title, head_end: head_end_fragment, body_end: body_end_fragment})
  unless bibi.scheme == "s3"
    raise "Currently, only s3 scheme is supported for bookshelf."
  end
  bucket = Aws::S3::Resource.new.bucket(bibi.host)
  bibi_path = bibi.path[1..]
  key = [bibi_path, "#{@name}.html"].join("/")
  upload_to_s3 bucket, key, content, "text/html"
end
upload_to_s3(bucket, key, content, type) click to toggle source
# File lib/bibi/publish.rb, line 143
def upload_to_s3(bucket, key, content, type)
  object = bucket.object(key)
  etag = Digest::MD5.hexdigest(content)
  if object.exists? && object.etag == "\"#{etag}\"" # seriously?
    $stderr.puts "Skipping #{object.public_url}"
    return
  end
  $stderr.puts "Uploading#{dry_run? ? " (dry run)" : ""} #{object.public_url}"
  object.put(body: content, content_type: type) unless dry_run?
end