mirror of
https://github.com/hkalexling/Mango.git
synced 2025-08-02 02:45:29 -04:00
115 lines
2.9 KiB
Crystal
115 lines
2.9 KiB
Crystal
require "yaml"
|
|
|
|
require "./entry"
|
|
|
|
class ArchiveEntry < Entry
|
|
include YAML::Serializable
|
|
|
|
getter zip_path : String
|
|
|
|
def initialize(@zip_path, @book)
|
|
storage = Storage.default
|
|
@encoded_path = URI.encode @zip_path
|
|
@title = File.basename @zip_path, File.extname @zip_path
|
|
@encoded_title = URI.encode @title
|
|
@size = (File.size @zip_path).humanize_bytes
|
|
id = storage.get_entry_id @zip_path, File.signature(@zip_path)
|
|
if id.nil?
|
|
id = random_str
|
|
storage.insert_entry_id({
|
|
path: @zip_path,
|
|
id: id,
|
|
signature: File.signature(@zip_path).to_s,
|
|
})
|
|
end
|
|
@id = id
|
|
@mtime = File.info(@zip_path).modification_time
|
|
|
|
unless File.readable? @zip_path
|
|
@err_msg = "File #{@zip_path} is not readable."
|
|
Logger.warn "#{@err_msg} Please make sure the " \
|
|
"file permission is configured correctly."
|
|
return
|
|
end
|
|
|
|
archive_exception = validate_archive @zip_path
|
|
unless archive_exception.nil?
|
|
@err_msg = "Archive error: #{archive_exception}"
|
|
Logger.warn "Unable to extract archive #{@zip_path}. " \
|
|
"Ignoring it. #{@err_msg}"
|
|
return
|
|
end
|
|
|
|
file = ArchiveFile.new @zip_path
|
|
@pages = file.entries.count do |e|
|
|
SUPPORTED_IMG_TYPES.includes? \
|
|
MIME.from_filename? e.filename
|
|
end
|
|
file.close
|
|
end
|
|
|
|
def path : String
|
|
@zip_path
|
|
end
|
|
|
|
private def sorted_archive_entries
|
|
ArchiveFile.open @zip_path do |file|
|
|
entries = file.entries
|
|
.select { |e|
|
|
SUPPORTED_IMG_TYPES.includes? \
|
|
MIME.from_filename? e.filename
|
|
}
|
|
.sort! { |a, b|
|
|
compare_numerically a.filename, b.filename
|
|
}
|
|
yield file, entries
|
|
end
|
|
end
|
|
|
|
def read_page(page_num)
|
|
raise "Unreadble archive. #{@err_msg}" if @err_msg
|
|
img = nil
|
|
begin
|
|
sorted_archive_entries do |file, entries|
|
|
page = entries[page_num - 1]
|
|
data = file.read_entry page
|
|
if data
|
|
img = Image.new data, MIME.from_filename(page.filename),
|
|
page.filename, data.size
|
|
end
|
|
end
|
|
rescue e
|
|
Logger.warn "Unable to read page #{page_num} of #{@zip_path}. Error: #{e}"
|
|
end
|
|
img
|
|
end
|
|
|
|
def page_dimensions
|
|
sizes = [] of Hash(String, Int32)
|
|
sorted_archive_entries do |file, entries|
|
|
entries.each_with_index do |e, i|
|
|
begin
|
|
data = file.read_entry(e).not_nil!
|
|
size = ImageSize.get data
|
|
sizes << {
|
|
"width" => size.width,
|
|
"height" => size.height,
|
|
}
|
|
rescue e
|
|
Logger.warn "Failed to read page #{i} of entry #{zip_path}. #{e}"
|
|
sizes << {"width" => 1000_i32, "height" => 1000_i32}
|
|
end
|
|
end
|
|
end
|
|
sizes
|
|
end
|
|
|
|
def examine : Bool
|
|
File.exists? @zip_path
|
|
end
|
|
|
|
def self.is_valid?(path : String) : Bool
|
|
is_supported_file path
|
|
end
|
|
end
|