#!/usr/bin/env ruby require 'douban.fm' require 'optparse' require 'ostruct' def main options = OpenStruct.new options.verbose = false opts = OptionParser.new do |opts| opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [OPTIONS]" opts.on('-u', '--user email', 'douban.fm account name, normally an email address', 'if not provided, will play anonymous playlist') do |email| options.email = email end opts.on('-p', '--password [password]', 'douban.fm account password', 'if not provided, will be asked') do |password| options.password = password end opts.on('-m', '--mpd', 'do not play by it own, send playlist to Music Player Daemon') do options.mpd = true end opts.on('-c', '--channel channel', 'which channel to play', 'if not provided, channel 0 will be selected but who knows what it is') do |channel| options.channel = channel end opts.on('-l', '--list', 'list all available channels') do options.list = true end opts.on('-v', '--verbose', 'verbose mode') do options.verbose = true end opts.on_tail('-h', '--help', 'show this message') do puts opts exit end end opts.parse! if options.verbose logger = DoubanFM::ConsoleLogger.new else logger = DoubanFM::DummyLogger.new end if options.list douban_fm = DoubanFM::DoubanFM.new(logger) douban_fm.fetch_channels douban_fm.channels['channels'].sort_by { |i| i['channel_id'] }.each do |channel| channel_id = channel['channel_id'] puts "#{channel_id}.#{' ' * (4 - channel_id.to_s.length)}#{channel['name']}" end exit end if options.channel.nil? options.channel = 0 end if options.email.nil? douban_fm = DoubanFM::DoubanFM.new(logger) logger.log('play anonymous playlist') else if options.password.nil? or options.password.empty? require 'highline/import' options.password = ask("Enter password: ") { |q| q.echo = false } end douban_fm = DoubanFM::DoubanFM.new(logger, options.email, options.password) douban_fm.login logger.log("login as user [#{options.email}]") end douban_fm.select_channel(options.channel) logger.log("select channel #{options.channel}") if options.mpd.nil? play_proc = proc do |waiting| if waiting begin logger.log('fetch next playlist') douban_fm.fetch_next_playlist rescue logger.log('session expired, relogin') douban_fm.login logger.log('fetch next playlist') douban_fm.fetch_next_playlist end logger.log('play current playlist') douban_fm.play do |waiting| play_proc.call(waiting) end end end play_proc.call(true) else # there are a lot more chances to get stack overflow in this mode, # so can't use the proc way while true douban_fm.add_to_mpd sleep 10 end end end main sleep