From 238539c27da6a1af01e29c09354965d7169fba08 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Fri, 20 May 2022 14:21:08 +0900 Subject: [PATCH] Split files --- src/library/archive_entry.cr | 114 ++++++++++++++++ src/library/dir_entry.cr | 144 ++++++++++++++++++++ src/library/entry.cr | 253 ----------------------------------- 3 files changed, 258 insertions(+), 253 deletions(-) create mode 100644 src/library/archive_entry.cr create mode 100644 src/library/dir_entry.cr diff --git a/src/library/archive_entry.cr b/src/library/archive_entry.cr new file mode 100644 index 0000000..4075590 --- /dev/null +++ b/src/library/archive_entry.cr @@ -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 diff --git a/src/library/dir_entry.cr b/src/library/dir_entry.cr new file mode 100644 index 0000000..a444cb0 --- /dev/null +++ b/src/library/dir_entry.cr @@ -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 diff --git a/src/library/entry.cr b/src/library/entry.cr index ef0556d..b718ed7 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -1,5 +1,4 @@ require "image_size" -require "yaml" abstract class Entry getter id : String, book : Title, title : String, @@ -229,255 +228,3 @@ abstract class Entry abstract def examine : Bool? 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