henchman-sync 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba50beb7184c552a3a27c1c6c993a70d9eb53496
4
- data.tar.gz: c1c5bb43fd8eb9dd21dd3e976ce22fd8efc8215a
3
+ metadata.gz: 7d27e875da0439ebd8e24c160d77c962202b0f19
4
+ data.tar.gz: 775dfd05202ac8248fc155901845f224adc004e5
5
5
  SHA512:
6
- metadata.gz: 4c06ad0803566f62aa4ad348801409c2b7b0a061cbb4dfea5e1a840cb1597c51c152be9baf260d3d9d0941d26527bbbd875ec34854039aa4cb8832e8ff253d09
7
- data.tar.gz: 4db7132de8baacbc36b82a3890e040742d0fd753e10126e29fa90a7dce3ce3b1ac3b5f6d2f31d4412bb428516fc4d27e0091b80fb0deb9a08238092c88b650aa
6
+ metadata.gz: fd12ef4db1308346aa45ffd3f386f02e90714217430effe5908b8196573275a4dda0133b6dcd8e07409332a4cce8308a45530b8a46c50de1efa2f19c4f54e8ae
7
+ data.tar.gz: 07d8df1684c9e5ec9db629ec9bbffec58c324668bc447ab98d49db7659743bed18eb6670edc0265b14826c70c6402195f8b9a07027fdacd7c1c92f2ff2bf1d38
data/README.md CHANGED
@@ -48,10 +48,6 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
48
48
 
49
49
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
50
 
51
- ## TODO
52
-
53
- - Move off of the 'dropbox-sdk' gem, since it uses their API V1, which will be depreciated June 28th, 2017 (or just buck up and update the gem myself)
54
-
55
51
  ## Contributing
56
52
 
57
53
  Bug reports and pull requests are welcome on GitHub at https://github.com/gremerritt/henchman.
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ["lib"]
29
29
 
30
30
  spec.add_dependency "commander", "~> 4.4"
31
- spec.add_dependency "dropbox-sdk", "~> 1.6"
31
+ spec.add_dependency "dropbox-sdk-v2", "~> 0.0"
32
32
  spec.add_development_dependency "bundler", "~> 1.12"
33
33
  spec.add_development_dependency "rake", "~> 10.0"
34
34
  spec.add_development_dependency "rspec", "~> 3.0"
@@ -133,7 +133,7 @@ module Henchman
133
133
  "end repeat"
134
134
  end
135
135
 
136
- def get_playlist_tracks_script playlist, skip = [], size = 100
136
+ def get_playlist_tracks_script playlist, skip = [], size = 5
137
137
  "property counter : 0\n"\
138
138
  "tell application \"iTunes\"\n"\
139
139
  " try\n"\
@@ -210,7 +210,7 @@ module Henchman
210
210
  next if track.empty?
211
211
  tmp_track = track.split @delimiter
212
212
  tracks.push( {:id => tmp_track[0],
213
- :date => DateTime.parse(tmp_track[1]),
213
+ :date => (tmp_track[1] != 'missing value') ? DateTime.parse(tmp_track[1]) : DateTime.new,
214
214
  :path => tmp_track[2]} )
215
215
  end
216
216
  tracks
@@ -229,7 +229,7 @@ module Henchman
229
229
  def get_playlist_tracks playlist, skip = []
230
230
  tracks = Array.new
231
231
  tmp_tracks = %x(#{applescript_command(get_playlist_tracks_script playlist, skip)}).chomp
232
- tmp_tracks = tmp_tracks.split @delimiter_major
232
+ tmp_tracks = tmp_tracks.force_encoding("UTF-8").split @delimiter_major
233
233
  tmp_tracks.each do |track|
234
234
  next if track.empty?
235
235
  tmp_track = track.split @delimiter
@@ -274,8 +274,6 @@ module Henchman
274
274
 
275
275
  ret = %x(#{applescript_command(update_track_location_script selection[:id], local_file)}).chomp
276
276
  if ret.empty? || ret == '0'
277
- puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
278
- "Could not update location of #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')} to #{local_file}"
279
277
  false
280
278
  else
281
279
  true
@@ -35,7 +35,8 @@ module Henchman
35
35
  end
36
36
 
37
37
  def get_time_last_downloaded track
38
- @cache[:history][track[:id].to_i]
38
+ id = track[:id].to_i
39
+ (@cache[:history].include?(id)) ? @cache[:history][id] : DateTime.new
39
40
  end
40
41
 
41
42
  def tag track
@@ -60,6 +61,17 @@ module Henchman
60
61
  end
61
62
  end
62
63
 
64
+ def clear type, value
65
+ raise "Invalid type #{type}" if !@cache[:ignore].keys.include? type
66
+ if @cache[:ignore][type].include? value
67
+ @cache[:ignore][type].delete value
68
+ puts "Deleting #{type} #{value} from cache"
69
+ else
70
+ puts "#{type} #{value} not found"
71
+ end
72
+ flush
73
+ end
74
+
63
75
  end
64
76
 
65
77
  end
@@ -7,7 +7,6 @@ module Henchman
7
7
  class Clean
8
8
 
9
9
  def self.run played_date
10
-
11
10
  puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
12
11
  "Cleanup Starting"
13
12
 
@@ -44,20 +43,20 @@ module Henchman
44
43
 
45
44
  def self.cleanup track
46
45
  filepath = track[:path]
47
- File.delete filepath
48
- @cache.delete track
49
- puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
50
- "Deleted #{filepath}"
46
+ begin
47
+ File.delete filepath
48
+ @cache.delete track
49
+ puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
50
+ "Deleted #{filepath}"
51
51
 
52
- while File.dirname(filepath) != @config[:root]
53
- filepath = File.dirname(filepath)
54
- begin
52
+ while File.dirname(filepath) != @config[:root]
53
+ filepath = File.dirname(filepath)
55
54
  Dir.rmdir(filepath)
56
55
  puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
57
56
  "Deleted #{filepath}"
58
- rescue SystemCallError => msg
59
- break
60
57
  end
58
+ rescue SystemCallError => msg
59
+ # do nothing
61
60
  end
62
61
  end
63
62
 
@@ -34,7 +34,7 @@ module Henchman
34
34
  if config[:root].empty? || agree("\nUpdate local music directory? (y/n) ")
35
35
  get_local_root config
36
36
  end
37
-
37
+
38
38
  Dir.mkdir(File.dirname(config_file)) if !File.exists?(File.dirname(config_file))
39
39
  File.open(config_file, "w") { |f| f.write( config.to_yaml ) }
40
40
  puts "\nConfiguration complete! Run `henchman start` to start the daemon."
@@ -43,10 +43,10 @@ module Henchman
43
43
  def self.connect config={}
44
44
  begin
45
45
  config = YAML.load_file(File.expand_path("~/.henchman/config")) if config.empty?
46
- client = DropboxClient.new(config[:dropbox][:access_token])
47
- account_info = client.account_info()
46
+ client = Dropbox::Client.new config[:dropbox][:access_token]
47
+ account_info = client.get_current_account()
48
48
  puts "Successfully connected to Dropbox: "
49
- puts " #{account_info['display_name']} [#{account_info['email']}]"
49
+ puts " #{account_info.display_name} [#{account_info.email}]"
50
50
  return client
51
51
  rescue StandardError => err
52
52
  puts "Error connecting to Dropbox account (#{err}). Try deleting the "\
@@ -91,8 +91,6 @@ module Henchman
91
91
  end
92
92
 
93
93
  def self.get_dropbox_root config, client
94
- # paths = Hash.new
95
- # build_dropbox_dirs(paths, client, '/', 0)
96
94
  not_done = true
97
95
  while not_done
98
96
  path = ask("Enter the path to your music directory in Dropbox: (? for help)" )
@@ -115,15 +113,28 @@ module Henchman
115
113
  end
116
114
  end
117
115
 
118
- # def self.build_dropbox_dirs paths, client, path, level
119
- # return if level == 2
120
- # metadata = client.metadata(path)
121
- # metadata['contents'].each do |elem|
122
- # next if !elem['is_dir']
123
- # paths[elem['path']] = Hash.new
124
- # build_dropbox_dirs(paths[elem['path']], client, elem['path'], level+1)
125
- # end
126
- # end
116
+ def self.collect_exts
117
+ config_file = File.expand_path('~/.henchman/config')
118
+ config = YAML.load_file(config_file)
119
+ client = connect config
120
+ exts = Hash.new
121
+ collect_exts_rec client, config[:dropbox][:root], exts
122
+
123
+ puts ""
124
+ exts.each_key { |k| puts k }
125
+ end
126
+
127
+ def self.collect_exts_rec client, path, exts
128
+ metadata = client.metadata(path)
129
+ metadata['contents'].each_with_index do |c, i|
130
+ print "\rCollecting#{'.'*(i%4)}#{' '*(3-(i%4))}"
131
+ if c['is_dir']
132
+ collect_exts_rec client, c['path'], exts
133
+ else
134
+ exts[File.extname(c['path'])] = true
135
+ end
136
+ end
137
+ end
127
138
 
128
139
  def self.get_local_root config
129
140
  not_done = true
@@ -1,4 +1,4 @@
1
- require "dropbox"
1
+ require "dbx_assistant"
2
2
  require "applescript"
3
3
  require "cache"
4
4
  require "yaml"
@@ -7,7 +7,9 @@ module Henchman
7
7
 
8
8
  class Core
9
9
 
10
- def self.run
10
+ def self.run args
11
+ debug = true if args[0] == 'debug'
12
+
11
13
  @appleScript = Henchman::AppleScript.new
12
14
  @cache = Henchman::Cache.new
13
15
  @update_cache = false
@@ -23,6 +25,10 @@ module Henchman
23
25
  @config[:delimiter_major] = Henchman::Templates.config[:delimiter_major]
24
26
  File.open(config_file, "w") { |f| f.write( @config.to_yaml ) }
25
27
  end
28
+ if !(@config.include? :file_extensions)
29
+ @config[:file_extensions] = Henchman::Templates.config[:file_extensions]
30
+ File.open(config_file, "w") { |f| f.write( @config.to_yaml ) }
31
+ end
26
32
 
27
33
  @cache.config @config
28
34
  rescue StandardError => err
@@ -33,10 +39,10 @@ module Henchman
33
39
 
34
40
  @appleScript.setup @config
35
41
  begin
36
- @dropbox = Henchman::DropboxAssistant.new @config
37
- rescue
42
+ @dropbox = Henchman::DropboxAssistant.new @config, debug
43
+ rescue StandardError => msg
38
44
  puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
39
- "Error connecting to Dropbox. Try rerunning `henchman configure`"
45
+ "Error connecting to Dropbox (#{msg}). Try rerunning `henchman configure`"
40
46
  return
41
47
  end
42
48
 
@@ -144,7 +150,10 @@ module Henchman
144
150
  updated = @appleScript.set_track_location track, file_save_path
145
151
 
146
152
  # if the update failed, remove that file
147
- cleanup file_save_path, track if !updated
153
+ if !updated
154
+ cleanup file_save_path, track
155
+ raise "Could not update location of #{track.reject{|k,v| k == :path || k == :id}.values.join(':')} to #{file_save_path}"
156
+ end
148
157
  end
149
158
  rescue StandardError => err
150
159
  puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|#{err}"
@@ -0,0 +1,185 @@
1
+ require 'dropbox'
2
+ require 'yaml'
3
+ require 'json'
4
+
5
+ module Henchman
6
+
7
+ class DropboxAssistant
8
+
9
+ def initialize config, debug
10
+ begin
11
+ @search_limit = 500
12
+ @debug = debug
13
+ @config = config
14
+ @client = Dropbox::Client.new @config[:dropbox][:access_token]
15
+
16
+ # stop words from http://nlp.stanford.edu/IR-book/html/htmledition/dropping-common-terms-stop-words-1.html
17
+ @stop_words = ['a', 'an', 'and', 'are', 'as', 'at', 'be', 'by', 'for', 'from',
18
+ 'has', 'he', 'in', 'is', 'it', 'its', 'of', 'on', 'that', 'the',
19
+ 'to', 'was', 'were', 'will', 'with']
20
+ true
21
+ rescue DropboxError => msg
22
+ puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
23
+ "Couldn't connect to Dropbox (#{msg}). "\
24
+ "Run `henchman stop` then `henchman configure` "\
25
+ "to configure Dropbox connection."
26
+ false
27
+ end
28
+ end
29
+
30
+ def download selection, dropbox_path
31
+ puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
32
+ "Downloading #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')} from #{dropbox_path}"
33
+ begin
34
+ # download the file
35
+ content, body = @client.download dropbox_path
36
+
37
+ # make sure we have the directory to put it in
38
+ trgt_dir = File.join @config[:root], selection[:artist], selection[:album]
39
+ puts trgt_dir if @debug
40
+ system 'mkdir', '-p', trgt_dir
41
+
42
+ # save the file
43
+ file_save_path = File.join trgt_dir, File.basename(dropbox_path)
44
+ puts file_save_path if @debug
45
+ open(file_save_path, 'w') {|f| f.puts body }
46
+ file_save_path
47
+ rescue DropboxError => msg
48
+ puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
49
+ "Error downloading Dropbox file #{dropbox_path}: #{msg}"
50
+ false
51
+ rescue StandardError => msg
52
+ puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
53
+ "Error saving Dropbox file #{dropbox_path} to #{trgt_dir}: #{msg}"
54
+ false
55
+ end
56
+ end
57
+
58
+ def search value, filter = nil, dir = @config[:dropbox][:root]
59
+ puts "Searching for #{value} in #{dir}, filtering by <#{filter}>" if @debug
60
+ begin
61
+ results = @client.search dir, value, 0, @search_limit
62
+ puts "#{results.length} total results found" if @debug
63
+ if filter == :dir
64
+ results.reject! { |result| !result.is_a? Dropbox::FolderMetadata }
65
+ elsif filter == :file
66
+ results.reject! { |result| !result.is_a? Dropbox::FileMetadata ||
67
+ !(@config[:file_extensions].include?(File.extname(result.path_lower)[1..-1])) }
68
+ end
69
+ puts "Returning #{results.length} results for `search` (after filtering)" if @debug
70
+ return results
71
+ rescue DropboxError => msg
72
+ raise "Error accessing Dropbox Search API|#{value}|#{dir}|#{msg}"
73
+ end
74
+ end
75
+
76
+ def get_results track, artist
77
+ puts "`get_results` for #{track} by #{artist}" if @debug
78
+ # Search Dropbox for the file
79
+ # We're only not filtering to get files because we want to check if we get 1000 results
80
+ # (i.e. a maxed out playload) back. This is because the filtering happens in OUR client,
81
+ # not in the Dropbox search. We're doing a simple search on only track name because we
82
+ # want to minimize the number of network calls, and USUALLY this is good enough
83
+ results = search track
84
+
85
+ # If we get 1000 results back, it means we probably have a REALLY simple song title
86
+ # and we're not assured to have the target song in our payload, since we maxed it
87
+ # out. So, we'll do another search call on the artist
88
+ if results.length == @search_limit
89
+ puts "Maximum (#{@search_limit}) results returned" if @debug
90
+ results.clear
91
+ album_dirs = search artist, :dir
92
+ album_dirs.each do |album|
93
+ tmp_rslts = search track, :file, album['path']
94
+ results.push(*tmp_rslts)
95
+ end
96
+ else # Otherwise, filter off all the directories and things without the right extensions
97
+ puts "Filtering out directories and incorrect file extensions" if @debug
98
+ results.reject! { |result| !result.is_a? Dropbox::FileMetadata ||
99
+ !(@config[:file_extensions].include?(File.extname(result.path_lower)[1..-1])) }
100
+ end
101
+ puts "Returning #{results.length} results from `get_results`" if @debug
102
+ return results
103
+ end
104
+
105
+ def search_for selection
106
+ puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
107
+ "Searching for #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')}"
108
+
109
+ results = get_results selection[:track], selection[:artist]
110
+
111
+ # if we still don't have any results, try dropping any brackets and paranthesis
112
+ if results.empty? && (selection[:track].match(%r( *\[.*\] *)) || selection[:track].match(%r( *\(.*\) *)))
113
+ puts "No results. Trying without brackets or parenthesis" if @debug
114
+ track = selection[:track].gsub(%r( *\[.*\] *), " ").gsub(%r( *\(.*\) *), " ")
115
+ results = get_results track, selection[:artist]
116
+ end
117
+
118
+ # if there were no results, raise err
119
+ if results.empty?
120
+ raise "Track not found in Dropbox: #{selection.reject{|k,v| k == :id}.values.join(':')}"
121
+ else
122
+ scores = Hash.new 0
123
+ tokens = Array.new
124
+ track_tokens = Array.new
125
+ [:artist, :album].each do |identifier|
126
+ tokens |= selection[identifier].downcase
127
+ .gsub(%r( +), " ")
128
+ .gsub(%r(-+), "-")
129
+ .strip
130
+ .split(/[\s-]/)
131
+ .delete_if{ |t| @stop_words.include? t }
132
+ end
133
+ @config[:file_extensions].each do |extension|
134
+ track_tokens |= selection[:track].downcase
135
+ .gsub(%r( +), " ")
136
+ .gsub(%r(-+), "-")
137
+ .strip
138
+ .split(/[\s-]/)
139
+ .map { |t| "#{t}.#{extension}" }
140
+ end
141
+
142
+ if @debug
143
+ puts ":artist and :album tokens: #{tokens.inspect}"
144
+ puts ":track tokens: #{track_tokens.inspect}"
145
+ end
146
+
147
+ results.each do |result|
148
+ dir = "#{File.dirname(result.path_lower)}/"
149
+ basename = " #{File.basename(result.path_lower)}"
150
+ tokens.each do |token|
151
+ if dir =~ %r(.*[\s\/-]#{token}[\s\/-].*)
152
+ puts "Token #{token} found in #{dir}" if @debug
153
+ if results.length == 1
154
+ return result.path_display
155
+ else
156
+ scores[result.path_display] += 1
157
+ end
158
+ end
159
+ end
160
+ track_tokens.each do |token|
161
+ if basename =~ %r([.]*[\s-]+#{token})
162
+ puts "Token #{token} found in #{basename}" if @debug
163
+ scores[result.path_display] += 1
164
+ end
165
+ end
166
+ end
167
+
168
+ # if the we only had one track and we're here, that means the path didn't contain
169
+ # any of the album or artist tokens, so we'll say we couldn't find it
170
+ if results.length == 1
171
+ raise "Track not found in Dropbox: #{selection.reject{|k,v| k == :id}.values.join(':')}"
172
+ end
173
+
174
+ # return the path that has the highest score
175
+ scores = scores.sort_by { |path, score| score }
176
+ if @debug
177
+ scores.each { |score| puts score.join ': ' }
178
+ end
179
+ scores[-1][0]
180
+ end
181
+ end
182
+
183
+ end
184
+
185
+ end
@@ -16,7 +16,7 @@ module Henchman
16
16
  c.syntax = 'henchman start'
17
17
  c.description = 'Starts the henchman daemon'
18
18
  c.action do |args, options|
19
- Henchman::LaunchdHandler.start
19
+ Henchman::LaunchdHandler.start args
20
20
  end
21
21
  end
22
22
 
@@ -40,7 +40,7 @@ module Henchman
40
40
  c.syntax = 'henchman run'
41
41
  c.description = 'Main interface into henchman. Should not be ran manually.'
42
42
  c.action do |args, options|
43
- Henchman::Core.run
43
+ Henchman::Core.run args
44
44
  end
45
45
  end
46
46
 
@@ -55,5 +55,31 @@ module Henchman
55
55
  end
56
56
  end
57
57
 
58
+ command :extensions do |c|
59
+ c.syntax = 'henchman extensions'
60
+ c.description = 'Collect file extensions'
61
+ c.action do |args, options|
62
+ Henchman.collect_exts
63
+ end
64
+ end
65
+
66
+ command :log do |c|
67
+ c.syntax = 'henchman log [options]'
68
+ c.description = 'Tails the henchman stdout log'
69
+ c.option '--n <number>', Integer, 'Number of lines to tail'
70
+ c.action do |args, options|
71
+ options.default :n => 10
72
+ puts `tail -n #{options.n} #{File.expand_path('~/.henchman/stdout.log')}`
73
+ end
74
+ end
75
+
76
+ command :clear do |c|
77
+ c.syntax = 'henchman clear <artist/playlist> <title>'
78
+ c.description = 'Clears the the artist or playlist from the cache'
79
+ c.action do |args, options|
80
+ @cache = Henchman::Cache.new
81
+ @cache.clear args[0].to_sym, args[1..-1].join(' ')
82
+ end
83
+ end
58
84
  end
59
85
  end
@@ -1,3 +1,3 @@
1
1
  module Henchman
2
- VERSION = "0.3.3"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -4,7 +4,7 @@ module Henchman
4
4
 
5
5
  class LaunchdHandler
6
6
 
7
- def self.start
7
+ def self.start args
8
8
  if !internet_connection?
9
9
  puts "No internet connection detected - unable to verify correct configuration."
10
10
  return if !agree("Launch henchman anyways? (y/n) ")
@@ -22,7 +22,7 @@ module Henchman
22
22
  shell_script_path_clean = File.expand_path("~/.henchman/clean.sh")
23
23
  cache_path = File.expand_path("~/.henchman/cache")
24
24
  File.write(plist_path_main, plist_main)
25
- File.write(shell_script_path_main, Henchman::Templates.shell_script('run'))
25
+ File.write(shell_script_path_main, Henchman::Templates.shell_script('run', args))
26
26
  File.write(plist_path_clean, plist_clean)
27
27
  File.write(shell_script_path_clean, Henchman::Templates.shell_script('clean'))
28
28
  File.open(cache_path, "w") { |f| f.write( Henchman::Templates.cache.to_yaml ) }
@@ -60,9 +60,9 @@ module Henchman
60
60
  "</plist>"
61
61
  end
62
62
 
63
- def self.shell_script command
63
+ def self.shell_script command, args = []
64
64
  "#!/bin/sh\n"\
65
- "#{`which henchman`.chomp} #{command}"
65
+ "#{`which henchman`.chomp} #{command} #{args.join(' ')}"
66
66
  end
67
67
 
68
68
  def self.config
@@ -77,7 +77,8 @@ module Henchman
77
77
  :poll_track => 3,
78
78
  :reprompt_timeout => 300,
79
79
  :delimiter => '|~|',
80
- :delimiter_major => '|?|'
80
+ :delimiter_major => '|?|',
81
+ :file_extensions => ['mp3', 'm4a']
81
82
  }
82
83
  end
83
84
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: henchman-sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Merritt
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-13 00:00:00.000000000 Z
11
+ date: 2016-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.4'
27
27
  - !ruby/object:Gem::Dependency
28
- name: dropbox-sdk
28
+ name: dropbox-sdk-v2
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.6'
33
+ version: '0.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.6'
40
+ version: '0.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -104,7 +104,7 @@ files:
104
104
  - lib/clean.rb
105
105
  - lib/configure.rb
106
106
  - lib/core.rb
107
- - lib/dropbox.rb
107
+ - lib/dbx_assistant.rb
108
108
  - lib/henchman.rb
109
109
  - lib/henchman/version.rb
110
110
  - lib/launchd_handler.rb
@@ -1,101 +0,0 @@
1
- require 'dropbox_sdk'
2
- require 'yaml'
3
- require 'json'
4
-
5
- module Henchman
6
-
7
- class DropboxAssistant
8
-
9
- def initialize config
10
- begin
11
- @config = config
12
- @client = DropboxClient.new(@config[:dropbox][:access_token])
13
- true
14
- rescue DropboxError => msg
15
- puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
16
- "Couldn't connect to Dropbox (#{msg}). "\
17
- "Run `henchman stop` then `henchman configure` "\
18
- "to configure Dropbox connection."
19
- false
20
- end
21
- end
22
-
23
- def download selection, dropbox_path
24
- puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
25
- "Downloading #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')}"
26
- begin
27
- # download the file
28
- content = @client.get_file(dropbox_path)
29
-
30
- # make sure we have the directory to put it in
31
- trgt_dir = File.join @config[:root], selection[:artist], selection[:album]
32
- system 'mkdir', '-p', trgt_dir
33
-
34
- # save the file
35
- file_save_path = File.join trgt_dir, File.basename(dropbox_path)
36
- open(file_save_path, 'w') {|f| f.puts content }
37
- file_save_path
38
- rescue DropboxError => msg
39
- puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
40
- "Error downloading Dropbox file #{dropbox_path}: #{msg}"
41
- false
42
- rescue StandardError => msg
43
- puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
44
- "Error saving Dropbox file #{dropbox_path} to #{trgt_dir}: #{msg}"
45
- false
46
- end
47
- end
48
-
49
- def search_for selection
50
- puts "#{DateTime.now.strftime('%m-%d-%Y %H:%M:%S')}|"\
51
- "Searching for #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')}"
52
-
53
- # search Dropbox for the file
54
- begin
55
- results = @client.search(@config[:dropbox][:root], selection[:track])
56
- rescue DropboxError => msg
57
- raise "Error accessing Dropbox Search API on #{selection.reject{|k,v| k == :path || k == :id}.values.join(':')}: #{msg}"
58
- end
59
-
60
- # get rid of any results that are directories
61
- results.reject! { |result| result['is_dir'] }
62
-
63
- # if we still don't have any results, try dropping any brackets and paranthesis
64
- if results.empty? && (selection[:track].match(%r( *\[.*\] *)) || selection[:track].match(%r( *\(.*\) *)))
65
- track = selection[:track].gsub(%r( *\[.*\] *), " ").gsub(%r( *\(.*\) *), " ")
66
- results = @client.search(@config[:dropbox][:root], track)
67
- results.reject! { |result| result['is_dir'] }
68
- end
69
-
70
- # if there were no results, raise err
71
- if results.empty?
72
- raise "Track not found in Dropbox: #{selection.reject{|k,v| k == :id}.values.join(':')}"
73
-
74
- # if there's only one result, return it
75
- elsif results.length == 1
76
- results[0]['path']
77
-
78
- # if there are multiple results, score them based on artist + album
79
- else
80
- scores = Hash.new 0
81
- results.each do |result|
82
- [:artist, :album].each do |identifier|
83
- tokens = selection[identifier].downcase
84
- .gsub(%r( +), " ")
85
- .gsub(%r(-+), "-")
86
- .strip
87
- .split(/[\s-]/)
88
- tokens.each do |token|
89
- scores[result['path']] += 1 if result['path'].downcase.include? token
90
- end
91
- end
92
- end
93
-
94
- # return the path that has the highest score
95
- (scores.sort_by { |path, score| score })[-1][0]
96
- end
97
- end
98
-
99
- end
100
-
101
- end