simple-images-downloader 1.0.3 → 1.1.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 +4 -4
- data/CHANGELOG.md +7 -1
- data/Gemfile.lock +1 -3
- data/README.md +14 -1
- data/lib/simple_images_downloader/configuration.rb +23 -1
- data/lib/simple_images_downloader/dispenser.rb +1 -1
- data/lib/simple_images_downloader/downloader.rb +15 -6
- data/lib/simple_images_downloader/errors.rb +10 -3
- data/lib/simple_images_downloader/line.rb +3 -10
- data/lib/simple_images_downloader/source_file.rb +1 -1
- data/lib/simple_images_downloader/strategies/from_file_strategy.rb +24 -0
- data/lib/simple_images_downloader/strategies/from_url_strategy.rb +18 -0
- data/lib/simple_images_downloader/strategies/strategy.rb +14 -0
- data/lib/simple_images_downloader/stringio_to_tempfile.rb +0 -2
- data/lib/simple_images_downloader/validatable/destination_validator.rb +5 -3
- data/lib/simple_images_downloader/validatable/file_accessibility_validator.rb +3 -3
- data/lib/simple_images_downloader/validatable/file_persistance_validator.rb +3 -3
- data/lib/simple_images_downloader/validatable/mime_type_validator.rb +59 -0
- data/lib/simple_images_downloader/version.rb +1 -1
- data/lib/simple_images_downloader.rb +22 -15
- data/rubocop.yml +3 -0
- data/simple_images_downloader.gemspec +0 -2
- metadata +5 -16
- data/lib/simple_images_downloader/validatable/image_path_validator.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 902c3b0e5fe1566296ac139123707162e33ded87accc9ff5705231fb3fa96f4f
|
4
|
+
data.tar.gz: c2812c8d700ca81d1f29b6a29d0063aef74b9dfd3162c652453733870b8073fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5501d04aa338c0f992d391d94a5b29e8b63a410938c7a8f31941ed3178b2efa63a6ef84b9bb419f87278880197498367eeb235dea017509c57c708f758f7b4ab
|
7
|
+
data.tar.gz: 26ba7c6dbd4cfdf1e34750ce6b3f7e99650511ba56597a7c8ab1ee7950c210f7919f0a1104053fcc6195bec822b215678e9c8bc5015fee9d6fc8ae6eb27612e7
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
## 1.1.0 - 2023-09-30
|
2
|
+
- Add validation of downloaded content over path validation
|
3
|
+
- Add ability to extend mime types from configuration
|
4
|
+
- Removed zeitwerk
|
5
|
+
- Refactored main interface
|
6
|
+
|
1
7
|
## 1.0.3 - 2023-09-27
|
2
8
|
- Corrected destination validation in SimpleImagesDownloader::Dispenser
|
3
|
-
- Corrected source file validation in SimpleImagesDownloader::
|
9
|
+
- Corrected source file validation in SimpleImagesDownloader::SourceFile
|
4
10
|
- Refactored
|
5
11
|
- Fixed error message when destination is invalid
|
6
12
|
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
simple-images-downloader (1.0
|
5
|
-
zeitwerk (~> 2.4.0)
|
4
|
+
simple-images-downloader (1.1.0)
|
6
5
|
|
7
6
|
GEM
|
8
7
|
remote: https://rubygems.org/
|
@@ -76,7 +75,6 @@ GEM
|
|
76
75
|
addressable (>= 2.3.6)
|
77
76
|
crack (>= 0.3.2)
|
78
77
|
hashdiff (>= 0.4.0, < 2.0.0)
|
79
|
-
zeitwerk (2.4.2)
|
80
78
|
|
81
79
|
PLATFORMS
|
82
80
|
ruby
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ Or install it yourself as:
|
|
33
33
|
|
34
34
|
The gem is provided with executable.
|
35
35
|
|
36
|
-
You can either run plain
|
36
|
+
You can either run plain command with file containing list of url:
|
37
37
|
|
38
38
|
```bash
|
39
39
|
simple-images-downloader <path_to_file>
|
@@ -67,6 +67,7 @@ Downloading https://test-for-simple-images-downloader.s3.eu-central-1.amazonaws.
|
|
67
67
|
Downloading is finished
|
68
68
|
```
|
69
69
|
|
70
|
+
## Configuration
|
70
71
|
**By default the images stored in a directory the script is run.**
|
71
72
|
You can also configure the place where the images would be stored to:
|
72
73
|
|
@@ -78,6 +79,18 @@ You can also configure the place where the images would be stored to:
|
|
78
79
|
[2] pry(main)* end
|
79
80
|
```
|
80
81
|
|
82
|
+
**By default the gem downloads only images with mime types: image/avif, image/gif, image/apng, image/jpg, image/jpeg, image/png, image/svg+xml, image/webp.**
|
83
|
+
You can also configure the mime types to download images with:
|
84
|
+
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
[1] pry(main)> require 'simple_images_downloader'
|
88
|
+
|
89
|
+
[2] pry(main)> SimpleImagesDownloader::Configuration.configure do |config|
|
90
|
+
[2] pry(main)* # You must use RFC 1341 - MIME (Multipurpose Internet Mail Extensions) format
|
91
|
+
[2] pry(main)* config.valid_mime_types = %w(image/png image/jpg image/jpeg)
|
92
|
+
[2] pry(main)* end
|
93
|
+
```
|
81
94
|
## Development
|
82
95
|
|
83
96
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -6,6 +6,7 @@ module SimpleImagesDownloader
|
|
6
6
|
|
7
7
|
ACCESSORS = %i[
|
8
8
|
destination
|
9
|
+
valid_mime_types
|
9
10
|
].freeze
|
10
11
|
|
11
12
|
REQUEST_OPTIONS = {
|
@@ -15,10 +16,31 @@ module SimpleImagesDownloader
|
|
15
16
|
read_timeout: 30
|
16
17
|
}.freeze
|
17
18
|
|
19
|
+
# https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types#common_image_file_types
|
20
|
+
DEFAULT_VALID_MIME_TYPES_MAP = {
|
21
|
+
'image/avif' => true,
|
22
|
+
'image/gif' => true,
|
23
|
+
'image/apng' => true,
|
24
|
+
'image/jpg' => true,
|
25
|
+
'image/jpeg' => true,
|
26
|
+
'image/png' => true,
|
27
|
+
'image/svg+xml' => true,
|
28
|
+
'image/webp' => true
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
DEFAULT_DESTINATION = './'
|
32
|
+
|
18
33
|
attr_accessor(*ACCESSORS)
|
19
34
|
|
20
35
|
def initialize
|
21
|
-
@destination =
|
36
|
+
@destination = DEFAULT_DESTINATION
|
37
|
+
@valid_mime_types = DEFAULT_VALID_MIME_TYPES_MAP.keys
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid_mime_types=(value)
|
41
|
+
raise BaseError, 'valid_mime_types must be an array' unless value.is_a?(Array)
|
42
|
+
|
43
|
+
@valid_mime_types = value
|
22
44
|
end
|
23
45
|
|
24
46
|
def self.configure
|
@@ -2,22 +2,31 @@
|
|
2
2
|
|
3
3
|
module SimpleImagesDownloader
|
4
4
|
class Downloader
|
5
|
-
|
6
|
-
|
5
|
+
include Validatable
|
6
|
+
|
7
|
+
def initialize(uri, client = Client.new, validators = [MimeTypeValidator.new])
|
8
|
+
@uri = uri
|
9
|
+
@client = client
|
10
|
+
@validators = validators
|
7
11
|
end
|
8
12
|
|
9
13
|
def download
|
10
14
|
puts "Downloading #{@uri}"
|
11
15
|
|
12
|
-
io =
|
16
|
+
io = @client.open(@uri)
|
17
|
+
|
18
|
+
raise Errors::EmptyResponse, @uri if io.nil?
|
19
|
+
|
20
|
+
validate!({ path: @uri.to_s, io: io })
|
13
21
|
|
14
|
-
|
22
|
+
tempfile = StringioToTempfile.convert(io)
|
15
23
|
|
16
|
-
Dispenser.new(
|
24
|
+
Dispenser.new(tempfile, @uri.path).place
|
17
25
|
|
18
26
|
puts 'Downloading is finished'
|
19
27
|
ensure
|
20
|
-
|
28
|
+
io&.close
|
29
|
+
tempfile&.close
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -25,9 +25,9 @@ module SimpleImagesDownloader
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
class
|
29
|
-
def initialize(path)
|
30
|
-
message = "The path
|
28
|
+
class BadMimeType < BaseError
|
29
|
+
def initialize(path, mime_type)
|
30
|
+
message = "The image with path: #{path} has wrong mime type #{mime_type}"
|
31
31
|
super(message)
|
32
32
|
end
|
33
33
|
end
|
@@ -66,5 +66,12 @@ module SimpleImagesDownloader
|
|
66
66
|
super(message)
|
67
67
|
end
|
68
68
|
end
|
69
|
+
|
70
|
+
class EmptyResponse < BaseError
|
71
|
+
def initialize(uri)
|
72
|
+
message = "Nothing returned from request #{uri}"
|
73
|
+
super(message)
|
74
|
+
end
|
75
|
+
end
|
69
76
|
end
|
70
77
|
end
|
@@ -2,19 +2,12 @@
|
|
2
2
|
|
3
3
|
module SimpleImagesDownloader
|
4
4
|
class Line
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(string, validators = [ImagePathValidator.new])
|
8
|
-
@string = string
|
9
|
-
@validators = validators
|
5
|
+
def initialize(string)
|
6
|
+
@string = string
|
10
7
|
end
|
11
8
|
|
12
9
|
def uri
|
13
|
-
|
14
|
-
|
15
|
-
validate!(@string)
|
16
|
-
|
17
|
-
parsed_uri
|
10
|
+
URI.parse(@string)
|
18
11
|
rescue URI::Error
|
19
12
|
raise Errors::BadUrl, @string
|
20
13
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleImagesDownloader
|
4
|
+
module Strategies
|
5
|
+
class FromFileStrategy < Strategy
|
6
|
+
def initialize(path)
|
7
|
+
super
|
8
|
+
@path = path
|
9
|
+
end
|
10
|
+
|
11
|
+
def process
|
12
|
+
source_file = SourceFile.new(@path)
|
13
|
+
|
14
|
+
source_file.each_line do |line|
|
15
|
+
uri = Line.new(line).uri
|
16
|
+
Downloader.new(uri).download
|
17
|
+
rescue Errors::BaseError => e
|
18
|
+
puts e.message
|
19
|
+
next
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleImagesDownloader
|
4
|
+
module Strategies
|
5
|
+
class FromUrlStrategy < Strategy
|
6
|
+
def initialize(url)
|
7
|
+
super
|
8
|
+
@url = url
|
9
|
+
end
|
10
|
+
|
11
|
+
def process
|
12
|
+
uri = Line.new(@url).uri
|
13
|
+
|
14
|
+
Downloader.new(uri).download
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -3,9 +3,11 @@
|
|
3
3
|
module SimpleImagesDownloader
|
4
4
|
module Validatable
|
5
5
|
class DestinationValidator < Validator
|
6
|
-
def validate(
|
7
|
-
|
8
|
-
|
6
|
+
def validate(options)
|
7
|
+
path = options[:path]
|
8
|
+
|
9
|
+
raise Errors::DestinationIsNotDirectory, path unless File.directory?(path)
|
10
|
+
raise Errors::DestinationIsNotWritable, path unless File.writable?(path)
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
module SimpleImagesDownloader
|
4
4
|
module Validatable
|
5
5
|
class FileAccessibilityValidator < Validator
|
6
|
-
def validate(
|
7
|
-
return if File.readable?(path)
|
6
|
+
def validate(options)
|
7
|
+
return if File.readable?(options[:path])
|
8
8
|
|
9
|
-
raise Errors::PermissionsError, path
|
9
|
+
raise Errors::PermissionsError, options[:path]
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
module SimpleImagesDownloader
|
4
4
|
module Validatable
|
5
5
|
class FilePersistanceValidator < Validator
|
6
|
-
def validate(
|
7
|
-
return if File.exist?(path)
|
6
|
+
def validate(options)
|
7
|
+
return if File.exist?(options[:path])
|
8
8
|
|
9
|
-
raise Errors::MissingFileError, path
|
9
|
+
raise Errors::MissingFileError, options[:path]
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleImagesDownloader
|
4
|
+
module Validatable
|
5
|
+
class MimeTypeValidator < Validator
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegator 'SimpleImagesDownloader::Configuration', :valid_mime_types, :valid_mime_types
|
9
|
+
|
10
|
+
def validate(options)
|
11
|
+
path = options[:path]
|
12
|
+
io = options[:io]
|
13
|
+
|
14
|
+
mime_type = mime_type_of(io)
|
15
|
+
|
16
|
+
return if Configuration::DEFAULT_VALID_MIME_TYPES_MAP[mime_type]
|
17
|
+
|
18
|
+
raise Errors::BadMimeType.new(path, mime_type)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Taken from Shrine https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/determine_mime_type.rb#L94
|
24
|
+
def mime_type_of(io)
|
25
|
+
Open3.popen3('file --mime-type --brief -') do |stdin, stdout, stderr, thread|
|
26
|
+
copy_stream(from: io, to: stdin.binmode)
|
27
|
+
|
28
|
+
io.rewind
|
29
|
+
stdin.close
|
30
|
+
|
31
|
+
status = thread.value
|
32
|
+
|
33
|
+
validate_thread_status(status)
|
34
|
+
$stderr.print(stderr.read)
|
35
|
+
|
36
|
+
output = stdout.read.strip
|
37
|
+
|
38
|
+
validate_command_output(output)
|
39
|
+
|
40
|
+
output
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def copy_stream(from:, to:)
|
45
|
+
IO.copy_stream(from, to)
|
46
|
+
rescue Errno::EPIPE # rubocop:disable Lint/SuppressedException
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate_thread_status(status)
|
50
|
+
raise Errors::BaseError, "file command failed to spawn: #{stderr.read}" if status.nil?
|
51
|
+
raise Errors::BaseError, "file command failed: #{stderr.read}" unless status.success?
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_command_output(output)
|
55
|
+
raise Errors::BaseError, "file command failed: #{output}" if output.include?('cannot open')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -4,27 +4,34 @@ require 'open-uri'
|
|
4
4
|
require 'tempfile'
|
5
5
|
require 'forwardable'
|
6
6
|
require 'singleton'
|
7
|
-
require '
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
require 'open3'
|
8
|
+
require_relative 'simple_images_downloader/version'
|
9
|
+
require_relative 'simple_images_downloader/errors'
|
10
|
+
require_relative 'simple_images_downloader/configuration'
|
11
|
+
require_relative 'simple_images_downloader/validatable'
|
12
|
+
require_relative 'simple_images_downloader/validatable/validator'
|
13
|
+
require_relative 'simple_images_downloader/validatable/destination_validator'
|
14
|
+
require_relative 'simple_images_downloader/validatable/file_accessibility_validator'
|
15
|
+
require_relative 'simple_images_downloader/validatable/file_persistance_validator'
|
16
|
+
require_relative 'simple_images_downloader/validatable/mime_type_validator'
|
17
|
+
require_relative 'simple_images_downloader/stringio_to_tempfile'
|
18
|
+
require_relative 'simple_images_downloader/client'
|
19
|
+
require_relative 'simple_images_downloader/source_file'
|
20
|
+
require_relative 'simple_images_downloader/runner'
|
21
|
+
require_relative 'simple_images_downloader/line'
|
22
|
+
require_relative 'simple_images_downloader/dispenser'
|
23
|
+
require_relative 'simple_images_downloader/strategies/strategy'
|
24
|
+
require_relative 'simple_images_downloader/downloader'
|
25
|
+
require_relative 'simple_images_downloader/strategies/from_file_strategy'
|
26
|
+
require_relative 'simple_images_downloader/strategies/from_url_strategy'
|
11
27
|
|
12
28
|
module SimpleImagesDownloader
|
13
29
|
def self.from_file(path)
|
14
|
-
|
15
|
-
|
16
|
-
source_file.each_line do |line|
|
17
|
-
uri = Line.new(line).uri
|
18
|
-
Downloader.new(uri).download
|
19
|
-
rescue Errors::BaseError => e
|
20
|
-
puts e.message
|
21
|
-
next
|
22
|
-
end
|
30
|
+
SimpleImagesDownloader::Strategies::FromFileStrategy.new(path).process
|
23
31
|
end
|
24
32
|
|
25
33
|
def self.from_url(url)
|
26
|
-
|
27
|
-
Downloader.new(uri).download
|
34
|
+
SimpleImagesDownloader::Strategies::FromUrlStrategy.new(url).process
|
28
35
|
end
|
29
36
|
|
30
37
|
def self.root
|
data/rubocop.yml
CHANGED
@@ -30,8 +30,6 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
31
|
spec.require_paths = ['lib']
|
32
32
|
|
33
|
-
spec.add_runtime_dependency 'zeitwerk', '~> 2.4.0'
|
34
|
-
|
35
33
|
spec.add_development_dependency 'faker', '~> 2.14'
|
36
34
|
spec.add_development_dependency 'pry', '~> 0.13.1'
|
37
35
|
spec.add_development_dependency 'rake', '~> 12.0'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-images-downloader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- IlkhamGaysin
|
@@ -10,20 +10,6 @@ bindir: exe
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2023-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: zeitwerk
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 2.4.0
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 2.4.0
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: faker
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -214,12 +200,15 @@ files:
|
|
214
200
|
- lib/simple_images_downloader/line.rb
|
215
201
|
- lib/simple_images_downloader/runner.rb
|
216
202
|
- lib/simple_images_downloader/source_file.rb
|
203
|
+
- lib/simple_images_downloader/strategies/from_file_strategy.rb
|
204
|
+
- lib/simple_images_downloader/strategies/from_url_strategy.rb
|
205
|
+
- lib/simple_images_downloader/strategies/strategy.rb
|
217
206
|
- lib/simple_images_downloader/stringio_to_tempfile.rb
|
218
207
|
- lib/simple_images_downloader/validatable.rb
|
219
208
|
- lib/simple_images_downloader/validatable/destination_validator.rb
|
220
209
|
- lib/simple_images_downloader/validatable/file_accessibility_validator.rb
|
221
210
|
- lib/simple_images_downloader/validatable/file_persistance_validator.rb
|
222
|
-
- lib/simple_images_downloader/validatable/
|
211
|
+
- lib/simple_images_downloader/validatable/mime_type_validator.rb
|
223
212
|
- lib/simple_images_downloader/validatable/validator.rb
|
224
213
|
- lib/simple_images_downloader/version.rb
|
225
214
|
- rubocop.yml
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SimpleImagesDownloader
|
4
|
-
module Validatable
|
5
|
-
class ImagePathValidator < Validator
|
6
|
-
VALID_EXTENSIONS = %w[.png .jpg .gif .jpeg].freeze
|
7
|
-
|
8
|
-
def validate(path)
|
9
|
-
extension = File.extname(path)
|
10
|
-
|
11
|
-
return if VALID_EXTENSIONS.include?(extension)
|
12
|
-
|
13
|
-
raise Errors::MissingImageInPath, path
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|