Permalink
Browse files

Added comments and tomdoc.

Signed-off-by: Diwank Singh Tomer <diwank.singh@gmail.com>
  • Loading branch information...
1 parent b98ecda commit 100feabca67cac7cf42b89fd250b485d0bb3ef69 @creatorrr committed Apr 1, 2013
Showing with 106 additions and 50 deletions.
  1. +10 −3 README.md
  2. +3 −4 package.json
  3. +23 −5 src/index.coffee
  4. +45 −29 src/listeners.coffee
  5. +1 −0 src/pages.coffee
  6. +20 −8 src/routes.coffee
  7. +4 −1 src/socket-controller.coffee
View
@@ -8,12 +8,19 @@ This is an external [hubot-script](https://github.com/github/hubot/blob/master/R
`"hubot-rdio": "*"`
2. Tell hubot to load it. Add `"hubot-rdio"` to the `external-scripts.json` list in the hubot root folder.
3. `npm install` while you grab a beer.
-4. _(Optional but recommended)_ Set environment variable `NODE_ENV` to `production`.
+4. Set the following environment variables and start hubot using `bin/hubot` :
+ NODE_ENV: 'production'
+ RDIO_CONSUMER: '<your rdio consumer key>'
+ RDIO_SECRET: '<your rdio consumer secret>'
+
+You can get the rdio consumer key and secret by creating an app at rdio's [developer page](http://developer.rdio.com/apps/mykeys).
## Commands
-* `hubot init rdio` - To authenticate your rdio account.
-* `hubot test rdio` - To test whether authentication was successful.
+* `hubot init rdio` - Authenticate rdio.
+* `hubot play (track|artist|album) <name>` - Search and play songs.
+* `hubot play random` - Pick a random song off top charts and play it.
+* `hubot pause` - Pause currently playing song.
## Contributing
View
@@ -13,8 +13,8 @@
},
"dependencies": {
"coffeecup": "0.3.x",
- "node-rdio": "0.1.x",
- "hubot.io": "0.1.x"
+ "node-rdio": ">= 0.1.1",
+ "hubot.io": ">= 0.1.3"
},
"keywords": [
"hubot",
@@ -24,6 +24,5 @@
"author": "creatorrr",
"license": "BSD",
"readmeFilename": "README.md",
- "devDependencies": {},
- "gitHead": "773de77dc4ef7351b2078e2ddd38fe77c648739c"
+ "devDependencies": {}
}
View
@@ -1,6 +1,24 @@
-# hubot
+# Description:
+# Rdio remote control for hubot.
#
-# search rdio for song
+# Dependencies:
+# "hubot.io": ">= 0.1.3"
+# "node-rdio": ">= 0.1.1"
+# "coffeecup": "0.3.x"
+#
+# Configuration:
+# NODE_ENV: 'production'
+# RDIO_CONSUMER: '<your rdio consumer key>'
+# RDIO_SECRET: '<your rdio consumer secret>'
+#
+# Commands:
+# hubot init rdio - Authenticate rdio.
+# hubot play (track|artist|album) <name> - Search and play songs.
+# hubot play random - Pick a random song off top charts and play it.
+# hubot pause - Pause currently playing song.
+#
+# Author:
+# creatorrr
# External libraries
sockets = require 'hubot.io'
@@ -17,14 +35,14 @@ module.exports = (robot) ->
listeners = (require './listeners') robot
socketController = (require './socket-controller') robot
- # Initialize this thing.
+ # Listeners
robot.respond /init rdio/i, listeners.init
- # robot.respond /test rdio/i, listeners.test
robot.respond /play (track|artist|album) (["'\w: \-_]+).*$/i, listeners.play
- robot.respond /play whatever/i, listeners.playWhatever
+ robot.respond /play random/i, listeners.playRandom
robot.respond /pause( music){0,1}/i, listeners.pause
+ # Routes
robot.router.get '/', routes.home
robot.router.get '/login', routes.login
robot.router.get "/#{ CALLBACK }", routes.auth
View
@@ -16,40 +16,45 @@ random = (min, max) -> min + Math.floor Math.random()*(max - min + 1)
# Get random element from arr.
getRandom = (arr) -> arr[random 0, arr.length-1]
+# Check if arr empty.
+isEmpty = (arr) -> arr.length is 0
+
# Return capitalized string.
capitalize = (str) -> (str.charAt 0).toUpperCase() + str[1..]
# Capture robot instance in a closure and return interface.
module.exports = listeners = (robot) ->
+ # Get rdio client (signed if access token available).
getRdio = ->
accessToken = robot.brain.get 'RdioAccessToken'
accessSecret = robot.brain.get "RdioAccessSecret-#{accessToken}"
- if not accessToken and accessSecret
- return msg.send 'Please login to your rdio account first.'
-
- rdio = new Rdio [
- RDIO_CONSUMER
- RDIO_SECRET
- ], [
- accessToken
- accessSecret
- ]
-
- rdio
+ if accessToken and accessSecret
+ rdio = new Rdio [
+ RDIO_CONSUMER
+ RDIO_SECRET
+ ], [
+ accessToken
+ accessSecret
+ ]
- return {
- init: (msg) ->
+ else
rdio = new Rdio [
RDIO_CONSUMER
RDIO_SECRET
]
+ # Return listeners interface.
+ return {
+ init: (msg) ->
+ rdio = getRdio()
+
rdio.beginAuthentication DOMAIN+CALLBACK, (error, authUrl) ->
if error
robot.logger.debug error
return msg.send "Error: #{ error }"
+ # Get request token and save it.
requestToken = rdio.token[0]
requestSecret = rdio.token[1]
@@ -58,45 +63,56 @@ module.exports = listeners = (robot) ->
.set("RdioRequestSecret-#{requestToken}", requestSecret)
.save()
+ # Redirect user to rdio auth url.
msg.send "Go to #{ authUrl } to verify your rdio account."
- test: (msg) ->
- rdio = getRdio()
- rdio.call 'currentUser', (error, {result}) ->
- if error
- robot.logger.debug "Error: #{ error }"
- return msg.send "Error: #{ error }"
-
- msg.send "Success: #{ inspect result }"
-
pause: (msg) ->
robot.emit 'player:send', 'pause'
msg.send 'Song paused.'
- playWhatever: (msg) ->
+ playRandom: (msg) ->
rdio = getRdio()
+
+ # Get top charts on rdio.
rdio.call 'getTopCharts', {type: 'Track'}, (error, {result}) ->
if error
robot.logger.debug "Error: #{ error }"
return msg.send "Error: #{ error }"
+ # Pick random track from results and send it off to player.
track = getRandom result
robot.emit 'player:send', 'play', track
msg.send "Playing track #{ track.name }"
play: (msg) ->
- mode = capitalize msg.match[1].toLowerCase()
+ # Parse `hubot play <mode> <query>`
+ mode = msg.match[1].toLowerCase()
query = msg.match[2]
rdio = getRdio()
- rdio.call 'search', { types: mode, query: query }, (error, {result}) ->
+
+ # Callback for playing tracks.
+ playTrack = (result) ->
+ track = switch mode
+ when 'track', 'album' then result
+
+ # If mode is 'artist' then get artist station.
+ when 'artist'
+ key: result.topSongsKey
+ name: result.name
+
+ msg.send "Playing #{ mode } - #{ track.name }"
+ robot.emit 'player:send', 'play', track
+
+ # Search query.
+ rdio.call 'search', { types: (capitalize mode), query: query }, (error, {result}) ->
if error
robot.logger.debug "Error: #{ error }"
return msg.send "Error: #{ error }"
- track = result.results[0]
- robot.emit 'player:send', 'play', track
+ if isEmpty result.results
+ msg.send "No results found for '#{ query }'"
- msg.send "Playing track #{ track.name }"
+ else playTrack result.results[0]
}
View
@@ -1,3 +1,4 @@
+# External libraries
{compile} = require 'coffeecup'
templates =
View
@@ -27,6 +27,7 @@ module.exports = routes = (robot) ->
robot.logger.debug error
return msg.send "Error: #{ error }"
+ # Get request token and save it.
requestToken = rdio.token[0]
requestSecret = rdio.token[1]
@@ -35,12 +36,14 @@ module.exports = routes = (robot) ->
.set("RdioRequestSecret-#{requestToken}", requestSecret)
.save()
+ # Redirect user to rdio auth url.
res.redirect authUrl
auth: (req, res) ->
res.writeHead 200,
'Content-Type': 'text/html'
+ # Retrieve params required for obtaining access token.
requestToken = req.query['oauth_token']
requestSecret = robot.brain.get "RdioRequestSecret-#{requestToken}"
@@ -50,6 +53,7 @@ module.exports = routes = (robot) ->
return res.end pages.error
message: 'Error: Invalid request token'
+ # Init rdio with the request token.
rdio = new Rdio [
RDIO_CONSUMER
RDIO_SECRET
@@ -58,6 +62,7 @@ module.exports = routes = (robot) ->
requestSecret
]
+ # Exchange request token for access token.
rdio.completeAuthentication verifier, (error) ->
if error
robot.logger.debug error
@@ -68,6 +73,7 @@ module.exports = routes = (robot) ->
accessToken = rdio.token[0]
accessSecret = rdio.token[1]
+ # Remove obsolete keys and persist the access token.
robot.brain
.remove('RdioRequestToken')
.remove("RdioRequestSecret-#{requestToken}")
@@ -79,6 +85,7 @@ module.exports = routes = (robot) ->
.set("RdioAccessSecret-#{accessToken}", accessSecret)
.save()
+ # Send user to the player.
res.end pages.redirect
message: "Yay! Your access token is #{ accessToken }"
redirect: '/player'
@@ -90,11 +97,13 @@ module.exports = routes = (robot) ->
accessToken = robot.brain.get 'RdioAccessToken'
accessSecret = robot.brain.get "RdioAccessSecret-#{accessToken}"
+ # Ask user to authorize app if access token not available.
unless accessToken and accessSecret
return res.end pages.redirect
message: 'Please authorize rdio first.'
- redirect: '/'
+ redirect: '/login'
+ # Init rdio with the access token.
rdio = new Rdio [
RDIO_CONSUMER
RDIO_SECRET
@@ -103,19 +112,22 @@ module.exports = routes = (robot) ->
accessSecret
]
+ # Make sure user session still valid.
rdio.call 'currentUser', (error) ->
if error
res.end pages.redirect
message: 'Please authorize rdio first.'
- redirect: '/'
+ redirect: '/login'
else
{hostname} = parse DOMAIN
+
+ # Request playback token from rdio.
rdio.call 'getPlaybackToken', { domain: hostname }, (error, data) ->
- if error
- res.end pages.error
- message: "Error: #{ error }"
+ res.end page =
+ if error
+ pages.error message: "Error: #{ error }"
- else
- res.end pages.player
- playbackToken: data.result
+ else
+ # Embed playback token for the playback api.
+ pages.player playbackToken: data.result
@@ -7,8 +7,12 @@ extend = (dest, sources...) ->
dest
module.exports = (robot) ->
+ # Return singleton interface.
new ->
+ # Internal store for socket connections.
@sockets = []
+
+ # Event emitter API for interfacing with other scripts.
robot.on 'sockets:connection', (socket) =>
socket.on 'event', (args...) ->
robot.emit 'player:receive', args...
@@ -18,5 +22,4 @@ module.exports = (robot) ->
robot.on 'player:send', (args...) =>
socket.emit args... for socket in @sockets
- # Return instance
this

0 comments on commit 100feab

Please sign in to comment.