plexify 0.1.1 → 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.
data/Gemfile CHANGED
@@ -5,5 +5,7 @@ gemspec
5
5
 
6
6
  gem "ruby-tmdb", ">= 0.2.1"
7
7
  gem "colorize", ">= 0.5.8"
8
- gem "text", ">= 1.2.1"
9
8
  gem "ruby-progressbar", ">= 1.0.2"
9
+ gem "debugger", ">= 1.2.2"
10
+ gem "rspec", ">= 2.12.0"
11
+ gem "amatch", ">= 0.2.10"
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # Plexify
2
2
 
3
- Currently in development. Not working yet.
3
+ Plexify is a file organizer tool to manage medias. It analyses files and search for movies in TheMovieDB to have
4
+ informations about them and create good folder names and add some additional stuffs like posters, desriptions
5
+ (these two lasts aren't supported yet, but will be ;))
4
6
 
5
- TODO: Write a gem description
6
7
 
7
8
  ## Installation
8
9
 
@@ -18,14 +19,36 @@ Or install it yourself as:
18
19
 
19
20
  $ gem install plexify
20
21
 
22
+ ## Ruby
23
+
24
+ Plexify is compatible with
25
+
26
+ ruby 1.9.3
27
+
21
28
  ## Usage
22
29
 
23
- TODO: Write usage instructions here
30
+ Plexify analyses files and move them to an oranized folder, so it creates destination folders and media folders.
31
+
32
+ The default usage is:
33
+
34
+ $ plexify -s /media/Temp -d /media/PlexMediaFolder
35
+
36
+ or more simple
37
+
38
+ $ plexify /media/Temp /media/PlexMediaFolder
39
+
40
+ If you specify a destination with the -d flag, it will create two folders inside the destination folder named "Movies" and "TV_Shows".
41
+
42
+ You can also specify movies and series folders like that:
43
+
44
+ $ plexify -s /media/Temp --movies-destination /media/PlexMediaFolder/Movies --series-destination /media/PlexMediaFolder/Series
45
+
46
+ If you aren't really sure about the tool, you can either use plexify in test mode like that:
47
+
48
+ $ plexify -s /media/Temp -d /media/PlexMediaFolder --test
49
+
50
+ It will just print found medias and not move files.
24
51
 
25
- ## Contributing
52
+ ## Contributors
26
53
 
27
- 1. Fork it
28
- 2. Create your feature branch (`git checkout -b my-new-feature`)
29
- 3. Commit your changes (`git commit -am 'Add some feature'`)
30
- 4. Push to the branch (`git push origin my-new-feature`)
31
- 5. Create new Pull Request
54
+ 1. Pierre FILSTROFF ([reaper](https://github.com/reaper/))
data/Rakefile CHANGED
@@ -1 +1,3 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new('spec')
data/lib/plexify.rb CHANGED
@@ -5,19 +5,23 @@ require 'optparse'
5
5
  require 'colorize'
6
6
  require 'ruby-tmdb'
7
7
  require 'yaml'
8
- require 'text'
8
+ require 'amatch'
9
9
 
10
10
  Dir[File.dirname(__FILE__) + "/plexify/**/*"].each{ |file| require file }
11
11
 
12
12
  module Plexify
13
- class Plexify
14
- def initialize(args)
15
- @opts = Execute::Plexify.new(args)
16
- end
13
+ class Plexify
14
+ def initialize(args)
15
+ @opts = Execute::Plexify.new(args)
16
+ end
17
17
 
18
- # Run plexify !
19
- def run!
20
- @opts.parse!
21
- end
18
+ # Run plexify !
19
+ def run!
20
+ @opts.parse!
22
21
  end
22
+ end
23
+
24
+ def self.version
25
+ return "Plexify version #{VERSION}"
26
+ end
23
27
  end
@@ -1,170 +1,180 @@
1
1
  module Plexify
2
- module Execute
3
- class Plexify
4
- # Plexify::Execute initialize method
5
- def initialize(args)
6
- @args = args
7
- @options = {}
8
- @missing_args = []
2
+ module Execute
3
+ class Plexify
4
+ # Plexify::Execute initialize method
5
+ def initialize(args)
6
+ @args = args
7
+ @options = {}
8
+ @missing_args = []
9
+ end
10
+
11
+ # Parses the command-line arguments and execute files processing
12
+ def parse!
13
+ begin
14
+ @opts = OptionParser.new(&method(:set_opts))
15
+ @opts.parse!(@args)
16
+ check_arguments
17
+
18
+ if @args.any?
19
+ @options[:source] = @args[0] unless @options[:source]
20
+ @options[:destination] = @args[1] if @args[1] && !@options[:destination]
21
+ end
22
+
23
+ process_result
24
+
25
+ # Puts missing arguments
26
+ rescue OptionParser::MissingArgument => e
27
+ built_string = e.message
28
+ for arg in @missing_args
29
+ built_string += arg
30
+ unless @missing_args.last == arg
31
+ built_string += ", "
32
+ else
33
+ built_string += "\n\n"
9
34
  end
35
+ end
36
+ puts built_string
37
+ puts @opts
10
38
 
11
- # Parses the command-line arguments and execute files processing
12
- def parse!
13
- begin
14
- @opts = OptionParser.new(&method(:set_opts))
15
- @opts.parse!(@args)
16
- check_arguments
17
-
18
- if @args.any?
19
- @options[:source] = @args[0] unless @options[:source]
20
- @options[:destination] = @args[1] unless @options[:destination]
21
- end
22
-
23
- process_result
24
-
25
- # Puts missing arguments
26
- rescue OptionParser::MissingArgument => e
27
- built_string = e.message
28
- for arg in @missing_args
29
- built_string += arg
30
- unless @missing_args.last == arg
31
- built_string += ", "
32
- else
33
- built_string += "\n\n"
34
- end
35
- end
36
- puts built_string
37
- puts @opts
38
-
39
- # Puts exception message
40
- rescue Exception => e
41
- raise e if @options[:trace] || e.is_a?(SystemExit)
42
-
43
- print "\n#{e.class}: " unless e.class == RuntimeError
44
- puts "#{e.message}"
45
- puts " Use --trace for backtrace."
46
- end
47
- exit 0
48
- end
39
+ # Puts exception message
40
+ rescue Exception => e
41
+ raise e if @options[:trace] || e.is_a?(SystemExit)
49
42
 
50
- private
51
- # Check missing arguments
52
- def check_arguments
53
- return if @args.size == 2
43
+ print "\n#{e.class}: " unless e.class == RuntimeError
44
+ puts "#{e.message}"
45
+ puts " Use --trace for backtrace."
46
+ end
47
+ exit 0
48
+ end
54
49
 
55
- @missing_args << "-s [source]" if !@options[:source] && !@args[0]
56
- @missing_args << "-d [destination]" if !@options[:destination] && !@options[:movies_destination] && !@options[:series_destination]
57
- @missing_args << "--movies-destination [destination]" if !@options[:destination] && !@options[:movies_destination] && !@options[:series_destination]
58
- @missing_args << "--series-destination [destination]" if !@options[:destination] && !@options[:series_destination] && !@options[:movies_destination]
50
+ private
51
+ # Check missing arguments
52
+ def check_arguments
53
+ return if @args.size == 2
59
54
 
60
- if @missing_args.any?
61
- raise OptionParser::MissingArgument
62
- end
63
- end
55
+ @missing_args << "-s [source]" if !@options[:source] && !@args[0]
56
+ @missing_args << "-d [destination]" if !@options[:test] && !@options[:destination] && !@options[:movies_destination] && !@options[:series_destination]
57
+ @missing_args << "--movies-destination [destination]" if !@options[:test] && !@options[:destination] && !@options[:movies_destination] && !@options[:series_destination]
58
+ @missing_args << "--series-destination [destination]" if !@options[:test] && !@options[:destination] && !@options[:series_destination] && !@options[:movies_destination]
64
59
 
65
- # Set options definition for command-line execution
66
- def set_opts(opts)
67
- opts.banner = "Usage: plexify -s /media/temp --movies-destination /media/Movies --series-destination /media/Series\n\n"
60
+ if @missing_args.any?
61
+ raise OptionParser::MissingArgument
62
+ end
63
+ end
68
64
 
69
- opts.on('-s [source]', '--source [source]', 'Source folder which includes media files. Temp folder.') do |source|
70
- @options[:source] = source
71
- end
65
+ # Set options definition for command-line execution
66
+ def set_opts(opts)
67
+ opts.banner = "Usage: plexify -s /media/temp --movies-destination /media/Movies --series-destination /media/Series\n\n"
72
68
 
73
- opts.on('-d [destination]', '--destination [dest]', 'Destination folder to put organized.') do |destination|
74
- @options[:destination] = destination
75
- end
69
+ opts.on('-s [source]', '--source [source]', 'Source folder which includes media files. Temp folder.') do |source|
70
+ @options[:source] = source
71
+ end
76
72
 
77
- opts.on('--movies-destination [dest]', 'Destination folder to put organized movies files.') do |movies_destination|
78
- @options[:movies_destination] = movies_destination
79
- end
73
+ opts.on('-d [destination]', '--destination [dest]', 'Destination folder to put organized.') do |destination|
74
+ @options[:destination] = destination
75
+ end
80
76
 
81
- opts.on('--series-destination [dest]', 'Destination folder to put organized series files.') do |series_destination|
82
- @options[:series_destination] = series_destination
83
- end
77
+ opts.on('--movies-destination [dest]', 'Destination folder to put organized movies files.') do |movies_destination|
78
+ @options[:movies_destination] = movies_destination
79
+ end
84
80
 
85
- opts.on_tail('-t', '--test', 'Test files name searching in media databases: only print results.') do
86
- @options[:test] = true
87
- end
81
+ opts.on('--series-destination [dest]', 'Destination folder to put organized series files.') do |series_destination|
82
+ @options[:series_destination] = series_destination
83
+ end
88
84
 
89
- opts.on_tail('--accept-removing-all', :NONE, 'Accept removing source files. [NOT WORKING YET]') do
90
- @options[:accept_removing_all] = true
91
- end
85
+ opts.on_tail('-t', '--test', 'Test files name searching in media databases: only print results.') do
86
+ @options[:test] = true
87
+ end
92
88
 
93
- opts.on_tail("-?", "-h", "--help", "Show this message.") do
94
- puts opts
95
- exit
96
- end
89
+ opts.on_tail('--accept-removing-all', :NONE, 'Accept removing source files. [NOT WORKING YET]') do
90
+ @options[:accept_removing_all] = true
91
+ end
97
92
 
98
- opts.on_tail("-v", "--version", "Print version") do
99
- puts("Plexify #{VERSION}")
100
- exit
101
- end
102
-
103
- opts.on_tail('--trace', :NONE, 'Show a full traceback on error') do
104
- @options[:trace] = true
105
- end
106
- end
93
+ opts.on_tail("-?", "-h", "--help", "Show this message.") do
94
+ puts opts
95
+ exit
96
+ end
97
+
98
+ opts.on_tail("-v", "--version", "Print version") do
99
+ puts("Plexify #{VERSION}")
100
+ exit
101
+ end
107
102
 
108
- # Process result
109
- def process_result
103
+ opts.on_tail('--trace', :NONE, 'Show a full traceback on error') do
104
+ @options[:trace] = true
105
+ end
106
+ end
110
107
 
111
- Logger.info("=> Preparing source folder")
112
- source = Prepare::Source.new(@options)
113
- source.prepare
114
- Logger.info(" : #{source.files.size} #{source.files.size > 1 ? 'files' : 'file'} found")
108
+ # Process result
109
+ def process_result
115
110
 
116
- unless @options[:test]
117
- Logger.info("\n=> Preparing destination folder")
118
- destination = Prepare::Destination.new(@options)
119
- destination.prepare
120
- end
111
+ Logger.info("=> Preparing source folder")
112
+ source = Prepare::Source.new(@options)
113
+ source.prepare
114
+ Logger.info(" : #{source.files.size} #{source.files.size > 1 ? 'files' : 'file'} found")
115
+
116
+ unless @options[:test]
117
+ Logger.info("\n=> Preparing destination folder")
118
+ destination = Prepare::Destination.new(@options)
119
+ destination.prepare
120
+ end
121
121
 
122
- media_manager = MediaManager.new
123
- media_organizer = MediaOrganizer.new(source, destination) unless @options[:test]
124
-
125
- files_processed_count = 0
126
-
127
- # Process files
128
- for file in source.files
129
- basename = File.basename(file.path)
130
- Logger.info("\n\n=> Analyzing '#{basename}' file...")
131
- medias = media_manager.analyze(file)
132
-
133
- # Choose the good media
134
- if medias.any?
135
- Logger.info("\nFound medias :")
136
-
137
- # If the test argument is present, don't move files or prompt the user
138
- if @options[:test]
139
- for media in medias
140
- Logger.success("\n#{media.data.name} #{media.data.released ? "(#{Date.parse(media.data.released).year})" : nil}")
141
- end
142
- else
143
- Logger.success("\n0: The movie isn't in the list, go next without doing anything.")
144
- medias.each_with_index do |media, index|
145
- Logger.success("\n#{index+1}: #{media.data.name} #{media.data.released ? "(#{Date.parse(media.data.released).year})" : nil}")
146
- end
147
-
148
- Logger.success("\nChoose the movie: ")
149
- resp = STDIN.gets.chomp.to_i-1
150
-
151
- if resp >= 0 && resp <= medias.size
152
- media = medias[resp]
153
- Logger.success("\nMedia found : #{media.data.name} #{media.data.released ? "(#{Date.parse(media.data.released).year})" : nil}")
154
- media_organizer.move_to_destination(file, media)
155
- files_processed_count += 1
156
- elsif resp == -1
157
- Logger.info("Aborting...")
158
- next
159
- end
160
- end
161
- else
162
- Logger.error("\nMedia not found")
163
- end
122
+ media_manager = MediaManager.new
123
+ media_organizer = MediaOrganizer.new(source, destination) unless @options[:test]
124
+
125
+ files_processed_count = 0
126
+
127
+ # Process files
128
+ for file in source.files
129
+ basename = File.basename(file.path)
130
+ Logger.info("\n\n=> Analyzing '#{basename}' file...")
131
+ medias = media_manager.analyze(file)
132
+
133
+ # Choose the good media
134
+ if medias.any?
135
+
136
+ # If the test argument is present, don't move files or prompt the user
137
+ if @options[:test]
138
+ Logger.info("\nFound medias :")
139
+
140
+ for media in medias
141
+ Logger.success("\n#{media.data.name} #{media.data.released ? "(#{Date.parse(media.data.released).year})" : nil}")
142
+ end
143
+ else
144
+ Logger.success("\nThe movie is '#{medias.first.data.name} #{medias.first.data.released ? "(#{Date.parse(medias.first.data.released).year})" : nil}'. Right ? (y/n) ")
145
+ resp = STDIN.gets.chomp
146
+
147
+ if resp.eql?("y")
148
+
149
+ media_organizer.move_to_destination(file, medias.first)
150
+ files_processed_count += 1
151
+ else
152
+ Logger.success("\n0: The movie isn't in the list, go next without doing anything.")
153
+ medias.each_with_index do |media, index|
154
+ Logger.success("\n#{index+1}: #{media.data.name} #{media.data.released ? "(#{Date.parse(media.data.released).year})" : nil}")
164
155
  end
165
156
 
166
- Logger.info("\n\n=> Files pocessed #{files_processed_count}/#{source.files.size}") unless @options[:test]
157
+ Logger.success("\nChoose the movie: ")
158
+ resp = STDIN.gets.chomp.to_i-1
159
+
160
+ if resp >= 0 && resp <= medias.size
161
+ media = medias[resp]
162
+ Logger.success("\nMedia found : #{media.data.name} #{media.data.released ? "(#{Date.parse(media.data.released).year})" : nil}")
163
+ media_organizer.move_to_destination(file, media)
164
+ files_processed_count += 1
165
+ elsif resp == -1
166
+ Logger.info("Aborting...")
167
+ next
168
+ end
169
+ end
167
170
  end
171
+ else
172
+ Logger.error("\nMedia not found")
173
+ end
168
174
  end
175
+
176
+ Logger.info("\n\n=> Files pocessed #{files_processed_count}/#{source.files.size}") unless @options[:test]
177
+ end
169
178
  end
179
+ end
170
180
  end
@@ -1,19 +1,19 @@
1
1
  module Plexify
2
- # Logger class
3
- class Logger
4
- # print informations
5
- def self.info(content)
6
- print content
7
- end
2
+ # Logger class
3
+ class Logger
4
+ # print informations
5
+ def self.info(content)
6
+ print content
7
+ end
8
8
 
9
- # print success in green
10
- def self.success(content)
11
- print content.colorize(:green)
12
- end
9
+ # print success in green
10
+ def self.success(content)
11
+ print content.colorize(:green)
12
+ end
13
13
 
14
- # print errors in red
15
- def self.error(content)
16
- print content.colorize(:red)
17
- end
14
+ # print errors in red
15
+ def self.error(content)
16
+ print content.colorize(:red)
18
17
  end
18
+ end
19
19
  end
data/lib/plexify/media.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  module Plexify
2
- # Media class
3
- # Will include more methods to test media data
4
- class Media
5
- attr_accessor :data
6
- attr_accessor :found_title
7
- attr_accessor :score
2
+ # Media class
3
+ # Will include more methods to test media data
4
+ class Media
5
+ attr_accessor :data
6
+ attr_accessor :found_title
7
+ attr_accessor :score
8
8
 
9
- def initialize(data)
10
- @data = data
11
- end
9
+ def initialize(data)
10
+ @data = data
12
11
  end
12
+ end
13
13
  end
@@ -1,88 +1,106 @@
1
1
  module Plexify
2
- class MediaManager
3
- # Initialize variables and load tmdb media manager
4
- def initialize
5
- @tmdb_api_key = nil
6
- @tmdb_default_language = nil
7
- load_tmdb
8
- end
9
-
10
- # Search for a media in the Tmdb media manager database.
11
- def analyze(file)
12
- name = File.basename(file.path, File.extname(file.path))
13
- splitted_name = name.split(/\W/).map(&:downcase)
2
+ class MediaManager
3
+ include Amatch
14
4
 
15
- medias = analyse_names(splitted_name, {})
5
+ # Initialize variables and load tmdb media manager
6
+ def initialize
7
+ @tmdb_api_key = nil
8
+ @tmdb_default_language = nil
9
+ load_tmdb
10
+ end
16
11
 
17
- flattened_medias = []
18
- medias.each_pair do |title, media|
19
- flattened_medias << media if flattened_medias.empty?
20
- unless flattened_medias.map(&:data).map(&:id).include?(media.data.id)
21
- media.found_title = title
22
- flattened_medias << media
23
- end
24
- end
12
+ # Search for a media in the Tmdb media manager database.
13
+ def analyze(file)
14
+ name = File.basename(file.path, File.extname(file.path))
15
+ splitted_name = name.split(/\W/).map(&:downcase)
16
+ found_medias = analyze_names(splitted_name, {})
25
17
 
26
- return flattened_medias
18
+ medias = Array.new
19
+ found_medias.each_pair do |title, list|
20
+ for media in list
21
+ medias << media if medias.empty?
22
+ unless medias.map(&:data).map(&:id).include?(media.data.id)
23
+ media.found_title = title
24
+ medias << media
25
+ end
27
26
  end
27
+ end
28
28
 
29
- private
30
- # Load tmdb media manager
31
- def load_tmdb
32
- load_plexify_config
33
- Tmdb.api_key = @tmdb_api_key
34
- Tmdb.default_language = @tmdb_default_language
35
- end
29
+ # Check differences betweend the file title
30
+ # and found medias names
31
+ title = name.gsub(/\W/, " ").downcase
32
+ for media in medias
33
+ name = media.data.name.downcase
34
+ media.score = title.hamming_similar(name)
35
+ end
36
36
 
37
- # Load plexify config yaml file in the home directory
38
- # The file structure is :
39
- # plexify:
40
- # tmdb:
41
- # api_key: xxxx
42
- # default_language: en
43
- def load_plexify_config
44
- config_file_path = File.join(File.dirname(__FILE__), "../../.plexify.yml")
45
- config_file = File.open config_file_path
46
- yaml_config = YAML::load(config_file)
47
-
48
- tmdb_config = yaml_config["plexify"]["tmdb"]
49
- @tmdb_api_key = tmdb_config["api_key"]
50
- @tmdb_default_language = tmdb_config["default_language"]
51
- end
37
+ # Compare title with original media name
38
+ # if the score is better, it selects it
39
+ for media in medias
40
+ name = media.data.original_name.downcase
41
+ score = title.hamming_similar(name)
42
+ media.score = score if score > media.score
43
+ end
52
44
 
53
- def analyse_names(list, medias)
54
- title = String.new
45
+ # Return ten last medias sort by score
46
+ return medias.sort_by(&:score).reverse.delete_if {|m| medias.index(m) > 10 }
47
+ end
55
48
 
56
- list.each_with_index do |str, index|
57
- title << " " if title.length > 0
58
- title << str
59
- media = find(title)
49
+ private
50
+ # Load tmdb media manager
51
+ def load_tmdb
52
+ load_plexify_config
53
+ Tmdb.api_key = @tmdb_api_key
54
+ Tmdb.default_language = @tmdb_default_language
55
+ end
60
56
 
61
- if media.empty?
62
- if medias.any?
63
- shift = list.shift
64
- analyse_names(list, medias)
65
- end
66
- else
67
- medias[title] = Media.new(media)
68
- end
69
- end
70
- return medias
71
- end
57
+ # Load plexify config yaml file in the home directory
58
+ # The file structure is :
59
+ # plexify:
60
+ # tmdb:
61
+ # api_key: xxxx
62
+ # default_language: en
63
+ def load_plexify_config
64
+ config_file_path = File.join(File.dirname(__FILE__), "../../.plexify.yml")
65
+ config_file = File.open config_file_path
66
+ yaml_config = YAML::load(config_file)
72
67
 
73
- # Get Levenshtein distance
74
- def levenshtein_distance(first, second)
75
- Text::Levenshtein.distance(first, second)
76
- end
68
+ tmdb_config = yaml_config["plexify"]["tmdb"]
69
+ @tmdb_api_key = tmdb_config["api_key"]
70
+ @tmdb_default_language = tmdb_config["default_language"]
71
+ end
77
72
 
78
- # Find a movie in the Tmdb database with a title and a limit of one item
79
- def find(title)
80
- TmdbMovie.find(:title => title, :limit => 1)
81
- end
73
+ # Analyze title name: iterates each words and find a related media
74
+ def analyze_names(list, medias)
75
+ title = String.new
76
+
77
+ list.each_with_index do |str, index|
78
+ title << " " if title.length > 0
79
+ title << str
80
+ found_medias = find(title)
82
81
 
83
- # Find all movies in the Tmdb database with a title
84
- def find_all(title)
85
- TmdbMovie.find(:title => title)
82
+ if found_medias.empty?
83
+ if medias.any?
84
+ shift = list.shift
85
+ analyze_names(list, medias)
86
+ end
87
+ else
88
+ tmp_medias = Array.new
89
+ found_medias.each { |m| tmp_medias << Media.new(m) }
90
+ medias[title] = tmp_medias
86
91
  end
92
+ end
93
+ return medias
94
+ end
95
+
96
+ # Find a movie in the Tmdb database with a title and a limit of one item
97
+ def find(title)
98
+ TmdbMovie.find(:title => title, :limit => 5)
99
+ end
100
+
101
+ # Find all movies in the Tmdb database with a title
102
+ def find_all(title)
103
+ TmdbMovie.find(:title => title)
87
104
  end
105
+ end
88
106
  end
@@ -1,71 +1,71 @@
1
1
  module Plexify
2
- # Class MediaOrganizer
3
- # It manage source and destination folders
4
- class MediaOrganizer
5
- attr_reader :source
6
- attr_reader :destination
2
+ # Class MediaOrganizer
3
+ # It manage source and destination folders
4
+ class MediaOrganizer
5
+ attr_reader :source
6
+ attr_reader :destination
7
7
 
8
- # Initialize
9
- def initialize(source, destination)
10
- @source = source
11
- @destination = destination
12
- end
8
+ # Initialize
9
+ def initialize(source, destination)
10
+ @source = source
11
+ @destination = destination
12
+ end
13
13
 
14
- # Move a file the his appropriate destination folder
15
- def move_to_destination(file, media)
16
- # Consider media is a movie
17
- destination = @destination.movies_folder.path
14
+ # Move a file the his appropriate destination folder
15
+ def move_to_destination(file, media)
16
+ # Consider media is a movie
17
+ destination = @destination.movies_folder.path
18
18
 
19
- # Create an appropriate media folder
20
- media_folder_name = "#{media.data.name} (#{Date.parse(media.data.released).year})"
21
- media_folder_path = File.join(destination, media_folder_name)
22
- file_basename = File.basename(file.path)
19
+ # Create an appropriate media folder
20
+ media_folder_name = "#{media.data.name} (#{Date.parse(media.data.released).year})"
21
+ media_folder_path = File.join(destination, media_folder_name)
22
+ file_basename = File.basename(file.path)
23
23
 
24
- # Create the movie folder
25
- FileUtils.mkdir(media_folder_path) unless File.exists?(media_folder_path)
26
- media_folder = File.open(media_folder_path)
24
+ # Create the movie folder
25
+ FileUtils.mkdir(media_folder_path) unless File.exists?(media_folder_path)
26
+ media_folder = File.open(media_folder_path)
27
27
 
28
- if media_folder
29
- renamed_file_basename = media_folder_name + File.extname(file_basename)
30
- renamed_file_path = File.join(media_folder.path, renamed_file_basename)
28
+ if media_folder
29
+ renamed_file_basename = media_folder_name + File.extname(file_basename)
30
+ renamed_file_path = File.join(media_folder.path, renamed_file_basename)
31
31
 
32
- # Copy the file with a progress bar
33
- Logger.info("\nCopying file to '#{renamed_file_path}'")
34
- copy_with_progressbar(file.path, renamed_file_path)
35
- Logger.success("File '#{renamed_file_path}' copied") if File.exists?(renamed_file_path)
36
- end
32
+ # Copy the file with a progress bar
33
+ Logger.info("Copying file to '#{renamed_file_path}'")
34
+ copy_with_progressbar(file.path, renamed_file_path)
35
+ Logger.success("File '#{renamed_file_path}' copied") if File.exists?(renamed_file_path)
36
+ end
37
37
 
38
- Logger.info("\nDo you want to remove the source file '#{file_basename}' ? (y/n) ")
39
- resp = STDIN.gets.chomp
38
+ Logger.info("\nDo you want to remove the source file '#{file_basename}' ? (y/n) ")
39
+ resp = STDIN.gets.chomp
40
40
 
41
- if resp.eql?("y")
42
- FileUtils.rm file.path
43
- Logger.success("File '#{file_basename}' removed")
44
- end
45
- end
41
+ if resp.eql?("y")
42
+ FileUtils.rm file.path
43
+ Logger.success("File '#{file_basename}' removed")
44
+ end
45
+ end
46
46
 
47
- private
47
+ private
48
48
 
49
- # Copy a file with a great progress bar
50
- def copy_with_progressbar(source, destination)
51
- source_file = File.new(source, "r")
52
- destination_file = File.new(destination, "w")
53
- source_size = File.size(source)
54
- batch_bytes = ( source_size / 100 ).ceil
55
- total = 0
49
+ # Copy a file with a great progress bar
50
+ def copy_with_progressbar(source, destination)
51
+ source_file = File.new(source, "r")
52
+ destination_file = File.new(destination, "w")
53
+ source_size = File.size(source)
54
+ batch_bytes = ( source_size / 100 ).ceil
55
+ total = 0
56
56
 
57
- p_bar = ProgressBar.create(:title => "Copying '#{File.basename(source_file.path)}'", :format => '|%b>%i| %p%% %t')
58
- buffer = source_file.sysread(batch_bytes)
57
+ p_bar = ProgressBar.create(:title => "Copying '#{File.basename(destination_file.path)}'", :format => '|%b>%i| %p%% %t')
58
+ buffer = source_file.sysread(batch_bytes)
59
59
 
60
- while total < source_size do
61
- destination_file.syswrite(buffer)
62
- p_bar.progress = ((total*100)/source_size).ceil + 1
63
- total += batch_bytes
64
- if (source_size - total) < batch_bytes
65
- batch_bytes = (source_size - total)
66
- end
67
- buffer = source_file.sysread(batch_bytes)
68
- end
60
+ while total < source_size do
61
+ destination_file.syswrite(buffer)
62
+ p_bar.progress = ((total*100)/source_size).ceil + 1
63
+ total += batch_bytes
64
+ if (source_size - total) < batch_bytes
65
+ batch_bytes = (source_size - total)
69
66
  end
67
+ buffer = source_file.sysread(batch_bytes)
68
+ end
70
69
  end
70
+ end
71
71
  end
@@ -1,91 +1,91 @@
1
1
  module Plexify
2
- module Prepare
3
- # Destination class implementation
4
- class Destination
5
- attr_accessor :folder
6
- attr_accessor :movies_folder
7
- attr_accessor :series_folder
2
+ module Prepare
3
+ # Destination class implementation
4
+ class Destination
5
+ attr_accessor :folder
6
+ attr_accessor :movies_folder
7
+ attr_accessor :series_folder
8
8
 
9
- # Plexify::Execute initialize method
10
- def initialize(options)
11
- @destination_path = options[:destination]
12
- @movies_destination_path = options[:movies_destination]
13
- @series_destination_path = options[:series_destination]
14
- end
9
+ # Plexify::Execute initialize method
10
+ def initialize(options)
11
+ @destination_path = options[:destination]
12
+ @movies_destination_path = options[:movies_destination]
13
+ @series_destination_path = options[:series_destination]
14
+ end
15
15
 
16
- def prepare
17
- if @destination_path
18
- prepare_destination
19
- else
20
- prepare_destinations
21
- end
22
- end
23
-
24
- protected
25
- # Prepare destination
26
- def prepare_destination
27
- # Create destination folder
28
- destination_path = @destination_path
29
- @folder = create_or_use_folder(destination_path)
16
+ def prepare
17
+ if @destination_path
18
+ prepare_destination
19
+ else
20
+ prepare_destinations
21
+ end
22
+ end
30
23
 
31
- # Create "Movies" and "TV Shows" folder
32
- @movies_folder = create_or_use_folder(destination_path, "Movies")
33
- @series_folder = create_or_use_folder(destination_path, "TV Shows")
34
- end
24
+ protected
25
+ # Prepare destination
26
+ def prepare_destination
27
+ # Create destination folder
28
+ destination_path = @destination_path
29
+ @folder = create_or_use_folder(destination_path)
35
30
 
36
- # Prepare destinations
37
- def prepare_destinations
38
- # Create or use movies and series folders
39
- movies_path = @movies_destination_path
40
- series_path = @series_destination_path
31
+ # Create "Movies" and "TV Shows" folder
32
+ @movies_folder = create_or_use_folder(destination_path, "Movies")
33
+ @series_folder = create_or_use_folder(destination_path, "TV Shows")
34
+ end
41
35
 
42
- @movies_folder = create_or_use_folder(movies_path) if movies_path
43
- @series_folder = create_or_use_folder(series_path) if series_path
44
- end
36
+ # Prepare destinations
37
+ def prepare_destinations
38
+ # Create or use movies and series folders
39
+ movies_path = @movies_destination_path
40
+ series_path = @series_destination_path
45
41
 
46
- # Create or use a folder
47
- def create_or_use_folder(*args)
48
- path = args.first
42
+ @movies_folder = create_or_use_folder(movies_path) if movies_path
43
+ @series_folder = create_or_use_folder(series_path) if series_path
44
+ end
49
45
 
50
- if args.size > 1
51
- name = args[1]
52
- end
46
+ # Create or use a folder
47
+ def create_or_use_folder(*args)
48
+ path = args.first
53
49
 
54
- folder_path = name ? File.join(path, name) : path
50
+ if args.size > 1
51
+ name = args[1]
52
+ end
55
53
 
56
- if File.exists?(folder_path) && File.directory?(folder_path)
57
- folder = File.open(folder_path)
58
- else
59
- Logger.info("\n=> Created missing '#{name ? name : File.basename(folder_path)}' folder in destination folder.")
60
- FileUtils.mkdir_p folder_path
61
- folder = File.open(folder_path) if File.exists?(folder_path)
62
- end
54
+ folder_path = name ? File.join(path, name) : path
63
55
 
64
- folder
65
- end
56
+ if File.exists?(folder_path) && File.directory?(folder_path)
57
+ folder = File.open(folder_path)
58
+ else
59
+ Logger.info("\n=> Created missing '#{name ? name : File.basename(folder_path)}' folder in destination folder.")
60
+ FileUtils.mkdir_p folder_path
61
+ folder = File.open(folder_path) if File.exists?(folder_path)
66
62
  end
67
63
 
68
- # Source class implementation
69
- class Source
70
- attr_accessor :folder
71
- attr_accessor :files
72
-
73
- # Initialize
74
- def initialize(options)
75
- @source_path = options[:source]
76
- @files = Array.new
77
- end
64
+ folder
65
+ end
66
+ end
67
+
68
+ # Source class implementation
69
+ class Source
70
+ attr_accessor :folder
71
+ attr_accessor :files
72
+
73
+ # Initialize
74
+ def initialize(options)
75
+ @source_path = options[:source]
76
+ @files = Array.new
77
+ end
78
78
 
79
- # Prepare source folder
80
- def prepare
81
- @folder = File.new @source_path
79
+ # Prepare source folder
80
+ def prepare
81
+ @folder = File.new @source_path
82
82
 
83
- if File.exists?(@folder.path) && File.directory?(@folder.path)
84
- Dir.glob(@folder.path + "/**/*.{mkv,avi,mov}") do |file|
85
- @files << File.open(file)
86
- end
87
- end
88
- end
83
+ if File.exists?(@folder.path) && File.directory?(@folder.path)
84
+ Dir.glob(@folder.path + "/**/*.{mkv,avi,mov}") do |file|
85
+ @files << File.open(file)
86
+ end
89
87
  end
88
+ end
90
89
  end
90
+ end
91
91
  end
@@ -1,3 +1,3 @@
1
1
  module Plexify
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/plexify.gemspec CHANGED
@@ -14,9 +14,11 @@ Gem::Specification.new do |gem|
14
14
 
15
15
  gem.add_dependency("ruby-tmdb", "= 0.2.1")
16
16
  gem.add_dependency("colorize", "= 0.5.8")
17
- gem.add_dependency("text", "= 1.2.1")
17
+ gem.add_dependency("amatch", "= 0.2.10")
18
18
  gem.add_dependency("ruby-progressbar", "= 1.0.2")
19
19
 
20
+ gem.add_development_dependency 'rspec', '~> 2.12.0'
21
+
20
22
  gem.files = `git ls-files`.split($/)
21
23
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
22
24
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Plexify, "#Version" do
4
+ it 'should return correct version string' do
5
+ Plexify.version.should == "Plexify version #{Plexify::VERSION}"
6
+ end
7
+ end
8
+
9
+ describe Plexify, "#Arguments" do
10
+ it 'should raise an error by passing bad arguments count' do
11
+ #TODO
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'plexify'
4
+
5
+ RSpec.configure do |config|
6
+ config.color_enabled = true
7
+ config.formatter = 'documentation'
8
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plexify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-03 00:00:00.000000000 Z
12
+ date: 2012-12-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby-tmdb
@@ -44,13 +44,13 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: 0.5.8
46
46
  - !ruby/object:Gem::Dependency
47
- name: text
47
+ name: amatch
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
51
  - - '='
52
52
  - !ruby/object:Gem::Version
53
- version: 1.2.1
53
+ version: 0.2.10
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.2.1
61
+ version: 0.2.10
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: ruby-progressbar
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -75,6 +75,22 @@ dependencies:
75
75
  - - '='
76
76
  - !ruby/object:Gem::Version
77
77
  version: 1.0.2
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 2.12.0
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 2.12.0
78
94
  description: Organize media folders to get ready with media managers
79
95
  email:
80
96
  - pfilstroff@gmail.com
@@ -99,6 +115,8 @@ files:
99
115
  - lib/plexify/prepare.rb
100
116
  - lib/plexify/version.rb
101
117
  - plexify.gemspec
118
+ - spec/plexify_spec.rb
119
+ - spec/spec_helper.rb
102
120
  homepage: ''
103
121
  licenses: []
104
122
  post_install_message:
@@ -123,4 +141,6 @@ rubygems_version: 1.8.24
123
141
  signing_key:
124
142
  specification_version: 3
125
143
  summary: Media managers files organizer
126
- test_files: []
144
+ test_files:
145
+ - spec/plexify_spec.rb
146
+ - spec/spec_helper.rb