imgfetcha 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/imgfetcha +6 -0
- data/lib/imgfetcha.rb +22 -0
- data/lib/imgfetcha/arg_parser.rb +48 -0
- data/lib/imgfetcha/batch_fetcher.rb +69 -0
- data/lib/imgfetcha/errors/input_file_not_specified_error.rb +11 -0
- data/lib/imgfetcha/errors/no_urls_found_error.rb +11 -0
- data/lib/imgfetcha/file_reader.rb +40 -0
- data/lib/imgfetcha/version.rb +3 -0
- metadata +112 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: 85a525ae878b7bdb3a04929960bae1c2a346efaca5774a1a78b51cdbf003259e
         | 
| 4 | 
            +
              data.tar.gz: cc85354908698f73e8b7d96a9c4343f1394df2cf2fd97c69edf7242fe0549c91
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 55c26e1b660266ff2949c4a220e855ef5530edb6f3261d1fd5c19075d36387184d30d636b8323d1f867726de68535a16df8a0a45db195f7ccd35ab51898a1a2a
         | 
| 7 | 
            +
              data.tar.gz: 61577dcbe5f68f9ad96c9c4c2aebfcf61fc7a031774e854cb27e21169dd9f640512e48813e354abf6ee9d94a90ad4e6be2b47eb983ee23f4cead0c21ee212a95
         | 
    
        data/bin/imgfetcha
    ADDED
    
    
    
        data/lib/imgfetcha.rb
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            require 'imgfetcha/version'
         | 
| 2 | 
            +
            require 'imgfetcha/arg_parser'
         | 
| 3 | 
            +
            require 'imgfetcha/file_reader'
         | 
| 4 | 
            +
            require 'imgfetcha/batch_fetcher'
         | 
| 5 | 
            +
            require 'imgfetcha/errors/input_file_not_specified_error'
         | 
| 6 | 
            +
            require 'imgfetcha/errors/no_urls_found_error'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module Imgfetcha
         | 
| 9 | 
            +
              def self.run
         | 
| 10 | 
            +
                parser = ArgParser.new
         | 
| 11 | 
            +
                options = parser.run
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                reader = FileReader.new(options)
         | 
| 14 | 
            +
                reader.run
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                downloader = BatchFetcher.new(reader.result, options)
         | 
| 17 | 
            +
                downloader.run
         | 
| 18 | 
            +
              rescue StandardError, NotImplementedError => e
         | 
| 19 | 
            +
                puts e.class, e.message
         | 
| 20 | 
            +
                puts e.backtrace if options[:verbose]
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            require 'optparse'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Imgfetcha
         | 
| 4 | 
            +
              class ArgParser
         | 
| 5 | 
            +
                attr_accessor :result
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize
         | 
| 8 | 
            +
                  @result = {}
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def run
         | 
| 12 | 
            +
                  execute_parser
         | 
| 13 | 
            +
                  @result
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                private
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # rubocop:disable Metrics/MethodLength
         | 
| 19 | 
            +
                def execute_parser
         | 
| 20 | 
            +
                  OptionParser.new do |opts|
         | 
| 21 | 
            +
                    opts.banner = 'Usage: imgfetcha -i INPUT_FILE -o OUTPUT_DIRECTORY'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
         | 
| 24 | 
            +
                      @result[:verbose] = v
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    opts.on('-i INPUT_FILE', '--input=INPUT_FILE', 'Specify input file') do |i|
         | 
| 28 | 
            +
                      @result[:input_file] = i
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    opts.on('-o OUTPUT_DIRECTORY', '--output=OUTPUT_DIRECTORY', 'Specify output directory') do |o|
         | 
| 32 | 
            +
                      @result[:output_dir] = o
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    opts.on('-V', '--version', 'Print version') do
         | 
| 36 | 
            +
                      puts Imgfetcha::VERSION
         | 
| 37 | 
            +
                      exit
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    opts.on('-h', '--help', 'Print this help') do
         | 
| 41 | 
            +
                      puts opts
         | 
| 42 | 
            +
                      exit
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
                  end.parse!
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
                # rubocop:enable Metrics/MethodLength
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -0,0 +1,69 @@ | |
| 1 | 
            +
            require 'open-uri'
         | 
| 2 | 
            +
            require 'mime/types'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Imgfetcha
         | 
| 5 | 
            +
              class BatchFetcher
         | 
| 6 | 
            +
                # NOTE: 'bin' stands for `application/octet-stream`
         | 
| 7 | 
            +
                VALID_TYPES = %w[jpeg jpg png gif heic bin].freeze
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                attr_reader :urls, :output_dir, :result
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def initialize(urls, options)
         | 
| 12 | 
            +
                  @urls       = urls
         | 
| 13 | 
            +
                  @output_dir = options[:output_dir] || Dir.pwd
         | 
| 14 | 
            +
                  @verbose    = options[:verbose]
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def run
         | 
| 18 | 
            +
                  @result = batch_download
         | 
| 19 | 
            +
                  puts "\nDownloaded #{@result.count} images"
         | 
| 20 | 
            +
                  @result
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                private
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def batch_download
         | 
| 26 | 
            +
                  urls.map.with_index do |url, i|
         | 
| 27 | 
            +
                    print_progress(url, i)
         | 
| 28 | 
            +
                    temp_file = URI.open(url)
         | 
| 29 | 
            +
                    type      = detect_type(temp_file)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    next unless validate_type(type)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    write_file(temp_file: temp_file, name: file_name(url, temp_file))
         | 
| 34 | 
            +
                    url
         | 
| 35 | 
            +
                  end.compact
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # Get basename from a URL
         | 
| 39 | 
            +
                def file_name(url, file)
         | 
| 40 | 
            +
                  name = File.basename(URI.parse(url).path)
         | 
| 41 | 
            +
                  # Append type if valid types aren't contained in the name
         | 
| 42 | 
            +
                  name += ".#{detect_type(file)}" unless VALID_TYPES.any? { |type| name.include?(type) }
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  name
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def write_file(temp_file:, name:)
         | 
| 48 | 
            +
                  File.open("#{@output_dir}/#{name}", 'wb') do |f|
         | 
| 49 | 
            +
                    f.write(temp_file.read) ? print('OK') : print('ERROR')
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def detect_type(file)
         | 
| 54 | 
            +
                  content_type = file.meta['content-type']
         | 
| 55 | 
            +
                  MIME::Types[content_type].first.preferred_extension
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                def validate_type(type)
         | 
| 59 | 
            +
                  return true if VALID_TYPES.include?(type)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  print("ERROR: Type #{type} is invalid")
         | 
| 62 | 
            +
                  false
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def print_progress(url, index)
         | 
| 66 | 
            +
                  print "\n[#{index + 1}/#{@urls.count}] Downloading #{url} "
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            module Imgfetcha
         | 
| 2 | 
            +
              class FileReader
         | 
| 3 | 
            +
                attr_reader :input_file, :result
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(options)
         | 
| 6 | 
            +
                  @input_file = options[:input_file]
         | 
| 7 | 
            +
                  @verbose    = options[:verbose]
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def run
         | 
| 11 | 
            +
                  read_file
         | 
| 12 | 
            +
                  filter_urls
         | 
| 13 | 
            +
                  report_results if @verbose
         | 
| 14 | 
            +
                  @result
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                private
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def read_file
         | 
| 20 | 
            +
                  raise InputFileNotSpecifiedError unless @input_file
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # Expand path so that Dir#chdir would understand paths relative to home
         | 
| 23 | 
            +
                  @contents = File.read(File.expand_path(@input_file)).split
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def filter_urls
         | 
| 27 | 
            +
                  @result = @contents.select { |url| URI.parse(url).is_a?(URI::HTTP) }
         | 
| 28 | 
            +
                  raise NoUrlsFoundError if @result.empty?
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  # TODO: group valid and unvalid URLs, warn about invalid ones
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  @result
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def report_results
         | 
| 36 | 
            +
                  puts "Found #{@result.count} URLs in #{@contents.count} lines:"
         | 
| 37 | 
            +
                  puts @result
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,112 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: imgfetcha
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - ston1x
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2020-07-31 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: mime-types
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '3.1'
         | 
| 20 | 
            +
              type: :development
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '3.1'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: pry
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: 0.13.1
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: 0.13.1
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: rspec
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - "~>"
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: 3.9.0
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - "~>"
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: 3.9.0
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: rubocop
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - '='
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: 0.88.0
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - '='
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: 0.88.0
         | 
| 69 | 
            +
            description: Uses input file as a list of URLs and downloads all the images
         | 
| 70 | 
            +
            email:
         | 
| 71 | 
            +
            - stoianovnk@gmail.com
         | 
| 72 | 
            +
            executables:
         | 
| 73 | 
            +
            - imgfetcha
         | 
| 74 | 
            +
            extensions: []
         | 
| 75 | 
            +
            extra_rdoc_files: []
         | 
| 76 | 
            +
            files:
         | 
| 77 | 
            +
            - bin/imgfetcha
         | 
| 78 | 
            +
            - lib/imgfetcha.rb
         | 
| 79 | 
            +
            - lib/imgfetcha/arg_parser.rb
         | 
| 80 | 
            +
            - lib/imgfetcha/batch_fetcher.rb
         | 
| 81 | 
            +
            - lib/imgfetcha/errors/input_file_not_specified_error.rb
         | 
| 82 | 
            +
            - lib/imgfetcha/errors/no_urls_found_error.rb
         | 
| 83 | 
            +
            - lib/imgfetcha/file_reader.rb
         | 
| 84 | 
            +
            - lib/imgfetcha/version.rb
         | 
| 85 | 
            +
            homepage: https://github.com/ston1x/imgfetcha
         | 
| 86 | 
            +
            licenses:
         | 
| 87 | 
            +
            - MIT
         | 
| 88 | 
            +
            metadata:
         | 
| 89 | 
            +
              allowed_push_host: https://rubygems.org
         | 
| 90 | 
            +
              homepage_uri: https://github.com/ston1x/imgfetcha
         | 
| 91 | 
            +
              source_code_uri: https://github.com/ston1x/imgfetcha
         | 
| 92 | 
            +
              changelog_uri: https://github.com/ston1x/imgfetcha
         | 
| 93 | 
            +
            post_install_message: 
         | 
| 94 | 
            +
            rdoc_options: []
         | 
| 95 | 
            +
            require_paths:
         | 
| 96 | 
            +
            - lib
         | 
| 97 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 98 | 
            +
              requirements:
         | 
| 99 | 
            +
              - - ">="
         | 
| 100 | 
            +
                - !ruby/object:Gem::Version
         | 
| 101 | 
            +
                  version: 2.3.0
         | 
| 102 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 103 | 
            +
              requirements:
         | 
| 104 | 
            +
              - - ">="
         | 
| 105 | 
            +
                - !ruby/object:Gem::Version
         | 
| 106 | 
            +
                  version: '0'
         | 
| 107 | 
            +
            requirements: []
         | 
| 108 | 
            +
            rubygems_version: 3.1.2
         | 
| 109 | 
            +
            signing_key: 
         | 
| 110 | 
            +
            specification_version: 4
         | 
| 111 | 
            +
            summary: Ruby gem that takes an input of image URLs and downloads them in batch
         | 
| 112 | 
            +
            test_files: []
         |