module Henchman

Constants

VERSION

Public Class Methods

collect_exts() click to toggle source
# 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) click to toggle source
# File lib/configure.rb, line 127
def self.collect_exts_rec client, path, exts
  metadata = client.metadata(path)
  metadata['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
configure() click to toggle source
# 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={}) click to toggle source
# 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]
    account_info = client.get_current_account()
    puts "Successfully connected to Dropbox: "
    puts "  #{account_info.display_name} [#{account_info.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) click to toggle source
# 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) click to toggle source
# 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
      metadata = client.metadata(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) click to toggle source
# 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
run() click to toggle source
# 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