class Robut::Plugin::Rdio

A plugin that hooks into Rdio, allowing you to queue songs from HipChat. key and secret must be set before we can deal with any Rdio commands. Additionally, you must call start_server in your Chatfile to start the Rdio web server.

Constants

RESULT_DISPLAYER

Attributes

domain[RW]

The domain associated with token. Defaults to localhost.

host[RW]

The host the Rdio web player will run on. Defaults to localhost.

key[RW]

Your Rdio API Key

port[RW]

The port the Rdio web player will run on. Defaults to 4567.

secret[RW]

Your Rdio API app secret

token[RW]

The playback token for domain. If you're accessing Rdio on localhost, you shouldn't need to change this. Otherwise, download the rdio-python plugin:

https://github.com/rdio/rdio-python

and generate a new token for your domain:

./rdio-call --consumer-key=YOUR_CONSUMER_KEY --consumer-secret=YOUR_CONSUMER_SECRET getPlaybackToken domain=YOUR_DOMAIN

Public Class Methods

start_server() click to toggle source

Starts a Robut::Plugin::Rdio::Server server for communicating with the actual Rdio web player. You must call this in the Chatfile if you plan on using this gem.

# File lib/robut-rdio.rb, line 43
def self.start_server
  @server = Thread.new { Server.run! :host => (host || "localhost"), :port => (port || 4567) }
  Server.token = self.token || "GAlNi78J_____zlyYWs5ZG02N2pkaHlhcWsyOWJtYjkyN2xvY2FsaG9zdEbwl7EHvbylWSWFWYMZwfc="
  Server.domain = self.domain || "localhost"
end

Public Instance Methods

command?(request) click to toggle source

@param [String,Array] request that is being evaluated as a command request @return [Boolean]

# File lib/robut-rdio.rb, line 145
def command?(request)
  Array(request).join(' ') =~ /^(?:play|(?:un)?pause|next|restart|back|clear)$/
end
establish_server_callbacks!() click to toggle source

Because an instance of this plugin is not created until the Robut client has recieved at least one message. The server callbacks need to be created during the handle request. This allows for the server to communicate back through the Robut communication channel that it receives the messages.

# File lib/robut-rdio.rb, line 55
def establish_server_callbacks!
  Server.reply_callback ||= lambda{|message| reply(message, :room)}
  Server.state_callback ||= lambda{|message| reply("/me #{message}", :room)}
end
handle(time, sender_nick, message) click to toggle source

Queues songs into the Rdio web player. @nick play search query will queue the first search result matching 'search query' into the web player. It can be an artist, album, or song.

# File lib/robut-rdio.rb, line 160
def handle(time, sender_nick, message)
  
  establish_server_callbacks!
  
  words = words(message)
  
  if sent_to_me?(message)

    if play?(words)

      play_result *parse_tracks_to_play(words)
      
    elsif search_and_play?(words)
      
      search_and_play_criteria = words[1..-1].join(" ")
      
      unless search_and_play_result search_and_play_criteria
        reply("I couldn't find '#{search_and_play_criteria}' on Rdio.")
      end
      
    elsif search?(words)
      
      find words.join(' ')[search_regex,-1]
    
    elsif skip_album?(message)

      run_command("next_album")

    else command?(words)
      
      run_command(words.join("_"))
      
    end
    
  end
  
end
parse_tracks_to_play(track_request) click to toggle source

@param [Array,String] track_request the play request that is going to be

parsed for available tracks.

@return [Array] track numbers that were identified.

@example Requesting multiple tracks

"play 1"
"play 1 2"
"play 1,2"
"play 1-3"
"play 1, 2 4-6"
"play all"
# File lib/robut-rdio.rb, line 105
def parse_tracks_to_play(track_request)
  if Array(track_request).join(' ') =~ /play all/
    [ 'all' ]
  else
    Array(track_request).join(' ')[play_results_regex,-1].to_s.split(/(?:\s|,\s?)/).map do |track| 
      tracks = track.split("-")
      (tracks.first.to_i..tracks.last.to_i).to_a
    end.flatten
  end
end
play?(request) click to toggle source

@param [String,Array] request that is being evaluated as a play request @return [Boolean]

# File lib/robut-rdio.rb, line 86
def play?(request)
  Array(request).join(' ') =~ play_results_regex
end
play_results_regex() click to toggle source

@param [String,Array] request that is being evaluated as a play request @return [Boolean]

# File lib/robut-rdio.rb, line 78
def play_results_regex
  /^(?:play)?\s?(?:result)?\s?((?:\d[\s,-]*)+|all)$/
end
results() click to toggle source

As the plugin is initialized each time a request is made, the plugin maintains the state of the results from the last search request to ensure that it will be available when someone makes another request.

# File lib/robut-rdio.rb, line 203
def results
  @@results
end
search?(request) click to toggle source

@param [String,Array] request that is being evaluated as a search request @return [Boolean]

# File lib/robut-rdio.rb, line 128
def search?(request)
  Array(request).join(' ') =~ search_regex
end
search_and_play?(request) click to toggle source

@param [String,Array] request that is being evaluated as a search and playback

request

@return [Boolean]

# File lib/robut-rdio.rb, line 137
def search_and_play?(request)
  Array(request).join(' ') =~ /^play\b[^\b]+/
end
search_regex() click to toggle source

@return [Regex] that is used to match searches for their parameters @see rubular.com/?regex=(find%7Cdo%20you%20have(%5Csany)%3F)%5Cs%3F(.%2B%5B%5E%3F%5D)%5C%3F%3F

# File lib/robut-rdio.rb, line 120
def search_regex
  /(find|do you have(\sany)?)\s?(.+[^?])\??/
end
skip_album?(message) click to toggle source

@param [String,Array] request that is being evaluated as a skip album request @return [Boolean]

# File lib/robut-rdio.rb, line 153
def skip_album?(message)
  message =~ /(next|skip) album/
end
usage() click to toggle source

Returns a description of how to use this plugin

# File lib/robut-rdio.rb, line 61
def usage
  [
    "#{at_nick} play <song> - queues <song> for playing",
    "#{at_nick} play album <album> - queues <album> for playing",
    "#{at_nick} play track <track> - queues <track> for playing",
    "#{at_nick} play/unpause - unpauses the track that is currently playing",
    "#{at_nick} next - move to the next track",
    "#{at_nick} next|skip album - skip all tracks in the current album group",
    "#{at_nick} restart - restart the current track"
  ]
end

Private Instance Methods

find(query) click to toggle source
# File lib/robut-rdio.rb, line 226
def find(query)
  reply("Searching for: #{query}...")
  @@results = search(query)

  result_display = format_results(@@results)
  reply(result_display)
end
format_result(search_result, index) click to toggle source
# File lib/robut-rdio.rb, line 298
def format_result(search_result, index)
  response = RESULT_DISPLAYER[search_result.class].call(search_result)
  puts response
  "#{index}: #{response}"
end
format_results(results) click to toggle source
# File lib/robut-rdio.rb, line 234
def format_results(results)
  result_display = ""
  results.each_with_index do |result, index|
    result_display += format_result(result, index) + "\n"
  end
  result_display
end
has_result?(number) click to toggle source
# File lib/robut-rdio.rb, line 282
def has_result?(number)
  !@@results[number].nil?
end
has_results?() click to toggle source
# File lib/robut-rdio.rb, line 278
def has_results?
  @@results && @@results.any?
end
play_result(*requests) click to toggle source
# File lib/robut-rdio.rb, line 242
def play_result(*requests)
  
  if !has_results?
    reply("I don't have any search results") and return
  end
  
  requests = requests.flatten.compact
  
  # Queue all the songs when the request is 'all'
  
  if requests.first == "all"
    results.length.times {|index| queue result_at(index) }
    return
  end
  
  requests.flatten.each do |request|
    
    if has_result?(request.to_i)
      queue result_at(request.to_i)
    else
      reply("I don't have that result")
    end
    
  end
  
end
queue(result) click to toggle source
# File lib/robut-rdio.rb, line 290
def queue(result)
  Server.queue << result.key
  name = result.name
  name = "#{result.artist_name} - #{name}" if result.respond_to?(:artist_name) && result.artist_name
  reply("Queuing: #{name}")
end
result_at(number) click to toggle source
# File lib/robut-rdio.rb, line 286
def result_at(number)
  @@results[number]
end
run_command(command) click to toggle source
# File lib/robut-rdio.rb, line 222
def run_command(command)
  Server.command << command
end
search_and_play_result(message) click to toggle source
# File lib/robut-rdio.rb, line 269
def search_and_play_result(message)
  
  if result = Array(search(message)).first
    queue(result)
    true
  end
  
end