mirror of
https://github.com/hkalexling/Mango.git
synced 2025-08-02 19:05:32 -04:00
Split files
This commit is contained in:
parent
1f5aed64f7
commit
238539c27d
114
src/library/archive_entry.cr
Normal file
114
src/library/archive_entry.cr
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
def createtime : Time
|
||||||
|
ctime @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
|
||||||
|
end
|
144
src/library/dir_entry.cr
Normal file
144
src/library/dir_entry.cr
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
require "yaml"
|
||||||
|
|
||||||
|
require "./entry"
|
||||||
|
|
||||||
|
class DirEntry < Entry
|
||||||
|
include YAML::Serializable
|
||||||
|
|
||||||
|
getter dir_path : String
|
||||||
|
|
||||||
|
@[YAML::Field(ignore: true)]
|
||||||
|
@sorted_files : Array(String)?
|
||||||
|
|
||||||
|
@signature : String
|
||||||
|
|
||||||
|
def initialize(@dir_path, @book)
|
||||||
|
storage = Storage.default
|
||||||
|
@encoded_path = URI.encode @dir_path
|
||||||
|
@title = File.basename @dir_path
|
||||||
|
@encoded_title = URI.encode @title
|
||||||
|
|
||||||
|
unless File.readable? @dir_path
|
||||||
|
@err_msg = "Directory #{@dir_path} is not readable."
|
||||||
|
Logger.warn "#{@err_msg} Please make sure the " \
|
||||||
|
"file permission is configured correctly."
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
unless DirEntry.validate_directory_entry @dir_path
|
||||||
|
@err_msg = "Directory #{@dir_path} is not valid directory entry."
|
||||||
|
Logger.warn "#{@err_msg} Please make sure the " \
|
||||||
|
"directory has valid images."
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
size_sum = 0
|
||||||
|
sorted_files.each do |file_path|
|
||||||
|
size_sum += File.size file_path
|
||||||
|
end
|
||||||
|
@size = size_sum.humanize_bytes
|
||||||
|
|
||||||
|
@signature = Dir.directory_entry_signature @dir_path
|
||||||
|
id = storage.get_entry_id @dir_path, @signature
|
||||||
|
if id.nil?
|
||||||
|
id = random_str
|
||||||
|
storage.insert_entry_id({
|
||||||
|
path: @dir_path,
|
||||||
|
id: id,
|
||||||
|
signature: @signature,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
@id = id
|
||||||
|
|
||||||
|
@mtime = sorted_files.map do |file_path|
|
||||||
|
File.info(file_path).modification_time
|
||||||
|
end.max
|
||||||
|
@pages = sorted_files.size
|
||||||
|
end
|
||||||
|
|
||||||
|
def path : String
|
||||||
|
@dir_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def createtime : Time
|
||||||
|
ctime @dir_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_page(page_num)
|
||||||
|
img = nil
|
||||||
|
begin
|
||||||
|
files = sorted_files
|
||||||
|
file_path = files[page_num - 1]
|
||||||
|
data = File.read(file_path).to_slice
|
||||||
|
if data
|
||||||
|
img = Image.new data, MIME.from_filename(file_path),
|
||||||
|
File.basename(file_path), data.size
|
||||||
|
end
|
||||||
|
rescue e
|
||||||
|
Logger.warn "Unable to read page #{page_num} of #{@dir_path}. Error: #{e}"
|
||||||
|
end
|
||||||
|
img
|
||||||
|
end
|
||||||
|
|
||||||
|
def page_dimensions
|
||||||
|
sizes = [] of Hash(String, Int32)
|
||||||
|
sorted_files.each_with_index do |path, i|
|
||||||
|
data = File.read(path).to_slice
|
||||||
|
begin
|
||||||
|
data.not_nil!
|
||||||
|
size = ImageSize.get data
|
||||||
|
sizes << {
|
||||||
|
"width" => size.width,
|
||||||
|
"height" => size.height,
|
||||||
|
}
|
||||||
|
rescue e
|
||||||
|
Logger.warn "Failed to read page #{i} of entry #{@dir_path}. #{e}"
|
||||||
|
sizes << {"width" => 1000_i32, "height" => 1000_i32}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sizes
|
||||||
|
end
|
||||||
|
|
||||||
|
def examine : Bool
|
||||||
|
existence = File.exists? @dir_path
|
||||||
|
return false unless existence
|
||||||
|
files = DirEntry.get_valid_files @dir_path
|
||||||
|
signature = Dir.directory_entry_signature @dir_path
|
||||||
|
existence = files.size > 0 && @signature == signature
|
||||||
|
@sorted_files = nil unless existence
|
||||||
|
|
||||||
|
# For more efficient, update a directory entry with new property
|
||||||
|
# and return true like Title.examine
|
||||||
|
existence
|
||||||
|
end
|
||||||
|
|
||||||
|
def sorted_files
|
||||||
|
cached_sorted_files = @sorted_files
|
||||||
|
return cached_sorted_files if cached_sorted_files
|
||||||
|
@sorted_files = DirEntry.get_valid_files_sorted @dir_path
|
||||||
|
@sorted_files.not_nil!
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.validate_directory_entry(dir_path)
|
||||||
|
files = DirEntry.get_valid_files dir_path
|
||||||
|
files.size > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_valid_files(dir_path)
|
||||||
|
files = [] of String
|
||||||
|
Dir.entries(dir_path).each do |fn|
|
||||||
|
next if fn.starts_with? "."
|
||||||
|
path = File.join dir_path, fn
|
||||||
|
next unless is_supported_image_file path
|
||||||
|
next if File.directory? path
|
||||||
|
next unless File.readable? path
|
||||||
|
files << path
|
||||||
|
end
|
||||||
|
files
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_valid_files_sorted(dir_path)
|
||||||
|
files = DirEntry.get_valid_files dir_path
|
||||||
|
files.sort! { |a, b| compare_numerically a, b }
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +1,4 @@
|
|||||||
require "image_size"
|
require "image_size"
|
||||||
require "yaml"
|
|
||||||
|
|
||||||
abstract class Entry
|
abstract class Entry
|
||||||
getter id : String, book : Title, title : String,
|
getter id : String, book : Title, title : String,
|
||||||
@ -229,255 +228,3 @@ abstract class Entry
|
|||||||
|
|
||||||
abstract def examine : Bool?
|
abstract def examine : Bool?
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def createtime : Time
|
|
||||||
ctime @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
|
|
||||||
end
|
|
||||||
|
|
||||||
class DirEntry < Entry
|
|
||||||
include YAML::Serializable
|
|
||||||
|
|
||||||
getter dir_path : String
|
|
||||||
|
|
||||||
@[YAML::Field(ignore: true)]
|
|
||||||
@sorted_files : Array(String)?
|
|
||||||
|
|
||||||
@signature : String
|
|
||||||
|
|
||||||
def initialize(@dir_path, @book)
|
|
||||||
storage = Storage.default
|
|
||||||
@encoded_path = URI.encode @dir_path
|
|
||||||
@title = File.basename @dir_path
|
|
||||||
@encoded_title = URI.encode @title
|
|
||||||
|
|
||||||
unless File.readable? @dir_path
|
|
||||||
@err_msg = "Directory #{@dir_path} is not readable."
|
|
||||||
Logger.warn "#{@err_msg} Please make sure the " \
|
|
||||||
"file permission is configured correctly."
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
unless DirEntry.validate_directory_entry @dir_path
|
|
||||||
@err_msg = "Directory #{@dir_path} is not valid directory entry."
|
|
||||||
Logger.warn "#{@err_msg} Please make sure the " \
|
|
||||||
"directory has valid images."
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
size_sum = 0
|
|
||||||
sorted_files.each do |file_path|
|
|
||||||
size_sum += File.size file_path
|
|
||||||
end
|
|
||||||
@size = size_sum.humanize_bytes
|
|
||||||
|
|
||||||
@signature = Dir.directory_entry_signature @dir_path
|
|
||||||
id = storage.get_entry_id @dir_path, @signature
|
|
||||||
if id.nil?
|
|
||||||
id = random_str
|
|
||||||
storage.insert_entry_id({
|
|
||||||
path: @dir_path,
|
|
||||||
id: id,
|
|
||||||
signature: @signature,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
@id = id
|
|
||||||
|
|
||||||
@mtime = sorted_files.map do |file_path|
|
|
||||||
File.info(file_path).modification_time
|
|
||||||
end.max
|
|
||||||
@pages = sorted_files.size
|
|
||||||
end
|
|
||||||
|
|
||||||
def path : String
|
|
||||||
@dir_path
|
|
||||||
end
|
|
||||||
|
|
||||||
def createtime : Time
|
|
||||||
ctime @dir_path
|
|
||||||
end
|
|
||||||
|
|
||||||
def read_page(page_num)
|
|
||||||
img = nil
|
|
||||||
begin
|
|
||||||
files = sorted_files
|
|
||||||
file_path = files[page_num - 1]
|
|
||||||
data = File.read(file_path).to_slice
|
|
||||||
if data
|
|
||||||
img = Image.new data, MIME.from_filename(file_path),
|
|
||||||
File.basename(file_path), data.size
|
|
||||||
end
|
|
||||||
rescue e
|
|
||||||
Logger.warn "Unable to read page #{page_num} of #{@dir_path}. Error: #{e}"
|
|
||||||
end
|
|
||||||
img
|
|
||||||
end
|
|
||||||
|
|
||||||
def page_dimensions
|
|
||||||
sizes = [] of Hash(String, Int32)
|
|
||||||
sorted_files.each_with_index do |path, i|
|
|
||||||
data = File.read(path).to_slice
|
|
||||||
begin
|
|
||||||
data.not_nil!
|
|
||||||
size = ImageSize.get data
|
|
||||||
sizes << {
|
|
||||||
"width" => size.width,
|
|
||||||
"height" => size.height,
|
|
||||||
}
|
|
||||||
rescue e
|
|
||||||
Logger.warn "Failed to read page #{i} of entry #{@dir_path}. #{e}"
|
|
||||||
sizes << {"width" => 1000_i32, "height" => 1000_i32}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sizes
|
|
||||||
end
|
|
||||||
|
|
||||||
def examine : Bool
|
|
||||||
existence = File.exists? @dir_path
|
|
||||||
return false unless existence
|
|
||||||
files = DirEntry.get_valid_files @dir_path
|
|
||||||
signature = Dir.directory_entry_signature @dir_path
|
|
||||||
existence = files.size > 0 && @signature == signature
|
|
||||||
@sorted_files = nil unless existence
|
|
||||||
|
|
||||||
# For more efficient, update a directory entry with new property
|
|
||||||
# and return true like Title.examine
|
|
||||||
existence
|
|
||||||
end
|
|
||||||
|
|
||||||
def sorted_files
|
|
||||||
cached_sorted_files = @sorted_files
|
|
||||||
return cached_sorted_files if cached_sorted_files
|
|
||||||
@sorted_files = DirEntry.get_valid_files_sorted @dir_path
|
|
||||||
@sorted_files.not_nil!
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.validate_directory_entry(dir_path)
|
|
||||||
files = DirEntry.get_valid_files dir_path
|
|
||||||
files.size > 0
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.get_valid_files(dir_path)
|
|
||||||
files = [] of String
|
|
||||||
Dir.entries(dir_path).each do |fn|
|
|
||||||
next if fn.starts_with? "."
|
|
||||||
path = File.join dir_path, fn
|
|
||||||
next unless is_supported_image_file path
|
|
||||||
next if File.directory? path
|
|
||||||
next unless File.readable? path
|
|
||||||
files << path
|
|
||||||
end
|
|
||||||
files
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.get_valid_files_sorted(dir_path)
|
|
||||||
files = DirEntry.get_valid_files dir_path
|
|
||||||
files.sort! { |a, b| compare_numerically a, b }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user