class Henchman::DropboxAssistant
Public Class Methods
new(config, debug)
click to toggle source
# File lib/dbx_assistant.rb, line 9 def initialize config, debug begin @search_limit = 500 @debug = debug @config = config @client = Dropbox::Client.new @config[:dropbox][:access_token] # stop words from http://nlp.stanford.edu/IR-book/html/htmledition/dropping-common-terms-stop-words-1.html @stop_words = ['a', 'an', 'and', 'are', 'as', 'at', 'be', 'by', 'for', 'from', 'has', 'he', 'in', 'is', 'it', 'its', 'of', 'on', 'that', 'the', 'to', 'was', 'were', 'will', 'with'] true rescue DropboxError => msg puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\ "Couldn't connect to Dropbox (#{msg}). "\ "Run `henchman stop` then `henchman configure` "\ "to configure Dropbox connection." false end end
Public Instance Methods
download(selection, dropbox_path)
click to toggle source
# File lib/dbx_assistant.rb, line 30 def download selection, dropbox_path puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\ "Downloading #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')} from #{dropbox_path}" begin # download the file content, body = @client.download dropbox_path # make sure we have the directory to put it in trgt_dir = File.join @config[:root], selection[:artist], selection[:album] puts trgt_dir if @debug system 'mkdir', '-p', trgt_dir # save the file file_save_path = File.join trgt_dir, File.basename(dropbox_path) puts file_save_path if @debug open(file_save_path, 'w') {|f| f.puts body } file_save_path rescue DropboxError => msg puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\ "Error downloading Dropbox file #{dropbox_path}: #{msg}" false rescue StandardError => msg puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\ "Error saving Dropbox file #{dropbox_path} to #{trgt_dir}: #{msg}" false end end
get_results(track, artist)
click to toggle source
# File lib/dbx_assistant.rb, line 76 def get_results track, artist puts "`get_results` for #{track} by #{artist}" if @debug # Search Dropbox for the file # We're only not filtering to get files because we want to check if we get 1000 results # (i.e. a maxed out playload) back. This is because the filtering happens in OUR client, # not in the Dropbox search. We're doing a simple search on only track name because we # want to minimize the number of network calls, and USUALLY this is good enough results = search track # If we get 1000 results back, it means we probably have a REALLY simple song title # and we're not assured to have the target song in our payload, since we maxed it # out. So, we'll do another search call on the artist if results.length == @search_limit puts "Maximum (#{@search_limit}) results returned" if @debug results.clear album_dirs = search artist, :dir album_dirs.each do |album| tmp_rslts = search track, :file, album['path'] results.push(*tmp_rslts) end else # Otherwise, filter off all the directories and things without the right extensions puts "Filtering out directories and incorrect file extensions" if @debug results.reject! { |result| !result.is_a? Dropbox::FileMetadata || !(@config[:file_extensions].include?(File.extname(result.path_lower)[1..-1])) } end puts "Returning #{results.length} results from `get_results`" if @debug return results end
search(value, filter = nil, dir = @config[:dropbox][:root])
click to toggle source
# File lib/dbx_assistant.rb, line 58 def search value, filter = nil, dir = @config[:dropbox][:root] puts "Searching for #{value} in #{dir}, filtering by <#{filter}>" if @debug begin results = @client.search dir, value, 0, @search_limit puts "#{results.length} total results found" if @debug if filter == :dir results.reject! { |result| !result.is_a? Dropbox::FolderMetadata } elsif filter == :file results.reject! { |result| !result.is_a? Dropbox::FileMetadata || !(@config[:file_extensions].include?(File.extname(result.path_lower)[1..-1])) } end puts "Returning #{results.length} results for `search` (after filtering)" if @debug return results rescue DropboxError => msg raise "Error accessing Dropbox Search API|#{value}|#{dir}|#{msg}" end end
search_for(selection)
click to toggle source
# File lib/dbx_assistant.rb, line 105 def search_for selection puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\ "Searching for #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')}" results = get_results selection[:track], selection[:artist] # if we still don't have any results, try dropping any brackets and paranthesis if results.empty? && (selection[:track].match(%r( *\[.*\] *)) || selection[:track].match(%r( *\(.*\) *))) puts "No results. Trying without brackets or parenthesis" if @debug track = selection[:track].gsub(%r( *\[.*\] *), " ").gsub(%r( *\(.*\) *), " ") results = get_results track, selection[:artist] end # if there were no results, raise err if results.empty? raise "Track not found in Dropbox: #{selection.reject{|k,v| k == :id}.values.join(':')}" else scores = Hash.new 0 tokens = Array.new track_tokens = Array.new [:artist, :album].each do |identifier| tokens |= selection[identifier].downcase .gsub(%r( +), " ") .gsub(%r(-+), "-") .strip .split(/[\s-]/) .delete_if{ |t| @stop_words.include? t } end @config[:file_extensions].each do |extension| track_tokens |= selection[:track].downcase .gsub(%r( +), " ") .gsub(%r(-+), "-") .strip .split(/[\s-]/) .map { |t| "#{t}.#{extension}" } end if @debug puts ":artist and :album tokens: #{tokens.inspect}" puts ":track tokens: #{track_tokens.inspect}" end results.each do |result| dir = "#{File.dirname(result.path_lower)}/" basename = " #{File.basename(result.path_lower)}" tokens.each do |token| if dir =~ %r(.*[\s\/-]#{token}[\s\/-].*) puts "Token #{token} found in #{dir}" if @debug if results.length == 1 return result.path_display else scores[result.path_display] += 1 end end end track_tokens.each do |token| if basename =~ %r([.]*[\s-]+#{token}) puts "Token #{token} found in #{basename}" if @debug scores[result.path_display] += 1 end end end # if the we only had one track and we're here, that means the path didn't contain # any of the album or artist tokens, so we'll say we couldn't find it if results.length == 1 raise "Track not found in Dropbox: #{selection.reject{|k,v| k == :id}.values.join(':')}" end # return the path that has the highest score scores = scores.sort_by { |path, score| score } if @debug scores.each { |score| puts score.join ': ' } end scores[-1][0] end end