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: []
|