Module: Henchman

Defined in:
lib/core.rb,
lib/cache.rb,
lib/clean.rb,
lib/henchman.rb,
lib/configure.rb,
lib/templates.rb,
lib/applescript.rb,
lib/dbx_assistant.rb,
lib/launchd_handler.rb,
lib/henchman/version.rb

Defined Under Namespace

Classes: AppleScript, Cache, Clean, Core, DropboxAssistant, LaunchdHandler, Templates

Constant Summary collapse

VERSION =
"0.4.0"

Class Method Summary collapse

Class Method Details

.collect_extsObject



116
117
118
119
120
121
122
123
124
125
# File 'lib/configure.rb', line 116

def self.collect_exts
  config_file = File.expand_path('~/.henchman/config')
  config = YAML.load_file(config_file)
  client = connect config
  exts = Hash.new
  collect_exts_rec client, config[:dropbox][:root], exts

  puts ""
  exts.each_key { |k| puts k }
end

.collect_exts_rec(client, path, exts) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/configure.rb', line 127

def self.collect_exts_rec client, path, exts
   = client.(path)
  ['contents'].each_with_index do |c, i|
    print "\rCollecting#{'.'*(i%4)}#{' '*(3-(i%4))}"
    if c['is_dir']
      collect_exts_rec client, c['path'], exts
    else
      exts[File.extname(c['path'])] = true
    end
  end
end

.configureObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/configure.rb', line 7

def self.configure
  config_file = File.expand_path('~/.henchman/config')
  if !File.exists?(config_file)
    config = Henchman::Templates.config
  else
    config = YAML.load_file(config_file)
  end

  if config[:dropbox][:key].empty? ||
     config[:dropbox][:secret].empty? ||
     config[:dropbox][:access_token].empty? ||
     agree("Update Dropbox configuration? (y/n) ")
    begin
      get_dropbox_credentials config
    rescue StandardError => err
      puts err
      return
    end
  end

  client = connect config
  return if !client

  if config[:dropbox][:root].empty? || agree("\nUpdate music directory in Dropbox? (y/n) ")
    get_dropbox_root config, client
  end

  if config[:root].empty? || agree("\nUpdate local music directory? (y/n) ")
    get_local_root config
  end

  Dir.mkdir(File.dirname(config_file)) if !File.exists?(File.dirname(config_file))
  File.open(config_file, "w") { |f| f.write( config.to_yaml ) }
  puts "\nConfiguration complete! Run `henchman start` to start the daemon."
end

.connect(config = {}) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/configure.rb', line 43

def self.connect config={}
  begin
    config = YAML.load_file(File.expand_path("~/.henchman/config")) if config.empty?
    client = Dropbox::Client.new config[:dropbox][:access_token]
     = client.()
    puts "Successfully connected to Dropbox: "
    puts "  #{.display_name} [#{.email}]"
    return client
  rescue StandardError => err
    puts "Error connecting to Dropbox account (#{err}). Try deleting the "\
         "henchman configuration file (`rm ~/.henchman`) and rerunning "\
         "`henchman configure`"
    return false
  end
end

.get_dropbox_credentials(config) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/configure.rb', line 59

def self.get_dropbox_credentials config
  puts "\nYou'll need to create your own Dropbox app to integrate. "\
       "Head over to https://www.dropbox.com/developers/apps. If "\
       "you have an app already that you'd like to use, click on "\
       "that app. If not, click on the 'Create App' link. From "\
       "here, choose 'Dropbox API', 'Full Dropbox', and finally "\
       "choose an app name.\n\n"\
       "Note your app key and app secret, and enter them below. "\
       "You will then be asked to login and give access to the app. "\
       "Once you have done this, copy the Authorization Code. You "\
       "will be prompted to enter it here.\n\n"

  dbx_cfg = config[:dropbox]
  dbx_cfg[:key]    = ask("Dropbox App Key: ")
  dbx_cfg[:secret] = ask("Dropbox App Secret: ")

  flow = DropboxOAuth2FlowNoRedirect.new(dbx_cfg[:key], dbx_cfg[:secret])
  authorize_url = flow.start()

  puts '1. Go to: ' + authorize_url
  puts '2. Click "Allow" (you might have to log in first)'
  puts '3. Copy the authorization code'

  code = ask("Enter the authorization code here: ")
  print "\n"
  begin
    dbx_cfg[:access_token], dbx_cfg[:user_id] = flow.finish(code)
  rescue StandardError => msg
    dbx_cfg[:key]    = ''
    dbx_cfg[:secret] = ''
    raise "Invalid authorization code (#{msg})"
  end
end

.get_dropbox_root(config, client) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/configure.rb', line 93

def self.get_dropbox_root config, client
  not_done = true
  while not_done
    path = ask("Enter the path to your music directory in Dropbox: (? for help)" )
    if path == '?'
      puts "The path to your music directory is a unix-like path. For example: "\
           "/Some/Directory/Music\n\n"
      next
    end

    path = path.chomp('/')
    begin
       = client.(path)
      config[:dropbox][:root] = path
      puts "Dropbox music path set!\n"
      not_done = false
    rescue StandardError => err
      print "Invalid path. (#{err})"
      not_done = agree("Try again? (y/n) ")
    end
  end
end

.get_local_root(config) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/configure.rb', line 139

def self.get_local_root config
  not_done = true
  while not_done
    path = ask("Enter the path to your local music directory: (? for help)" )
    if path == '?'
      puts "This is the directory in which local music files will be stored. "\
           "For example: /Users/yourusernam/Music\n\n"
      next
    end

    path = File.expand_path(path.chomp('/'))
    if File.directory? path
      config[:root] = path
      puts "Local music path set!\n"
      not_done = false
    elsif File.directory? File.dirname(path)
      if agree("Directory doesn't exist. Create it? (y/n) ")
        Dir.mkdir(path)
        config[:root] = path
        puts "Local music path set!\n"
        not_done = false
      end
    else
      puts "Invalid path."
    end
  end
end

.runObject



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/henchman.rb', line 10

def Henchman.run
  program :name, 'Henchman'
  program :version, Henchman::VERSION
  program :description, 'Cloud music syncing for iTunes on OS X'

  command :start do |c|
    c.syntax = 'henchman start'
    c.description = 'Starts the henchman daemon'
    c.action do |args, options|
      Henchman::LaunchdHandler.start args
    end
  end

  command :stop do |c|
    c.syntax = 'henchman stop'
    c.description = 'Stops the henchman daemon'
    c.action do |args, options|
      Henchman::LaunchdHandler.stop
    end
  end

  command :configure do |c|
    c.syntax = 'henchman configure'
    c.description = 'Configures the henchman client'
    c.action do |args, options|
      Henchman.configure
    end
  end

  command :run do |c|
    c.syntax = 'henchman run'
    c.description = 'Main interface into henchman. Should not be ran manually.'
    c.action do |args, options|
      Henchman::Core.run args
    end
  end

  command :clean do |c|
    c.syntax = 'henchman clean [options]'
    c.description = 'Remove tracks from the file system that are old. '\
                    'Should not be ran manually.'
    c.option '--played_date \'true\'/\'false\'', String, 'Delete tracks based only on last played date'
    c.action do |args, options|
      options.default :played_date => 'false'
      Henchman::Clean.run options.played_date
    end
  end

  command :extensions do |c|
    c.syntax = 'henchman extensions'
    c.description = 'Collect file extensions'
    c.action do |args, options|
      Henchman.collect_exts
    end
  end

  command :log do |c|
    c.syntax = 'henchman log [options]'
    c.description = 'Tails the henchman stdout log'
    c.option '--n <number>', Integer, 'Number of lines to tail'
    c.action do |args, options|
      options.default :n => 10
      puts `tail -n #{options.n} #{File.expand_path('~/.henchman/stdout.log')}`
    end
  end

  command :clear do |c|
    c.syntax = 'henchman clear <artist/playlist> <title>'
    c.description = 'Clears the the artist or playlist from the cache'
    c.action do |args, options|
      @cache = Henchman::Cache.new
      @cache.clear args[0].to_sym, args[1..-1].join(' ')
    end
  end
end