Browse Source

WIP: move zip extract logic from script to gem

Lukasz Badura 5 months ago
parent
commit
e43da653d5
5 changed files with 121 additions and 9 deletions
  1. 11 0
      bin/fotos
  2. 7 4
      fotos.gemspec
  3. 2 5
      lib/fotos.rb
  4. 32 0
      lib/fotos/thumbnail.rb
  5. 69 0
      lib/fotos/zip_extractor.rb

+ 11 - 0
bin/fotos

@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+
+require 'fotos'
+require 'optparse'
+
+parser = OptionParser.new
+parser.on('-z PATH', '--zip', 'Extract a zip file with images from PATH')
+parser.on('-d [PATH]', '--dest', 'Copy to a destinatio dir')
+options = {dest: '.'}
+parser.parse!(into: options)
+Fotos::ZipExtractor.new(options).call

+ 7 - 4
fotos.gemspec

@@ -28,12 +28,15 @@ Gem::Specification.new do |spec|
         f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
         f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
     end
     end
   end
   end
-  spec.bindir = "exe"
-  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+  spec.bindir = "bin"
+  spec.executables = "fotos"
   spec.require_paths = ["lib"]
   spec.require_paths = ["lib"]
 
 
-  # Uncomment to register a new dependency of your gem
-  # spec.add_dependency "example-gem", "~> 1.0"
+  spec.add_dependency "image_science", "~> 1.3"
+  spec.add_dependency "rubyzip", "~> 2.4"
+  spec.add_dependency "exifr", "~> 1.4"
+  spec.add_dependency "rake", "~> 13.2"
+  spec.add_dependency "logger"
 
 
   # For more information and examples about making a new gem, check out our
   # For more information and examples about making a new gem, check out our
   # guide at: https://bundler.io/guides/creating_gem.html
   # guide at: https://bundler.io/guides/creating_gem.html

+ 2 - 5
lib/fotos.rb

@@ -1,8 +1,5 @@
 # frozen_string_literal: true
 # frozen_string_literal: true
 
 
 require_relative "fotos/version"
 require_relative "fotos/version"
-
-module Fotos
-  class Error < StandardError; end
-  # Your code goes here...
-end
+require_relative "fotos/zip_extractor"
+require_relative "fotos/thumbnail"

+ 32 - 0
lib/fotos/thumbnail.rb

@@ -0,0 +1,32 @@
+require 'image_science'
+module Fotos
+  class Thumbnail
+    def initialize(path)
+      @path = path
+      @input_filename = File.basename(path)
+    end
+
+    def create
+      if File.exist?(thumbnail_path)
+        puts "Thumbnail exists for #{@input_filename}"
+      else
+        puts "Creating #{thumbnail_filename}"
+        ImageScience.with_image(@path) do |img|
+          img.thumbnail(250) do |thumb|
+            thumb.save(thumbnail_path)
+          end
+        end
+      end
+    end
+
+    private
+
+    def thumbnail_filename
+      "TH_#{@input_filename}"
+    end
+
+    def thumbnail_path
+      File.join(File.dirname(@path), thumbnail_filename)
+    end
+  end
+end

+ 69 - 0
lib/fotos/zip_extractor.rb

@@ -0,0 +1,69 @@
+require 'zip'
+require 'exifr/jpeg'
+require 'fileutils'
+
+module Fotos
+  class ZipExtractor
+    def initialize(options)
+      @zip_file_path = options[:zip]
+      @destination_path = options[:dest]
+      @extracted_paths = []
+      @copied_paths = []
+    end
+
+    attr_reader :zip_file_path, :destination_path
+    attr_accessor :extracted_paths, :copied_paths
+
+    def call
+      extract
+      copy
+      generate_thumbnails
+    end
+
+    private
+    def extract
+      Zip::File.open(zip_file_path) do |zip_file|
+        tmp_dir_path = File.join(Pathname.pwd, 'tmp')
+        Dir.mkdir(tmp_dir_path) unless Dir.exist?(tmp_dir_path)
+
+        zip_file.each do |entry|
+          file_name = entry.name.split('/').last
+          dest_path = File.join(tmp_dir_path, file_name)
+          #puts "extracting #{entry.name}"
+          extracted_paths << dest_path
+          entry.extract(dest_path)
+        rescue Zip::DestinationFileExistsError
+          next
+        end
+      end
+    end
+
+    def copy
+      date_format = '%d-%m-%Y'
+      copied_paths = extracted_paths.map do |fp|
+        file_name = File.basename(fp)
+        puts "looking at #{file_name}"
+        exif = EXIFR::JPEG.new(fp)
+
+        # get date from file's exif data
+        exif_date_str = exif.date_time.strftime(date_format)
+
+        # destination dir for given file in public/images/dd-mm-yyyy
+        dest_dir = File.join(Pathname.pwd, destination_path, 'images', exif_date_str)
+        dest_path = File.join(dest_dir, File.basename(fp))
+
+        # create destination dir if not already there
+        FileUtils.mkdir_p(dest_dir) unless Dir.exist?(dest_dir)
+        puts "#{file_name} --> #{dest_path}"
+        FileUtils.cp(fp, dest_path)
+        dest_path
+      end
+    end
+
+    def generate_thumbnails
+      copied_paths.map do |fp|
+        Thumbnail.new(fp).create
+      end
+    end
+  end
+end