filter_rename 1.1.0 → 1.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.
@@ -1,10 +1,14 @@
1
- module FilterRename
1
+ # frozen_string_literal: true
2
2
 
3
+ module FilterRename
4
+ #
5
+ # Basic file attributes translated
6
+ # to tags to be replaced.
7
+ #
3
8
  class Filename
4
-
5
9
  attr_reader :original
6
10
 
7
- def self.has_writable_tags
11
+ def self.writable_tags?
8
12
  false
9
13
  end
10
14
 
@@ -17,12 +21,12 @@ module FilterRename
17
21
  load_filename_data(fname)
18
22
  end
19
23
 
20
- def ==(dest)
21
- full_filename == dest.full_filename
24
+ def ==(other)
25
+ full_filename == other.full_filename
22
26
  end
23
27
 
24
- def !=(dest)
25
- full_filename != dest.full_filename
28
+ def !=(other)
29
+ full_filename != other.full_filename
26
30
  end
27
31
 
28
32
  def filename
@@ -42,29 +46,27 @@ module FilterRename
42
46
  end
43
47
 
44
48
  def set_string(target, str)
45
- instance_variable_set ('@' + target.to_s), str
49
+ instance_variable_set "@#{target}", str
46
50
  end
47
51
 
48
52
  def get_string(target)
49
- instance_variable_get '@' + target.to_s
53
+ instance_variable_get "@#{target}"
50
54
  end
51
55
 
52
- def has_target?(target)
53
- instance_variables.include?(('@' + target.to_s).to_sym)
56
+ def target?(target)
57
+ instance_variables.include?(:"@#{target}")
54
58
  end
55
59
 
56
60
  def exists?
57
- File.exists?(full_filename)
61
+ File.exist?(full_filename)
58
62
  end
59
63
 
60
64
  def rename!(dest)
61
65
  old_data = {}
62
66
 
63
67
  if full_filename != dest.full_filename
64
- if full_path != dest.full_path
65
- FileUtils.mkdir_p(dest.full_path) unless Dir.exists? dest.full_path
66
- end
67
- unless File.exists?(dest.full_filename)
68
+ FileUtils.mkdir_p(dest.full_path) if full_path != dest.full_path && !(Dir.exist? dest.full_path)
69
+ unless File.exist?(dest.full_filename)
68
70
  FileUtils.mv full_filename, dest.full_filename
69
71
  old_data = { full_filename: full_filename, full_path: full_path, filename: filename }
70
72
  load_filename_data(dest.full_filename)
@@ -75,7 +77,8 @@ module FilterRename
75
77
  end
76
78
 
77
79
  def calculate_hash(hash_type = :md5)
78
- raise UnknownHashCode, hash_type unless [:sha1, :sha2, :md5].include?(hash_type.to_sym)
80
+ raise UnknownHashCode, hash_type unless %i[sha1 sha2 md5].include?(hash_type.to_sym)
81
+
79
82
  klass = Object.const_get("Digest::#{hash_type.to_s.upcase}")
80
83
  klass.file(full_filename).to_s
81
84
  end
@@ -85,47 +88,50 @@ module FilterRename
85
88
  end
86
89
 
87
90
  def pretty_size(size)
88
- i = 0; size = size.to_i
89
- while ((size >= 1024) && (i < FILE_SIZES.length))
91
+ i = 0
92
+ size = size.to_i
93
+ while (size >= 1024) && (i < FILE_SIZES.length)
90
94
  size = size.to_f / 1024
91
95
  i += 1
92
96
  end
93
- size.round(2).to_s.gsub(/.0$/, '') + FILE_SIZES[i]
97
+ size.round(2).to_s.gsub(/.0$/, "") + FILE_SIZES[i]
94
98
  end
95
99
 
96
100
  def targets
97
- res = {:readonly => [], :writable => []}
101
+ res = { readonly: [], writable: [] }
98
102
  instance_variables.each do |v|
99
103
  next if v == :@cfg
100
- res[instance_variable_get(v).writable? ? :writable : :readonly] << v
104
+
105
+ res[instance_variable_get(v).writable? ? :writable : :readonly] << v.to_s.delete("@").to_sym
101
106
  end
102
107
 
103
108
  res
104
109
  end
105
110
 
106
111
  def writable?(tag)
107
- instance_variable_get("@#{tag}".to_sym).writable?
112
+ instance_variable_get(:"@#{tag}").writable?
108
113
  end
109
114
 
110
115
  def custom?(tag)
111
- instance_variable_get("@#{tag}".to_sym).custom?
116
+ instance_variable_get(:"@#{tag}").custom?
112
117
  end
113
118
 
114
119
  def values
115
120
  res = {}
116
121
  instance_variables.each do |v|
117
122
  next if v == :@cfg
118
- res[v.to_s.delete('@').to_sym] = instance_variable_get(v)
123
+
124
+ res[v.to_s.delete("@").to_sym] = instance_variable_get(v)
119
125
  end
120
126
  res
121
127
  end
122
128
 
123
129
  protected
124
130
 
125
- def metatag_to_var!(key, value, readonly = true)
126
- var_name = key.downcase.gsub(/[^a-z]/, '_').gsub(/_+/, '_')
127
- instance_variable_set('@' + var_name, value.to_s.gsub('/', '_'))
128
- instance_variable_get('@' + var_name).readonly! if readonly
131
+ def metatag_to_var!(key, value, readonly: true)
132
+ var_name = key.downcase.gsub(/[^a-z]/, "_").gsub(/_+/, "_")
133
+ instance_variable_set("@#{var_name}", value.to_s.gsub("/", "_"))
134
+ instance_variable_get("@#{var_name}").readonly! if readonly
129
135
  end
130
136
 
131
137
  private
@@ -133,23 +139,28 @@ module FilterRename
133
139
  def load_filename_data(fname)
134
140
  @ext = File.extname(fname)
135
141
  @name = File.basename(fname, @ext)
136
- @path= File.dirname(File.expand_path(fname))
142
+ @path = File.dirname(File.expand_path(fname))
137
143
  @folder = File.basename(@path)
138
144
  @path = File.dirname(@path)
139
145
 
140
146
  # read only stuff
141
- @count = @@count.to_s.rjust(@cfg.counter_length.to_i, '0')
142
- @ctime = File.ctime(fname).strftime(@cfg.date_format)
143
- @mtime = File.mtime(fname).strftime(@cfg.date_format)
144
- @size = File.size(fname).to_s
145
- @pretty_size = pretty_size(@size)
147
+ @count = @@count.to_s.rjust(@cfg.counter_length.to_i, "0")
148
+
149
+ if @cfg.essential_tags
150
+ @count.readonly!
151
+ [@ext, @name, @path, @folder, @path, @count, @original].map(&:basic!)
152
+ else
153
+ @ctime = File.ctime(fname).strftime(@cfg.date_format)
154
+ @mtime = File.mtime(fname).strftime(@cfg.date_format)
155
+ @size = File.size(fname).to_s
156
+ @pretty_size = pretty_size(@size)
146
157
 
147
- [@count, @ctime, @mtime, @size, @pretty_size].map(&:readonly!)
158
+ [@count, @ctime, @mtime, @size, @pretty_size].map(&:readonly!)
148
159
 
149
- [@ext, @name, @path, @folder, @path, @count, @ctime, @size, @pretty_size].map(&:basic!)
160
+ [@ext, @name, @path, @folder, @path, @count, @ctime, @size, @pretty_size, @original].map(&:basic!)
150
161
 
151
- metatag_to_var!('hash', calculate_hash(@cfg.hash_type), true) if @cfg.hash_on_tags
162
+ metatag_to_var!("hash", calculate_hash(@cfg.hash_type), readonly: true) if @cfg.hash_on_tags
163
+ end
152
164
  end
153
165
  end
154
-
155
166
  end
@@ -1,28 +1,35 @@
1
- require 'mimemagic'
2
- require 'fileutils'
3
- require 'differ'
4
- require 'digest'
1
+ # frozen_string_literal: true
5
2
 
6
- module FilterRename
3
+ require "mimemagic"
4
+ require "fileutils"
5
+ require "differ"
6
+ require "digest"
7
7
 
8
+ module FilterRename
9
+ #
10
+ # Factory class that returns the
11
+ # related file handler depending
12
+ # from its file type.
13
+ #
8
14
  class FilenameFactory
9
-
10
15
  def self.create(fname, cfg)
11
-
12
- return Filename.new(fname, cfg) if File.directory?(fname)
16
+ return Filename.new(fname, cfg) if File.directory?(fname) || !cfg.mimemagic
13
17
 
14
18
  magic = MimeMagic.by_magic(File.open(fname))
15
- mediatype, type = magic.nil? ? ['unknown', 'unknown'] : [magic.mediatype, magic.type]
19
+ mediatype, type, subtype = magic.nil? ? %w[unknown unknown unknown] : [magic.mediatype, magic.type, magic.subtype]
16
20
 
17
- if (IO.read(fname, 3) == 'ID3') && (mediatype == 'audio')
18
- require 'filter_rename/filetype/mp3_filename'
21
+ if (File.read(fname, 3) == "ID3") && (mediatype == "audio")
22
+ require "filter_rename/filetype/mp3_filename"
19
23
  res = Mp3Filename.new(fname, cfg)
20
- elsif ((mediatype == 'image') && (! ['vnd.djvu+multipage'].include? type.split('/')[1]))
24
+ elsif ((mediatype == "audio") && (subtype == "mp4")) || (%w[flac ogg].include? subtype)
25
+ require "filter_rename/filetype/audio_filename"
26
+ res = AudioFilename.new(fname, cfg)
27
+ elsif (mediatype == "image") && (!["vnd.djvu+multipage"].include? type.split("/")[1])
21
28
  # supported types: jpeg, png
22
- require 'filter_rename/filetype/image_filename'
29
+ require "filter_rename/filetype/image_filename"
23
30
  res = ImageFilename.new(fname, cfg)
24
- elsif (type == 'application/pdf')
25
- require 'filter_rename/filetype/pdf_filename'
31
+ elsif type == "application/pdf"
32
+ require "filter_rename/filetype/pdf_filename"
26
33
  res = PdfFilename.new(fname, cfg)
27
34
  else
28
35
  res = Filename.new(fname, cfg)
@@ -30,7 +37,5 @@ module FilterRename
30
37
 
31
38
  res
32
39
  end
33
-
34
40
  end
35
-
36
41
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "taglib"
4
+
5
+ module FilterRename
6
+ #
7
+ # Mp3 files tags handling.
8
+ #
9
+ class AudioFilename < Filename
10
+ def self.writable_tags?
11
+ true
12
+ end
13
+
14
+ def initialize(fname, cfg)
15
+ super
16
+
17
+ load_audio_data(fname) if cfg.audio_metadata
18
+ end
19
+
20
+ def ==(other)
21
+ super &&
22
+ ([@title, @artist, @album, @track, @comment, @year, @genre] ==
23
+ [other.get_string(:title), other.get_string(:artist), other.get_string(:album), other.get_string(:track),
24
+ other.get_string(:comment), other.get_string(:year), other.get_string(:genre)])
25
+ end
26
+
27
+ def rename!(dest)
28
+ old_data = super
29
+
30
+ TagLib::FileRef.open(full_filename) do |audio|
31
+ old_data.merge!({ title: audio.tag.title, artist: audio.tag.artist, album: audio.tag.album,
32
+ track: audio.tag.track, comment: audio.tag.comment, year: audio.tag.year,
33
+ genre: audio.tag.genre })
34
+
35
+ audio.tag.title = dest.get_string(:title)
36
+ audio.tag.artist = dest.get_string(:artist)
37
+ audio.tag.album = dest.get_string(:album)
38
+ audio.tag.track = dest.get_string(:track)
39
+ audio.tag.comment = dest.get_string(:comment).to_s
40
+ audio.tag.year = dest.get_string(:year)
41
+ audio.tag.genre = dest.get_string(:genre)
42
+
43
+ audio.save
44
+ end
45
+
46
+ load_audio_data(full_filename)
47
+
48
+ old_data
49
+ end
50
+
51
+ def diff(dest)
52
+ super + "
53
+ Title: #{Differ.diff_by_word(dest.get_string(:title).to_s, @title.to_s)}
54
+ Artist: #{Differ.diff_by_word(dest.get_string(:artist).to_s, @artist.to_s)}
55
+ Album: #{Differ.diff_by_word(dest.get_string(:album).to_s, @album.to_s)}
56
+ Track: #{Differ.diff_by_word(dest.get_string(:track).to_s, @track.to_s)}
57
+ Comments: #{Differ.diff_by_word(dest.get_string(:comment).to_s, @comment.to_s)}
58
+ Year: #{Differ.diff_by_word(dest.get_string(:year).to_s, @year.to_s)}
59
+ Genre: #{Differ.diff_by_word(dest.get_string(:genre).to_s, @genre.to_s)}
60
+ "
61
+ end
62
+
63
+ private
64
+
65
+ def load_audio_data(fname)
66
+ audioinfo = TagLib::FileRef.new(fname, true, TagLib::AudioProperties::Average)
67
+ @title = audioinfo.tag.title.to_s
68
+ @artist = audioinfo.tag.artist.to_s
69
+ @album = audioinfo.tag.album.to_s
70
+ @track = audioinfo.tag.track.to_i
71
+ @comment = audioinfo.tag.comment.to_s
72
+ @year = audioinfo.tag.year.to_i
73
+ @genre = audioinfo.tag.genre.to_s
74
+
75
+ # read only stuff
76
+ @duration = audioinfo.audio_properties.length_in_seconds.to_s
77
+ @hduration = format "%<h>dh%<m>dm%<s>2ds", { h: @duration.to_i / 3600,
78
+ m: @duration.to_i / 60 % 60,
79
+ s: @duration.to_i % 60 }
80
+ @samplerate = audioinfo.audio_properties.sample_rate.to_s
81
+ @bitrate = audioinfo.audio_properties.bitrate.to_s
82
+
83
+ [@duration, @hduration, @samplerate, @bitrate].map(&:readonly!)
84
+ end
85
+ end
86
+ end
@@ -1,12 +1,15 @@
1
- require 'fastimage'
2
- require 'exiv2'
1
+ # frozen_string_literal: true
3
2
 
4
- module FilterRename
3
+ require "fastimage"
4
+ require "exiv2"
5
5
 
6
+ module FilterRename
7
+ #
8
+ # Image files tags handling.
9
+ #
6
10
  class ImageFilename < Filename
7
-
8
11
  def initialize(fname, cfg)
9
- super fname, cfg
12
+ super
10
13
 
11
14
  image = FastImage.new(fname)
12
15
  @width = image.size[0].to_s
@@ -14,15 +17,18 @@ module FilterRename
14
17
 
15
18
  [@width, @height].map(&:readonly!)
16
19
 
17
- if cfg.image_metadata
18
- image = Exiv2::ImageFactory.open(fname)
19
- image.read_metadata
20
+ load_image_data(fname) if cfg.image_metadata
21
+ end
20
22
 
21
- image.exif_data.each do |key, value|
22
- metadata_to_var!(key, value, true)
23
- end unless image.exif_data.nil?
23
+ def load_image_data(fname)
24
+ image = Exiv2::ImageFactory.open(fname)
25
+ image.read_metadata
26
+
27
+ return if image.exif_data.nil?
28
+
29
+ image.exif_data.each do |key, value|
30
+ metadata_to_var!(key, value, true)
24
31
  end
25
32
  end
26
33
  end
27
-
28
34
  end
@@ -1,28 +1,31 @@
1
- require 'mp3info'
1
+ # frozen_string_literal: true
2
2
 
3
- module FilterRename
3
+ require "mp3info"
4
4
 
5
+ module FilterRename
6
+ #
7
+ # Mp3 files tags handling.
8
+ #
5
9
  class Mp3Filename < Filename
6
-
7
- def self.has_writable_tags
10
+ def self.writable_tags?
8
11
  true
9
12
  end
10
13
 
11
14
  def initialize(fname, cfg)
12
- super fname, cfg
15
+ super
13
16
 
14
- load_mp3_data(fname)
17
+ load_mp3_data(fname) if cfg.audio_metadata
15
18
  end
16
19
 
17
- def ==(dest)
20
+ def ==(other)
18
21
  super &&
19
- ([ @title, @artist, @album, @track, @comments, @year, @genre, @genre_s ] ==
20
- [ dest.get_string(:title), dest.get_string(:artist), dest.get_string(:album), dest.get_string(:track),
21
- dest.get_string(:comments), dest.get_string(:year), dest.get_string(:genre), dest.get_string(:genre_s) ])
22
+ ([@title, @artist, @album, @track, @comments, @year, @genre, @genre_s] ==
23
+ [other.get_string(:title), other.get_string(:artist), other.get_string(:album), other.get_string(:track),
24
+ other.get_string(:comments), other.get_string(:year), other.get_string(:genre), other.get_string(:genre_s)])
22
25
  end
23
26
 
24
27
  def rename!(dest)
25
- old_data = super dest
28
+ old_data = super
26
29
 
27
30
  Mp3Info.open(full_filename) do |mp3|
28
31
  old_data.merge!({ title: mp3.tag.title, artist: mp3.tag.artist, album: mp3.tag.album,
@@ -35,7 +38,7 @@ module FilterRename
35
38
  mp3.tag.tracknum = dest.get_string(:track)
36
39
  mp3.tag.comments = dest.get_string(:comments).to_s
37
40
  mp3.tag.year = dest.get_string(:year)
38
- mp3.tag.genre = dest.get_string(:genre).to_i % 256
41
+ mp3.tag.genre = dest.get_string(:genre).to_i % 256
39
42
  mp3.tag.genre_s = dest.get_string(:genre_s)
40
43
  end
41
44
 
@@ -45,7 +48,7 @@ module FilterRename
45
48
  end
46
49
 
47
50
  def diff(dest)
48
- super(dest) + "
51
+ super + "
49
52
  Title: #{Differ.diff_by_word(dest.get_string(:title).to_s, @title.to_s)}
50
53
  Artist: #{Differ.diff_by_word(dest.get_string(:artist).to_s, @artist.to_s)}
51
54
  Album: #{Differ.diff_by_word(dest.get_string(:album).to_s, @album.to_s)}
@@ -57,7 +60,6 @@ module FilterRename
57
60
  "
58
61
  end
59
62
 
60
-
61
63
  private
62
64
 
63
65
  def load_mp3_data(fname)
@@ -69,16 +71,14 @@ module FilterRename
69
71
  @comments = mp3info.tag.comments.to_s
70
72
  @year = mp3info.tag.year.to_i
71
73
  @genre = mp3info.tag.genre.to_i
72
- @genre_s = mp3info.tag.genre_s.to_s
74
+ @genre_s = mp3info.tag.genre_s.to_s
73
75
 
74
76
  # read only stuff
75
- @vbr = (mp3info.tag.vbr ? 'vbr' : '')
77
+ @vbr = (mp3info.tag.vbr ? "vbr" : "").dup
76
78
  @samplerate = mp3info.samplerate.to_s
77
79
  @bitrate = mp3info.bitrate.to_s
78
80
 
79
81
  [@vbr, @samplerate, @bitrate].map(&:readonly!)
80
82
  end
81
-
82
83
  end
83
-
84
84
  end
@@ -1,24 +1,31 @@
1
- require 'pdf-reader'
1
+ # frozen_string_literal: true
2
2
 
3
- module FilterRename
3
+ require "pdf-reader"
4
4
 
5
+ module FilterRename
6
+ #
7
+ # Pdf files tags handling.
8
+ #
5
9
  class PdfFilename < Filename
6
-
7
10
  def initialize(fname, cfg)
8
- super fname, cfg
11
+ super
9
12
 
10
- if cfg.pdf_metadata
13
+ load_pdf_data(fname) if cfg.pdf_metadata
14
+ end
11
15
 
12
- pdfinfo = PDF::Reader.new(fname)
16
+ private
13
17
 
14
- @page_count = pdfinfo.page_count.to_s
15
- @page_count.readonly!
18
+ def load_pdf_data(fname)
19
+ pdfinfo = PDF::Reader.new(fname)
16
20
 
17
- pdfinfo.info.each do |key, value|
18
- metatag_to_var!(key.to_s.gsub(/([A-Z])([^A-Z]+)/, '\1\2 ').strip, value, true)
19
- end unless pdfinfo.info.nil?
21
+ @page_count = pdfinfo.page_count.to_s
22
+ @page_count.readonly!
23
+
24
+ return if pdfinfo.info.nil?
25
+
26
+ pdfinfo.info.each do |key, value|
27
+ metatag_to_var!(key.to_s.gsub(/([A-Z])([^A-Z]+)/, '\1\2 ').strip, value, readonly: true)
20
28
  end
21
29
  end
22
30
  end
23
-
24
31
  end