class MovieManagerGem::Finder
DH Searcher ###
Public Class Methods
new()
click to toggle source
require ‘pg’ # postgres implementation
# File lib/movie-manager-gem.rb, line 13 def initialize() # start database @@DB = Sequel.sqlite(File.expand_path('~/.movie_manager_003.db')) # sqlite3 implementation # @@DB = Sequel.postgres('testdb', :host=>'localhost', :user=>'David', :password=>'password') # postgres implementation # create tables within database create_all_tables # tie ruby-accessible datasets to database table @movies_dataset = @@DB[:movies] @movie_genre_dataset = @@DB[:movie_genre] @genres_dataset = @@DB[:genres] @directories_dataset = @@DB[:directories] @movie_actor_dataset = @@DB[:movie_actor] @actors_dataset = @@DB[:actors] @movie_director_dataset = @@DB[:movie_director] @directors_dataset = @@DB[:directors] # joins @movie_directories_join = @movies_dataset.join(:directories, :id => :directory_id) # must be before other joins @movie_genre_join = @movie_directories_join.join(:movie_genre, :movie_id => :movies__id).join(:genres, :id => :genre_id) @movie_actor_join = @movie_directories_join.join(:movie_actor, :movie_id => :movies__id).join(:actors, :id => :actor_id) @movie_director_join = @movie_directories_join.join(:movie_director, :movie_id => :movies__id).join(:directors, :id => :movie_director__director_id) # queues and threads @local_movies_queue = Queue.new @processed_movies_queue = Queue.new @threads = [] end
Public Instance Methods
actors_record_exists?(name)
click to toggle source
# File lib/movie-manager-gem.rb, line 368 def actors_record_exists?(name) return false if @actors_dataset.select(:id).where(:name => name).all.length == 0 return true end
add_all_movies_to_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 284 def add_all_movies_to_table # works # add func to auto-find/add new movies. 2.times do # this code was supplied by Theo on SO # http://stackoverflow.com/questions/6558828/thread-and-queue @threads << Thread.new do until @local_movies_queue.empty? long_name, clean_name, data = @local_movies_queue.pop(true) rescue nil if long_name if movies_record_exists?(long_name) movie_title = @movies_dataset.select(:title).where(:original_title => long_name).first[:title] puts "#{movie_title} record already exists" else data = get_imdb_movie_info(clean_name) @processed_movies_queue << [long_name, clean_name, data] add_movie(@processed_movies_queue.pop) end end end end end @threads.each { |t| t.join } end
add_movie((long_name, clean_name, data))
click to toggle source
# File lib/movie-manager-gem.rb, line 308 def add_movie((long_name, clean_name, data)) # works if data # Add Directory to directories_dataset @directories_dataset.insert(:directory_path => File.dirname(long_name)) unless directories_record_exists?(File.dirname(long_name)) # Add Movie to movies_dataset @movies_dataset.insert( :original_title => long_name, :title => data.title[0..-8], :imdb_score => data.rating, :summary => data.plot_summary||'No summary available', :length => data.length||-1, :date_added => Time.new(), :directory_id => @directories_dataset.select(:id).where(:directory_path => File.dirname(long_name)).first[:id]) movie_id = @movies_dataset.select(:id).where(:title => data.title[0..-8]).first[:id] # Add Actors to actors_dataset and movie_actor_dataset data.cast_members.each do |actor| @actors_dataset.insert(:name => actor) unless actors_record_exists?(actor) # used to be :name => actor.name. Make sure this works online! @movie_actor_dataset.insert(:movie_id => movie_id, :actor_id => @actors_dataset.select(:id).where(:name => actor).first[:id]) end if data.cast_members # Add Genres to genres_dataset and movie_genre_dataset data.genres.each do |genre| @genres_dataset.insert(:genre => genre) unless genres_record_exists?(genre) @movie_genre_dataset.insert(:movie_id => movie_id, :genre_id => @genres_dataset.select(:id).where(:genre => genre).first[:id]) end if data.genres # Add Directors to directors_dataset and movie_director_dataset data.director.each do |director| if director != "(more)" # compensates for a bug in imdb gem. Pull request submitted. @directors_dataset.insert(:name => director) unless directors_record_exists?(director) @movie_director_dataset.insert(:movie_id => movie_id, :director_id => @directors_dataset.select(:id).where(:name => director).first[:id]) end end if data.director puts "#{data.title[0..-8]} added to table" else @movies_dataset.insert(:original_title => long_name, :title => clean_name, :date_added => Time.new()) puts "#{clean_name} added to table" end end
create_actors_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 459 def create_actors_table if @@DB.table_exists?(:actors) raise StandardError, 'Actors table already exists, try a different name' else @@DB.create_table :actors do primary_key :id String :name end end end
create_all_tables()
click to toggle source
Tables & DBs ###
# File lib/movie-manager-gem.rb, line 389 def create_all_tables create_directories_table unless @@DB.table_exists?(:directories) create_movies_table unless @@DB.table_exists?(:movies) create_genres_table unless @@DB.table_exists?(:genres) create_movie_genre_table unless @@DB.table_exists?(:movie_genre) create_actors_table unless @@DB.table_exists?(:actors) create_movie_actor_table unless @@DB.table_exists?(:movie_actor) create_directors_table unless @@DB.table_exists?(:directors) create_movie_director_table unless @@DB.table_exists?(:movie_director) end
create_directories_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 424 def create_directories_table if @@DB.table_exists?(:directories) raise StandardError, 'Directories table already exists, try a different name' else @@DB.create_table :directories do primary_key :id String :directory_path Integer :available, :default => 1 end end end
create_directors_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 482 def create_directors_table if @@DB.table_exists?(:directors) raise StandardError, 'Directors table already exists, try a different name' else @@DB.create_table :directors do primary_key :id String :name end end end
create_genres_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 436 def create_genres_table if @@DB.table_exists?(:genres) raise StandardError, 'Genres table already exists, try a different name' else @@DB.create_table :genres do primary_key :id String :genre end end end
create_movie_actor_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 470 def create_movie_actor_table if @@DB.table_exists?(:movie_actor) raise StandardError, 'Movie_Actor table already exists, try a different name' else @@DB.create_table :movie_actor do primary_key :id Integer :movie_id Integer :actor_id end end end
create_movie_director_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 493 def create_movie_director_table if @@DB.table_exists?(:movie_director) raise StandardError, 'Movie_Director table already exists, try a different name' else @@DB.create_table :movie_director do primary_key :id Integer :movie_id Integer :director_id end end end
create_movie_genre_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 447 def create_movie_genre_table if @@DB.table_exists?(:movie_genre) raise StandardError, 'Movie_Genre table already exists, try a different name' else @@DB.create_table :movie_genre do primary_key :id Integer :movie_id Integer :genre_id end end end
create_movies_table()
click to toggle source
# File lib/movie-manager-gem.rb, line 404 def create_movies_table if @@DB.table_exists?(:movies) raise StandardError, 'Movies table already exists, try a different name' else @@DB.create_table :movies do primary_key :id String :original_title String :title Float :imdb_score, :default => -1 #1-100 Float :my_score, :default => -1 #1-100 Integer :correct_filename, :default => 0 #0/no, 1/yes Integer :watched, :default => -1 #-1/unknown, 0/no, 1/yes String :summary, {:text => true, :default => 'No summary available.'} Integer :length, :default => -1 String :date_added Integer :directory_id end end end
directories_record_exists?(path)
click to toggle source
# File lib/movie-manager-gem.rb, line 383 def directories_record_exists?(path) return false if @directories_dataset.select(:directory_path).where(:directory_path => path).all.length == 0 return true end
directors_record_exists?(name)
click to toggle source
# File lib/movie-manager-gem.rb, line 373 def directors_record_exists?(name) return false if @directors_dataset.select(:id).where(:name => name).all.length == 0 return true end
display_movie_info(title)
click to toggle source
List and Play Movies ###
# File lib/movie-manager-gem.rb, line 106 def display_movie_info(title) movie_list = @movie_genre_join.where(Sequel.ilike(:title, '%'+title+'%'), :available => 1).all # sqlite3 implementation if movie_list.empty? puts "Sorry, couldn't find '#{title}'" else puts "Title: #{movie_list[0][:title]}" puts "Genre(s): #{movie_list.inject([]){|out, movie| out<<movie[:genre]}.join(", ")}" puts "Rating: #{movie_list[0][:imdb_score]}/10" puts "Length: #{movie_list[0][:length]} min." puts "Summary:" puts "#{movie_list[0][:summary]}" end end
drop_table(table_name = table_name.to_sym)
click to toggle source
# File lib/movie-manager-gem.rb, line 505 def drop_table(table_name = table_name.to_sym) if @@DB.table_exists?(table_name) puts "Are you sure you want to drop table \'#{table_name}\'? Y/N" response = 1000.chomp.downcase case response when 'y', 'yes' @@DB.drop_table(table_name) puts 'Table dropped' when 'n', 'no' puts 'Table not dropped' else puts 'Reply with Y or N' drop_table(table_name) end else raise StandardError, 'Table doesn\'t exist' end end
enqueue_local_movies()
click to toggle source
Movie-handling fuctions ###
# File lib/movie-manager-gem.rb, line 259 def enqueue_local_movies # works movies_glob = Dir.glob('**/*.{mkv,MKV,avi,AVI,mp4,MP4,mpg,MPG,mov,MOV}').uniq movies_glob.each {|movie| @local_movies_queue << [File.absolute_path(movie), normalize_title(movie), nil]} # movies.select!{|movie| File.size(movie) > 600_000_000} # works end
find_files_in(path)
click to toggle source
# File lib/movie-manager-gem.rb, line 75 def find_files_in(path) # works # tried using ~/ as the default path. Returned too many unrelated videos. Dir.chdir(path) do enqueue_local_movies add_all_movies_to_table update_directories_status end end
genres_record_exists?(genre)
click to toggle source
# File lib/movie-manager-gem.rb, line 378 def genres_record_exists?(genre) return false if @genres_dataset.select(:id).where(:genre => genre).all.length == 0 return true end
get_imdb_movie_info(clean_name)
click to toggle source
# File lib/movie-manager-gem.rb, line 355 def get_imdb_movie_info(clean_name) # works i = Imdb::Search.new(clean_name) return i.movies.first if i.movies.first.class == Imdb::Movie return nil end
initialized?()
click to toggle source
Update and Refine Data ###
# File lib/movie-manager-gem.rb, line 44 def initialized? @movies_dataset.first end
list_all_movies(min_score=-1)
click to toggle source
# File lib/movie-manager-gem.rb, line 120 def list_all_movies(min_score=-1) # works movie_list = @movie_director_join.where({:available => 1}, (Sequel.expr(:imdb_score) >= min_score)).group(:movies__id).order(:title).all # sqlite3 impementation # movie_list = @movie_directories_join.order(:title).distinct(:movies__id,:title).where({:available => 1}, (Sequel.expr(:imdb_score) >= min_score)).all? # postgres implementation if movie_list.empty? puts "Sorry, we don\'t have any movies with a score higher than #{min_score}" else puts "--- Movies Rated Higher Than #{min_score} ---" movie_list.each{ |movie| puts movie[:title]} end end
list_movies_by_genre(genre, min_score = -1)
click to toggle source
# File lib/movie-manager-gem.rb, line 195 def list_movies_by_genre(genre, min_score = -1) # works movie_list = @movie_genre_join.where(Sequel.ilike(:genre, '%'+genre+'%') & {:available => 1}).group(:movies__id).order(:title).all # sqlite3 implementation & (Sequel.expr(:imdb_score) >= min_score) # movie_list = @movie_genre_join.order(:title).distinct(:movies__id,:title).where(Sequel.ilike(:genre, '%'+genre+'%') & {:available => 1} & (Sequel.expr(:imdb_score) >= min_score)).all # postgres implementation if movie_list.empty? puts 'Sorry, we don\'t have that genre. Please enter one from the list:' @genres_dataset.select(:genre).order(:genre).all.each {|genre| puts '- ' + genre[:genre]} elsif movie_list.select {|movie| movie[:imdb_score] >= min_score}.empty? puts "Sorry, couldn't find any movies with genre #{movie_list[0][:genre]} and a rating above #{min_score}" else search_genre = movie_list.first[:genre] print "--- Movies with genre '#{search_genre}' " print "rated above #{min_score} " if min_score != -1 puts "---" movie_list.select {|movie| movie[:imdb_score] >= min_score}.each{ |movie| puts movie[:title]} end end
list_movies_with_actor(actor, min_score = -1)
click to toggle source
# File lib/movie-manager-gem.rb, line 163 def list_movies_with_actor(actor, min_score = -1) # works results_list = @actors_dataset.where(Sequel.ilike(:name, '%'+actor+'%')).all if results_list.length > 1 temp = [] results_list.each {|result| temp << result[:name]} puts "Here are the results for '#{actor}'. Please enter the number of the one you want." temp.each_with_index do |name,i| puts "#{i+1}: #{name}" end print '> ' actor_name = temp[$stdin.gets.chomp.to_i - 1] elsif results_list.length == 1 actor_name = results_list[0][:name] else puts "Sorry, we couldn't find an actor named '#{actor}'. Here are the actors we have:" @actors_dataset.select(:name).order(:name).all.each {|actor| puts '- ' + actor[:name]} return end movie_list = @movie_actor_join.where({:name => actor_name}, {:available => 1}, (Sequel.expr(:imdb_score) >= min_score)).group(:movies__id).order(:title).all # sqlite3 implementation # movie_list = @movie_actor_join.order(:title).distinct(:movies__id,:title).where({:name => actor_name}, {:available => 1}, (Sequel.expr(:imdb_score) >= min_score)).all # postgres implementation if movie_list.empty? puts "Sorry, we don\'t have any movies starring \'#{actor_name}\'." else puts "--- Movies starring '#{actor_name}' ---" movie_list.each{ |movie| puts movie[:title]} end end
list_movies_with_director(director, min_score = -1)
click to toggle source
# File lib/movie-manager-gem.rb, line 132 def list_movies_with_director(director, min_score = -1) # works results_list = @directors_dataset.where(Sequel.ilike(:name, '%'+director+'%')).all if results_list.length > 1 temp = [] results_list.each {|result| temp << result[:name]} puts "Here are the results for '#{director}'. Please enter the number of the one you want." temp.each_with_index do |name,i| puts "#{i+1}: #{name}" end print '> ' director_name = temp[$stdin.gets.chomp.to_i - 1] elsif results_list.length == 1 director_name = results_list[0][:name] else puts "Sorry, we couldn't find a director named '#{director}'. Here are the directors we have:" @directors_dataset.select(:name).order(:name).all.each {|director| puts '- ' + director[:name]} return end movie_list = @movie_director_join.where({:name => director_name}, {:available => 1}, (Sequel.expr(:imdb_score) >= min_score)).group(:movies__id).order(:title).all # sqlite3 implementation #movie_list = @movie_director_join.order(:title).distinct(:movies__id,:title).where({:name => director_name} & {:available => 1} & (Sequel.expr(:imdb_score) >= min_score)).all # postgres implementation if movie_list.empty? puts "Sorry, we don\'t have any movies directed by \'#{director_name}\'." else puts "--- Movies directed by '#{director_name}' ---" movie_list.each{ |movie| puts movie[:title]} end end
movies_record_exists?(original)
click to toggle source
Exists? ###
# File lib/movie-manager-gem.rb, line 363 def movies_record_exists?(original) return false if @movies_dataset.select(:id).where(:original_title => original).all.length == 0 return true end
normalize_title(title)
click to toggle source
# File lib/movie-manager-gem.rb, line 265 def normalize_title(title) # works # output should seperate path, suffix. Change . and _ to spaces. Replace / and : with - to be unix-safe. remove anything in brackets or braces. File.basename(title,'.*').gsub(/[\.|\_]/," ").gsub(/[\/|:]/,"-").gsub(/[\[|\{].*[\]|\}]/, "") end
play(movie_title, user_input=true)
click to toggle source
# File lib/movie-manager-gem.rb, line 230 def play(movie_title, user_input=true) # works # does a search for the title if a user input it. opens the exact file if another function provided the name if user_input movie_to_play = @movie_directories_join.where(Sequel.ilike(:title, '%'+movie_title+'%'), :available => 1).group(:movies__id).first # sqlite3 implementation # movie_to_play = @movie_directories_join.order(:title).distinct(:movies__id,:title).where(Sequel.ilike(:title, '%'+movie_title+'%'), :available => 1).first # postgres implementation else movie_to_play = @movies_dataset.where(:title => movie_title).first end if movie_to_play puts "Play #{movie_to_play[:title]}? Y/N" print '> ' response = $stdin.gets.chomp.downcase case response when 'y', 'yes' update_watched_status(movie_to_play[:title],1) system("open \"#{movie_to_play[:original_title]}\"") # unix needs double quotes around file names with spaces when 'n', 'no' puts 'Okay...' else puts 'Speak English, man!' play(movie_title) end else puts "No movie named '#{movie_title}' found, try a different search" end end
play_unseen_genre(genre, min_score = -1)
click to toggle source
# File lib/movie-manager-gem.rb, line 213 def play_unseen_genre(genre, min_score = -1) # works movie_genre_list = @movie_genre_join.where(Sequel.ilike(:genre, '%'+genre+'%') & {:available => 1} & (Sequel.expr(:imdb_score) >= min_score)).group(:movies__id).all # sqlite3 implementation # movie_genre_list = @movie_genre_join.order(:title).distinct(:movies__id,:title).where(Sequel.ilike(:genre, '%'+genre+'%') & {:available => 1} & (Sequel.expr(:imdb_score) >= min_score)).all # postgres implementation if movie_genre_list.empty? puts "Sorry, we don\'t have any movies with the genre #{genre}." # this exception doesn't reveal if there are no movies of that genre above the minimum score else unwatched_list = movie_genre_list.select{|movie| movie[:watched] != 1} if unwatched_list.empty? puts "Sorry, you\'ve seen all of your #{genre} movies" else movie_title = unwatched_list.sample[:title] play(movie_title,false) end end end
update_directories_status()
click to toggle source
# File lib/movie-manager-gem.rb, line 270 def update_directories_status # works @directories_dataset.select(:directory_path).all.each do |dir| if Dir.exists?(dir[:directory_path]) @directories_dataset.where(:directory_path => dir[:directory_path]).update(:available => 1) else @directories_dataset.where(:directory_path => dir[:directory_path]).update(:available => 0) end end end
update_file_names()
click to toggle source
# File lib/movie-manager-gem.rb, line 48 def update_file_names incorrect_names = @movies_dataset.select(:id, :original_title, :title).where(:correct_filename => 0).all incorrect_names.each do |name| puts "Is \"#{name[:title]}\" the correct title for \"#{File.basename(name[:original_title],".*")}\"? \n y/n" print '> ' response = $stdin.gets.chomp.downcase case response when 'y','yes' new_title = File.dirname(name[:original_title]) + '/' + name[:title].gsub(/[\.|\_]/," ").gsub(/[\/|:]/,"-") + File.extname(name[:original_title]) File.rename(name[:original_title], new_title) #this is also in normalize # mac replaces ':' with '/', this is a problem # directories get confused when a movie title has a '/' in it @movies_dataset.where(:id => name[:id]).update(:correct_filename => 1, :original_title => new_title) puts "File updated" when 'n', 'no' # incorrect title, must refine, replace our RT search records @movies_dataset.where(:id => name[:id]).update(:correct_filename => -1) puts "crap, sorry..." when 'end','exit' break else puts "Respond with 'y' or 'n'" # you'll have to run the command again to continue end end end
update_watched_list()
click to toggle source
# File lib/movie-manager-gem.rb, line 84 def update_watched_list # works @movies_dataset.where(:watched => -1).all.each do |movie| puts "Have you seen #{movie[:title]}? Y/N or end" print '> ' response = $stdin.gets.chomp.downcase case response when 'y', 'yes' update_watched_status(movie[:title],1) puts 'Record updated' when 'n', 'no' update_watched_status(movie[:title],0) puts 'Record updated' when 'end' break else puts 'I didn\'t catch that..' update_watched_list end end end
update_watched_status(movie_title, status)
click to toggle source
# File lib/movie-manager-gem.rb, line 280 def update_watched_status(movie_title, status) # works. @movies_dataset.where(:title => movie_title).update(:watched => status) end