simple-images-downloader 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 902c3b0e5fe1566296ac139123707162e33ded87accc9ff5705231fb3fa96f4f
4
- data.tar.gz: c2812c8d700ca81d1f29b6a29d0063aef74b9dfd3162c652453733870b8073fe
3
+ metadata.gz: 0e7adf857ef1d9f8490a079e5828b6025d0b44a21ec098bfc0012124c61223a9
4
+ data.tar.gz: 50175489068f5c9c7587b940d0690d335f8787f4e78c3f7ede9b26982b13b1c5
5
5
  SHA512:
6
- metadata.gz: 5501d04aa338c0f992d391d94a5b29e8b63a410938c7a8f31941ed3178b2efa63a6ef84b9bb419f87278880197498367eeb235dea017509c57c708f758f7b4ab
7
- data.tar.gz: 26ba7c6dbd4cfdf1e34750ce6b3f7e99650511ba56597a7c8ab1ee7950c210f7919f0a1104053fcc6195bec822b215678e9c8bc5015fee9d6fc8ae6eb27612e7
6
+ metadata.gz: e205d6d7feb52617f2d526765dd3b3f82509d5cfc2343ca90dbf966966784fa8099cae222904b245ff338d46f5f38883a648d50914c39ec7d3b285af0c6e61a6
7
+ data.tar.gz: 2660f410b9d48c4876e48fd387c69ad12707b29fef9e02ccb453331fc557c42249d0311da6f0df9eafe50e894ce23fa50c7260d2a6b4f091664ab3247b8dbcbe
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 1.1.1 - 2023-09-30
2
+ - Fixed setting of mime types from configuration. It was using default values instead of the ones set in the configuration
3
+ - Added documentation to classes and methods
4
+
1
5
  ## 1.1.0 - 2023-09-30
2
6
  - Add validation of downloaded content over path validation
3
7
  - Add ability to extend mime types from configuration
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simple-images-downloader (1.1.0)
4
+ simple-images-downloader (1.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,11 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # add documentation to this class using YARD
5
+
6
+ # Client class
7
+ # Responsible for opening the URI and handling errors
8
+ #
9
+ # @example
10
+ # SimpleImagesDownloader::Client.new.open(uri)
11
+ #
4
12
  class Client
5
13
  def initialize(options = Configuration::REQUEST_OPTIONS)
6
14
  @options = options
7
15
  end
8
16
 
17
+ # @param uri [URI] URI object
18
+ # @return [StringIO] StringIO object
9
19
  def open(uri)
10
20
  uri.open(@options)
11
21
  rescue OpenURI::HTTPRedirect
@@ -1,6 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # Configuration class
5
+ # @example
6
+ # SimpleImagesDownloader::Configuration.configure do |config|
7
+ # config.destination = './images'
8
+ # config.valid_mime_types = ['image/jpeg', 'image/png']
9
+ # end
10
+ #
11
+ # SimpleImagesDownloader::Configuration.destination
12
+ # # => './images'
13
+ #
14
+ # SimpleImagesDownloader::Configuration.valid_mime_types
15
+ # # => ['image/jpeg', 'image/png']
16
+ #
4
17
  class Configuration
5
18
  include Singleton
6
19
 
@@ -17,16 +30,16 @@ module SimpleImagesDownloader
17
30
  }.freeze
18
31
 
19
32
  # 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
33
+ DEFAULT_VALID_MIME_TYPES = [
34
+ 'image/avif',
35
+ 'image/gif',
36
+ 'image/apng',
37
+ 'image/jpg',
38
+ 'image/jpeg',
39
+ 'image/png',
40
+ 'image/svg+xml',
41
+ 'image/webp'
42
+ ].freeze
30
43
 
31
44
  DEFAULT_DESTINATION = './'
32
45
 
@@ -34,15 +47,32 @@ module SimpleImagesDownloader
34
47
 
35
48
  def initialize
36
49
  @destination = DEFAULT_DESTINATION
37
- @valid_mime_types = DEFAULT_VALID_MIME_TYPES_MAP.keys
50
+ @valid_mime_types = DEFAULT_VALID_MIME_TYPES
38
51
  end
39
52
 
53
+ # Allows to set valid_mime_types to check against allowed mime types
54
+ #
55
+ # @param value [Array] Array of valid mime types followed by
56
+ # RFC 1341 - MIME (Multipurpose Internet Mail Extensions) format
57
+ # @raise [BaseError] if value is not an Array
58
+ #
40
59
  def valid_mime_types=(value)
41
- raise BaseError, 'valid_mime_types must be an array' unless value.is_a?(Array)
60
+ raise Errors::BaseError, 'valid_mime_types must be an array' unless value.is_a?(Array)
42
61
 
43
62
  @valid_mime_types = value
44
63
  end
45
64
 
65
+ #### Configurable options
66
+ #
67
+ # destination: String, default: './', description: 'Destination folder to put downloaded images'
68
+ # valid_mime_types: Array,
69
+ # default: [
70
+ # 'image/avif', 'image/gif', 'image/apng', 'image/jpg',
71
+ # 'image/jpeg', 'image/png', 'image/svg+xml', 'image/webp'
72
+ # ], description: 'Valid mime types to download'
73
+ #
74
+ # @yield [config] Yields the Configuration object to the block
75
+ #
46
76
  def self.configure
47
77
  yield instance
48
78
  end
@@ -1,18 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # Dispenser class
5
+ # Responsible for moving tempfile to destination directory
6
+ #
7
+ # @example
8
+ # SimpleImagesDownloader::Dispenser.new(tempfile, 'https://example.com/image.jpg').place
9
+ #
4
10
  class Dispenser
5
11
  extend Forwardable
6
12
  include Validatable
7
13
 
8
14
  def_delegator 'SimpleImagesDownloader::Configuration', :destination, :destination_dir
9
15
 
16
+ # @param source [Tempfile] Tempfile object
17
+ # @param remote_path [String] original path of the image from input of SimpleImagesDownloader module
18
+ # @param validators [Array] array of validators for validating the destination directory.
19
+ # Default: [DestinationValidator.new]
10
20
  def initialize(source, remote_path, validators = [DestinationValidator.new])
11
21
  @source = source
12
22
  @remote_path = remote_path
13
23
  @validators = validators
14
24
  end
15
25
 
26
+ # Moves tempfile to destination directory
27
+ #
28
+ # @raise [Errors::BadDestination] if destination directory is not valid
29
+ # @see DestinationValidator
16
30
  def place
17
31
  validate!({ path: destination_dir })
18
32
 
@@ -1,15 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # Downloader class
5
+ # Responsible for downloading images from URI and placing them to the destination folder
6
+ # allows to use custom client and validators for downloading
7
+ #
8
+ # @example
9
+ # SimpleImagesDownloader::Downloader.new(uri).download
10
+ #
4
11
  class Downloader
5
12
  include Validatable
6
13
 
14
+ # @param uri [URI] URI object from which image will be downloaded
15
+ # @param client [Client] Client object for opening the URI. Default: Client.new
16
+ # @param validators [Array] array of validators for validating the response. Default: [MimeTypeValidator.new]
7
17
  def initialize(uri, client = Client.new, validators = [MimeTypeValidator.new])
8
18
  @uri = uri
9
19
  @client = client
10
20
  @validators = validators
11
21
  end
12
22
 
23
+ # Downloads image from URI and places it to the destination folder
24
+ #
25
+ # @raise [Errors::EmptyResponse] if response is empty
26
+ # @raise [Errors::BadMimeType] if response is not an image
27
+ # @see Errors module
28
+ # @see MimeTypeValidator
13
29
  def download
14
30
  puts "Downloading #{@uri}"
15
31
 
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # Errors module
5
+ # Responsible for storing all errors
6
+ #
4
7
  module Errors
5
8
  class BaseError < StandardError; end
6
9
 
@@ -1,11 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # Line class
5
+ # Responsible for parsing the string into URI object
6
+ #
7
+ # @example
8
+ # SimpleImagesDownloader::Line.new('https://example.com/image.jpg').uri
9
+ # # => #<URI::HTTPS https://example.com/image.jpg>
10
+ #
4
11
  class Line
5
12
  def initialize(string)
6
13
  @string = string
7
14
  end
8
15
 
16
+ # @return [URI] URI object
17
+ # @raise [Errors::BadUrl] if string is not a valid URI
18
+ # @see Errors::BadUrl
19
+ #
9
20
  def uri
10
21
  URI.parse(@string)
11
22
  rescue URI::Error
@@ -1,7 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # Runner class
5
+ # Responsible for invoking interface to download images from file
6
+ #
7
+ # @example
8
+ # SimpleImagesDownloader::Runner.invoke('./urls.txt')
9
+ #
4
10
  class Runner
11
+ # Allows to invoke interface to download images from file
5
12
  def self.invoke
6
13
  raise SimpleImagesDownloader::Errors::MissingFileArgumentError if ARGV.size.zero?
7
14
 
@@ -1,14 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # SourceFile class
5
+ # Responsible for opening the file of URLs and validating it
6
+ #
7
+ # @example
8
+ # SimpleImagesDownloader::SourceFile.new('./urls.txt').each_line do |line|
9
+ # puts line
10
+ # end
11
+ #
4
12
  class SourceFile
5
13
  include Validatable
6
14
 
15
+ # @param path [String] path to file
16
+ # @param validators [Array] array of validators
7
17
  def initialize(path, validators = [FilePersistanceValidator.new, FileAccessibilityValidator.new])
8
18
  @path = path
9
19
  @validators = validators
10
20
  end
11
21
 
22
+ # @yield [line] passes each line of file to block
23
+ # @yieldparam line [String] line of file
12
24
  def each_line(&block)
13
25
  validate!({ path: @path })
14
26
 
@@ -1,9 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # StringIOToTempfile module
5
+ # Responsible for converting StringIO to Tempfile
6
+ #
7
+ # @example
8
+ # SimpleImagesDownloader::StringioToTempfile.convert(stringio)
9
+ # # => #<Tempfile:0x00007f9b9c0b3a38>
10
+ #
4
11
  module StringioToTempfile
5
12
  module_function
6
13
 
14
+ # @param stringio [StringIO] StringIO object
15
+ # @return [Tempfile] Tempfile object
7
16
  def convert(stringio)
8
17
  tempfile = Tempfile.new(binmode: true)
9
18
 
@@ -2,7 +2,16 @@
2
2
 
3
3
  module SimpleImagesDownloader
4
4
  module Validatable
5
+ # DestinationValidator class
6
+ # Responsible for validating destination path
7
+ #
8
+ # @example
9
+ # SimpleImagesDownloader::DestinationValidator.new.validate({ path: './images' })
10
+ #
5
11
  class DestinationValidator < Validator
12
+ # @param options [Hash] hash with path to destination directory
13
+ # @raise [Errors::DestinationIsNotDirectory] if destination is not directory
14
+ # @raise [Errors::DestinationIsNotWritable] if destination is not writable
6
15
  def validate(options)
7
16
  path = options[:path]
8
17
 
@@ -2,7 +2,15 @@
2
2
 
3
3
  module SimpleImagesDownloader
4
4
  module Validatable
5
+ # FileAccessibilityValidator class
6
+ # Responsible for validating file accessibility
7
+ #
8
+ # @example
9
+ # SimpleImagesDownloader::FileAccessibilityValidator.new.validate({ path: './urls.txt' })
10
+ #
5
11
  class FileAccessibilityValidator < Validator
12
+ # @param options [Hash] hash with path to file
13
+ # @raise [Errors::PermissionsError] if file is not readable
6
14
  def validate(options)
7
15
  return if File.readable?(options[:path])
8
16
 
@@ -2,7 +2,15 @@
2
2
 
3
3
  module SimpleImagesDownloader
4
4
  module Validatable
5
+ # FilePersistanceValidator class
6
+ # Responsible for validating file persistance
7
+ #
8
+ # @example
9
+ # SimpleImagesDownloader::FilePersistanceValidator.new.validate({ path: './urls.txt' })
10
+ #
5
11
  class FilePersistanceValidator < Validator
12
+ # @param options [Hash] hash with path to file
13
+ # @raise [Errors::MissingFileError] if file does not exist
6
14
  def validate(options)
7
15
  return if File.exist?(options[:path])
8
16
 
@@ -2,25 +2,40 @@
2
2
 
3
3
  module SimpleImagesDownloader
4
4
  module Validatable
5
+ # MimeTypeValidator class
6
+ # Responsible for validating mime type of file
7
+ #
8
+ # @example
9
+ # SimpleImagesDownloader::MimeTypeValidator.new.validate({ path: './image.jpg', io: StringIO.new })
10
+ #
5
11
  class MimeTypeValidator < Validator
6
12
  extend Forwardable
7
13
 
8
14
  def_delegator 'SimpleImagesDownloader::Configuration', :valid_mime_types, :valid_mime_types
9
15
 
16
+ # Validates mime type of file. The mime types are taken from file Configuration
17
+ #
18
+ # @param options [Hash] hash with path to file and io object. Example: { path: './image.jpg', io: StringIO }
19
+ # @raise [Errors::BadMimeType] if mime type is not valid
20
+ # @see Configuration::DEFAULT_VALID_MIME_TYPES to see default valid mime types or add your own
10
21
  def validate(options)
11
22
  path = options[:path]
12
23
  io = options[:io]
13
24
 
14
25
  mime_type = mime_type_of(io)
15
26
 
16
- return if Configuration::DEFAULT_VALID_MIME_TYPES_MAP[mime_type]
27
+ return if SimpleImagesDownloader::Configuration.valid_mime_types.include?(mime_type)
17
28
 
18
29
  raise Errors::BadMimeType.new(path, mime_type)
19
30
  end
20
31
 
21
32
  private
22
33
 
23
- # Taken from Shrine https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/determine_mime_type.rb#L94
34
+ # Returns mime type of file. Uses UNIX file command
35
+ #
36
+ # @see https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/determine_mime_type.rb#L94
37
+ # @param io [IO] io object
38
+ # @return [String] mime type of file
24
39
  def mime_type_of(io)
25
40
  Open3.popen3('file --mime-type --brief -') do |stdin, stdout, stderr, thread|
26
41
  copy_stream(from: io, to: stdin.binmode)
@@ -2,6 +2,8 @@
2
2
 
3
3
  module SimpleImagesDownloader
4
4
  module Validatable
5
+ # Validator class
6
+ # Responsible for defining interface for validators
5
7
  class Validator
6
8
  def validate(_value)
7
9
  raise NotImplementedError, 'must be implemented in subclass'
@@ -1,7 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
+ # Validatable module
5
+ # Responsible for validating the object using array of validators
6
+ #
7
+ # @example
8
+ # class SourceFile
9
+ # include Validatable
10
+ #
11
+ # def initialize(path, validators = [FilePersistanceValidator.new, FileAccessibilityValidator.new])
12
+ # @path = path
13
+ # @validators = validators
14
+ # end
15
+ #
16
+ # def each_line(&block)
17
+ # validate!({ path: @path })
18
+ # # ...
19
+ # end
20
+ # end
4
21
  module Validatable
22
+ # @param value [Object] value to validate
23
+ # @raise [Errors::<Particular>Error] if value is not valid
5
24
  def validate!(value)
6
25
  (@validators ||= []).each { |validator| validator.validate(value) }
7
26
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleImagesDownloader
4
- VERSION = '1.1.0'
4
+ # gem version
5
+ VERSION = '1.1.1'
5
6
  end
@@ -25,15 +25,31 @@ require_relative 'simple_images_downloader/downloader'
25
25
  require_relative 'simple_images_downloader/strategies/from_file_strategy'
26
26
  require_relative 'simple_images_downloader/strategies/from_url_strategy'
27
27
 
28
+ # SimpleImagesDownloader module
29
+ # It is a main module of the gem
30
+ # It is responsible for providing interface to download images from file or url
31
+ #
32
+ # @example
33
+ # SimpleImagesDownloader.from_file('./urls.txt')
34
+ # SimpleImagesDownloader.from_url('https://example.com/image.jpg')
35
+ #
28
36
  module SimpleImagesDownloader
37
+ # Downloads images from file by taking urls from it. Places images to the destination folder set in configuration
38
+ #
39
+ # @param path [String] path to file with urls
29
40
  def self.from_file(path)
30
41
  SimpleImagesDownloader::Strategies::FromFileStrategy.new(path).process
31
42
  end
32
43
 
44
+ # Downloads image from url. Places image to the destination folder set in configuration
45
+ #
46
+ # @param url [String] url of image
33
47
  def self.from_url(url)
34
48
  SimpleImagesDownloader::Strategies::FromUrlStrategy.new(url).process
35
49
  end
36
50
 
51
+ # Returns root path of the gem. It is used for testing purposes
52
+ # @return [String] root path of the gem
37
53
  def self.root
38
54
  File.dirname __dir__
39
55
  end
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.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - IlkhamGaysin