filter_rename 1.0.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,8 +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
9
+ attr_reader :original
4
10
 
5
- def self.has_writable_tags
11
+ def self.writable_tags?
6
12
  false
7
13
  end
8
14
 
@@ -11,15 +17,16 @@ module FilterRename
11
17
  @@count += 1
12
18
  @cfg = cfg
13
19
 
20
+ @original = fname
14
21
  load_filename_data(fname)
15
22
  end
16
23
 
17
- def ==(dest)
18
- full_filename == dest.full_filename
24
+ def ==(other)
25
+ full_filename == other.full_filename
19
26
  end
20
27
 
21
- def !=(dest)
22
- full_filename != dest.full_filename
28
+ def !=(other)
29
+ full_filename != other.full_filename
23
30
  end
24
31
 
25
32
  def filename
@@ -39,29 +46,27 @@ module FilterRename
39
46
  end
40
47
 
41
48
  def set_string(target, str)
42
- instance_variable_set ('@' + target.to_s), str
49
+ instance_variable_set "@#{target}", str
43
50
  end
44
51
 
45
52
  def get_string(target)
46
- instance_variable_get '@' + target.to_s
53
+ instance_variable_get "@#{target}"
47
54
  end
48
55
 
49
- def has_target?(target)
50
- instance_variables.include?(('@' + target.to_s).to_sym)
56
+ def target?(target)
57
+ instance_variables.include?(:"@#{target}")
51
58
  end
52
59
 
53
60
  def exists?
54
- File.exists?(full_filename)
61
+ File.exist?(full_filename)
55
62
  end
56
63
 
57
64
  def rename!(dest)
58
65
  old_data = {}
59
66
 
60
67
  if full_filename != dest.full_filename
61
- if full_path != dest.full_path
62
- FileUtils.mkdir_p(dest.full_path) unless Dir.exists? dest.full_path
63
- end
64
- 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)
65
70
  FileUtils.mv full_filename, dest.full_filename
66
71
  old_data = { full_filename: full_filename, full_path: full_path, filename: filename }
67
72
  load_filename_data(dest.full_filename)
@@ -72,7 +77,8 @@ module FilterRename
72
77
  end
73
78
 
74
79
  def calculate_hash(hash_type = :md5)
75
- 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
+
76
82
  klass = Object.const_get("Digest::#{hash_type.to_s.upcase}")
77
83
  klass.file(full_filename).to_s
78
84
  end
@@ -82,39 +88,50 @@ module FilterRename
82
88
  end
83
89
 
84
90
  def pretty_size(size)
85
- i = 0; size = size.to_i
86
- while ((size >= 1024) && (i < FILE_SIZES.length))
91
+ i = 0
92
+ size = size.to_i
93
+ while (size >= 1024) && (i < FILE_SIZES.length)
87
94
  size = size.to_f / 1024
88
95
  i += 1
89
96
  end
90
- size.round(2).to_s.gsub(/.0$/, '') + FILE_SIZES[i]
97
+ size.round(2).to_s.gsub(/.0$/, "") + FILE_SIZES[i]
91
98
  end
92
99
 
93
100
  def targets
94
- res = {:readonly => [], :writable => []}
101
+ res = { readonly: [], writable: [] }
95
102
  instance_variables.each do |v|
96
103
  next if v == :@cfg
97
- 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
98
106
  end
99
107
 
100
108
  res
101
109
  end
102
110
 
111
+ def writable?(tag)
112
+ instance_variable_get(:"@#{tag}").writable?
113
+ end
114
+
115
+ def custom?(tag)
116
+ instance_variable_get(:"@#{tag}").custom?
117
+ end
118
+
103
119
  def values
104
120
  res = {}
105
121
  instance_variables.each do |v|
106
122
  next if v == :@cfg
107
- res[v.to_s.delete('@').to_sym] = instance_variable_get(v)
123
+
124
+ res[v.to_s.delete("@").to_sym] = instance_variable_get(v)
108
125
  end
109
126
  res
110
127
  end
111
128
 
112
129
  protected
113
130
 
114
- def metatag_to_var!(key, value, readonly = true)
115
- var_name = key.downcase.gsub(/[^a-z]/, '_').gsub(/_+/, '_')
116
- instance_variable_set('@' + var_name, value.to_s.gsub('/', '_'))
117
- 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
118
135
  end
119
136
 
120
137
  private
@@ -122,21 +139,28 @@ module FilterRename
122
139
  def load_filename_data(fname)
123
140
  @ext = File.extname(fname)
124
141
  @name = File.basename(fname, @ext)
125
- @path= File.dirname(File.expand_path(fname))
142
+ @path = File.dirname(File.expand_path(fname))
126
143
  @folder = File.basename(@path)
127
144
  @path = File.dirname(@path)
128
145
 
129
146
  # read only stuff
130
- @count = @@count.to_s.rjust(@cfg.counter_length.to_i, '0')
131
- @ctime = File.ctime(fname).strftime(@cfg.date_format)
132
- @mtime = File.mtime(fname).strftime(@cfg.date_format)
133
- @size = File.size(fname).to_s
134
- @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)
135
157
 
136
- [@count, @ctime, @mtime, @size, @pretty_size].map(&:readonly!)
158
+ [@count, @ctime, @mtime, @size, @pretty_size].map(&:readonly!)
137
159
 
138
- metatag_to_var!('hash', calculate_hash(@cfg.hash_type), true) unless @cfg.hash_type == :none
160
+ [@ext, @name, @path, @folder, @path, @count, @ctime, @size, @pretty_size, @original].map(&:basic!)
161
+
162
+ metatag_to_var!("hash", calculate_hash(@cfg.hash_type), readonly: true) if @cfg.hash_on_tags
163
+ end
139
164
  end
140
165
  end
141
-
142
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,33 +1,36 @@
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 ] ==
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) ])
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,
29
- tracknum: mp3.tag.tracknum, comments: mp3.tag.comments, year: mp3.tag.year,
30
- genre_s: mp3.tag.genre_s })
32
+ track: mp3.tag.tracknum, comments: mp3.tag.comments, year: mp3.tag.year,
33
+ genre: mp3.tag.genre, genre_s: mp3.tag.genre_s })
31
34
 
32
35
  mp3.tag.title = dest.get_string(:title)
33
36
  mp3.tag.artist = dest.get_string(:artist)
@@ -35,8 +38,8 @@ 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_s = dest.get_string(:genre)
39
-
41
+ mp3.tag.genre = dest.get_string(:genre).to_i % 256
42
+ mp3.tag.genre_s = dest.get_string(:genre_s)
40
43
  end
41
44
 
42
45
  load_mp3_data(full_filename)
@@ -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)}
@@ -53,10 +56,10 @@ module FilterRename
53
56
  Comments: #{Differ.diff_by_word(dest.get_string(:comments).to_s, @comments.to_s)}
54
57
  Year: #{Differ.diff_by_word(dest.get_string(:year).to_s, @year.to_s)}
55
58
  Genre: #{Differ.diff_by_word(dest.get_string(:genre).to_s, @genre.to_s)}
59
+ GenreS: #{Differ.diff_by_word(dest.get_string(:genre_s).to_s, @genre_s.to_s)}
56
60
  "
57
61
  end
58
62
 
59
-
60
63
  private
61
64
 
62
65
  def load_mp3_data(fname)
@@ -67,16 +70,15 @@ module FilterRename
67
70
  @track = mp3info.tag.tracknum.to_i
68
71
  @comments = mp3info.tag.comments.to_s
69
72
  @year = mp3info.tag.year.to_i
70
- @genre = mp3info.tag.genre_s.to_s
73
+ @genre = mp3info.tag.genre.to_i
74
+ @genre_s = mp3info.tag.genre_s.to_s
71
75
 
72
76
  # read only stuff
73
- @vbr = (mp3info.tag.vbr ? 'vbr' : '')
77
+ @vbr = (mp3info.tag.vbr ? "vbr" : "").dup
74
78
  @samplerate = mp3info.samplerate.to_s
75
79
  @bitrate = mp3info.bitrate.to_s
76
80
 
77
81
  [@vbr, @samplerate, @bitrate].map(&:readonly!)
78
82
  end
79
-
80
83
  end
81
-
82
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