Comparing version 0.6.3 to 0.7.0
# Changelog | ||
## 0.7.0 | ||
### Breaking changes | ||
* The success event on `lastfm.request` now emits parsed JSON rather than raw text. | ||
* `RecentTracksStream.isStreaming` has been removed in favour of `RecentTracksStream.isStreaming()`. | ||
## 0.6.3 | ||
@@ -15,3 +21,4 @@ | ||
* Reinstated LastFmSession.authorise() handler options which were accidentallly removed rather than deprecated. Thanks to Vytautas Jakutis for the spot.* Fixed LastFmSession.authorise() documentation (Vytautas Jakutis) | ||
* Reinstated LastFmSession.authorise() handler options which were accidentallly removed rather than deprecated. Thanks to Vytautas Jakutis for the spot. | ||
* Fixed LastFmSession.authorise() documentation (Vytautas Jakutis) | ||
@@ -18,0 +25,0 @@ ## 0.6.0 |
@@ -1,60 +0,35 @@ | ||
var EventEmitter = require("events").EventEmitter; | ||
var utils = require("./utils"); | ||
var LastFmBase = require("./lastfm-base"); | ||
var LastFmInfo = function(lastfm, type, options) { | ||
var that = this; | ||
options = options || {}; | ||
var that = this; | ||
EventEmitter.call(this); | ||
LastFmBase.call(this); | ||
if (options.error) { | ||
this.on("error", options.error); | ||
} | ||
registerEventHandlers(options); | ||
requestInfo(type, options); | ||
if (options.success) { | ||
this.on("success", options.success); | ||
function registerEventHandlers(options) { | ||
if (options.error) { | ||
that.on("error", options.error); | ||
} | ||
if (options.success) { | ||
that.on("success", options.success); | ||
} | ||
that.registerHandlers(options.handlers); | ||
} | ||
utils.registerHandlers(this, options.handlers); | ||
if (!type) { | ||
this.emit("error", new Error("Item type not specified")); | ||
return; | ||
} | ||
var params = filterOptions(options); | ||
var method = type + ".getinfo"; | ||
var request = lastfm.request(method, params); | ||
request.on("success", success); | ||
request.on("error", error); | ||
function filterOptions(options) { | ||
var params = { }; | ||
if (type == "track") { | ||
if (typeof(options.track) == "object") { | ||
params.artist = options.track.artist["#text"]; | ||
params.track = options.track.name; | ||
params.mbid = options.track.mbid; | ||
} | ||
function requestInfo(type, options) { | ||
if (!type) { | ||
that.emit("error", new Error("Item type not specified")); | ||
return; | ||
} | ||
Object.keys(options).forEach(function(name) { | ||
if (name != "error" && name != "success" && name != "handlers" && !params[name]) { | ||
params[name] = options[name]; | ||
} | ||
}); | ||
return params; | ||
var params = that.filterParameters(options, ["error", "success", "handlers"]) | ||
, method = type + ".getinfo" | ||
, request = lastfm.request(method, params); | ||
request.on("success", success); | ||
request.on("error", error); | ||
} | ||
function success(data) { | ||
try { | ||
var response = JSON.parse(data); | ||
} | ||
catch(e) { | ||
that.emit("error", new Error(e.message + ":" + data)); | ||
return; | ||
} | ||
function success(response) { | ||
if (response[type]) { | ||
@@ -64,8 +39,2 @@ that.emit("success", response[type]); | ||
} | ||
if (response.error) { | ||
that.emit("error", new Error(response.message)); | ||
return; | ||
} | ||
that.emit("error", new Error("Unexpected error")); | ||
@@ -79,4 +48,4 @@ } | ||
LastFmInfo.prototype = Object.create(EventEmitter.prototype); | ||
LastFmInfo.prototype = Object.create(LastFmBase.prototype); | ||
module.exports = LastFmInfo; |
if (global.GENTLY_HIJACK) require = GENTLY_HIJACK.hijack(require); | ||
var http = require("http"); | ||
var querystring = require('querystring'); | ||
var EventEmitter = require("events").EventEmitter; | ||
var _ = require("underscore"); | ||
var crypto = require("crypto"); | ||
var utils = require("./utils"); | ||
var http = require("http") | ||
, querystring = require('querystring') | ||
, _ = require("underscore") | ||
, crypto = require("crypto") | ||
, LastFmBase = require("./lastfm-base"); | ||
var WRITE_METHODS = ["album.addtags", "album.removetag", "album.share", | ||
"artist.addtags", "artist.removetag", "artist.share", "artist.shout", | ||
"event.attend", "event.share", "event.shout", | ||
"library.addalbum", "library.addartist", "library.addtrack", | ||
"playlist.addtrack", "playlist.create", | ||
"radio.tune", | ||
"track.addtags", "track.ban", "track.love", "track.removetag", | ||
"track.scrobble", "track.share", "track.unban", "track.unlove", | ||
"track.updatenowplaying", | ||
"user.shout"], | ||
SIGNED_METHODS = ["auth.getmobilesession", "auth.getsession", "auth.gettoken", | ||
"radio.getplaylist"]; | ||
var LastFmRequest = module.exports = function(lastfm, method, params) { | ||
var that = this; | ||
LastFmBase.call(this); | ||
params = params || {}; | ||
EventEmitter.call(this); | ||
utils.registerHandlers(this, params.handlers); | ||
that.registerHandlers(params.handlers); | ||
var requestParams = filterParams(params); | ||
requestParams.method = method; | ||
requestParams.api_key = requestParams.api_key || lastfm.api_key; | ||
requestParams.format = requestParams.format || lastfm.format; | ||
var isWriteRequest = params.write || isWriteMethod(method); | ||
var requiresSignature = isWriteRequest || params.signed || isSignedMethod(method); | ||
if (requiresSignature) { | ||
requestParams = signParams(requestParams); | ||
sendRequest(lastfm.host, lastfm.url, params); | ||
function registerEventHandlers(handlers) { | ||
utils.registerHandlers(that, handlers); | ||
} | ||
var data = querystring.stringify(requestParams); | ||
var httpVerb = isWriteRequest ? "POST" : "GET"; | ||
sendRequest(httpVerb, lastfm.host, lastfm.url, data); | ||
function sendRequest(host, url, params) { | ||
var httpVerb = isWriteRequest() ? "POST" : "GET" | ||
, port = 80 | ||
, connection = http.createClient(port, host) | ||
, requestParams = buildRequestParams(params) | ||
, data = querystring.stringify(requestParams); | ||
function sendRequest(httpVerb, host, url, data) { | ||
var port = 80; | ||
var connection = http.createClient(port, host); | ||
connection.on("error", function(error) { | ||
@@ -46,35 +53,36 @@ that.emit("error", error); | ||
} | ||
request.on("response", handleResponse); | ||
request.on("response", chunkedResponse); | ||
request.end(); | ||
} | ||
function filterParams(params) { | ||
var paramsBlackList = ["handlers", "signed", "write"]; | ||
var filteredParams = {}; | ||
_(Object.keys(params)).each(function(key) { | ||
if (!_(paramsBlackList).include(key)) { | ||
filteredParams[key] = params[key]; | ||
} | ||
}); | ||
return filteredParams; | ||
function buildRequestParams(params) { | ||
var requestParams = that.filterParameters(params, ["handlers", "signed", "write", "error", "success"]); | ||
requestParams.method = method; | ||
requestParams.api_key = requestParams.api_key || lastfm.api_key; | ||
requestParams.format = requestParams.format || lastfm.format; | ||
if (params.track && typeof params.track === "object") { | ||
requestParams.artist = params.track.artist["#text"]; | ||
requestParams.track = params.track.name; | ||
requestParams.mbid = params.track.mbid; | ||
} | ||
if (requiresSignature()) { | ||
requestParams.api_sig = createSignature(requestParams, lastfm.secret); | ||
} | ||
return requestParams; | ||
} | ||
function requiresSignature() { | ||
return params.signed || isWriteRequest() || isSignedMethod(method); | ||
} | ||
function isWriteRequest() { | ||
return params.write || isWriteMethod(method); | ||
} | ||
function isSignedMethod(method) { | ||
var signedMethods = ["auth.getmobilesession", "auth.getsession", "auth.gettoken", | ||
"radio.getplaylist"]; | ||
return method && _(signedMethods).include(method.toLowerCase()); | ||
return method && _(SIGNED_METHODS).include(method.toLowerCase()); | ||
} | ||
function isWriteMethod(method) { | ||
var writeMethods = ["album.addtags", "album.removetag", "album.share", | ||
"artist.addtags", "artist.removetag", "artist.share", "artist.shout", | ||
"event.attend", "event.share", "event.shout", | ||
"library.addalbum", "library.addartist", "library.addtrack", | ||
"playlist.addtrack", "playlist.create", | ||
"radio.tune", | ||
"track.addtags", "track.ban", "track.love", "track.removetag", | ||
"track.scrobble", "track.share", "track.unban", "track.unlove", | ||
"track.updatenowplaying", | ||
"user.shout"]; | ||
return method && _(writeMethods).include(method.toLowerCase()); | ||
return method && _(WRITE_METHODS).include(method.toLowerCase()); | ||
} | ||
@@ -95,3 +103,3 @@ | ||
function handleResponse(response) { | ||
function chunkedResponse(response) { | ||
var data = ""; | ||
@@ -102,17 +110,32 @@ response.on("data", function(chunk) { | ||
response.on("end", function() { | ||
that.emit("success", data); | ||
if (lastfm.format !== "json") { | ||
that.emit("success", data); | ||
return; | ||
} | ||
try { | ||
var json = JSON.parse(data); | ||
if (json.error) { | ||
that.emit("error", json); | ||
return; | ||
} | ||
that.emit("success", json); | ||
} | ||
catch(e) { | ||
that.emit("error", e) | ||
} | ||
}); | ||
} | ||
function signParams(params) { | ||
function createSignature(params, secret) { | ||
var sig = ""; | ||
Object.keys(params).sort().forEach(function(key) { | ||
if (key != "format") sig += key + params[key]; | ||
if (key != "format") { | ||
sig += key + params[key]; | ||
} | ||
}); | ||
sig += lastfm.secret; | ||
params.api_sig = crypto.createHash("md5").update(sig, "utf8").digest("hex"); | ||
return params; | ||
}; | ||
sig += secret; | ||
return crypto.createHash("md5").update(sig, "utf8").digest("hex"); | ||
} | ||
}; | ||
LastFmRequest.prototype = Object.create(EventEmitter.prototype); | ||
LastFmRequest.prototype = Object.create(LastFmBase.prototype); |
@@ -1,58 +0,79 @@ | ||
var EventEmitter = require("events").EventEmitter; | ||
var utils = require("./utils"); | ||
var LastFmBase = require("./lastfm-base"); | ||
var LastFmSession = function(lastfm, user, key) { | ||
EventEmitter.call(this); | ||
this.lastfm = lastfm; | ||
this.user = user || ""; | ||
this.key = key || ""; | ||
}; | ||
var that = this; | ||
LastFmBase.call(this); | ||
user = user || ""; | ||
key = key || ""; | ||
LastFmSession.prototype = Object.create(EventEmitter.prototype); | ||
this.user = user; | ||
LastFmSession.prototype.authorise = function(token, options) { | ||
options = options || { }; | ||
if (options.error) { | ||
this.on("error", options.error); | ||
this.key = key; | ||
this.authorise = function(token, options) { | ||
authorise(token, options); | ||
}; | ||
this.isAuthorised = function() { | ||
return isAuthorised(); | ||
} | ||
if (options.authorised) { | ||
this.on("authorised", options.authorised); | ||
function authorise(token, options) { | ||
options = options || { }; | ||
registerEventHandlers(options); | ||
validateToken(token); | ||
} | ||
utils.registerHandlers(this, options.handlers); | ||
function registerEventHandlers(options) { | ||
if (options.error) { | ||
that.on("error", options.error); | ||
} | ||
if (options.authorised) { | ||
that.on("authorised", options.authorised); | ||
} | ||
if (!token) { | ||
this.emit("error", new Error("No token supplied")); | ||
return; | ||
that.registerHandlers(options.handlers); | ||
} | ||
var that = this; | ||
var request = this.lastfm.request("auth.getsession", { token: token }); | ||
request.on("success", function(data) { | ||
var result = JSON.parse(data); | ||
if (result.error) { | ||
that.emit("error", new Error(result.message)); | ||
function validateToken(token) { | ||
if (!token) { | ||
that.emit("error", new Error("No token supplied")); | ||
return; | ||
} | ||
if (result.session) { | ||
that.user = result.session.name; | ||
that.key = result.session.key; | ||
that.emit("authorised", that); | ||
var params = { token: token }, | ||
request = lastfm.request("auth.getsession", params); | ||
request.on("success", authoriseSession); | ||
request.on("error", bubbleError); | ||
} | ||
function isAuthorised() { | ||
return that.key && that.key !== ''; | ||
} | ||
function authoriseSession(result) { | ||
if (!result.session) { | ||
that.emit("error", new Error("Unexpected error")); | ||
return; | ||
} | ||
} | ||
setSessionDetails(result.session); | ||
that.emit("authorised", that); | ||
} | ||
that.emit("error", new Error("Unexpected error")); | ||
}); | ||
function setSessionDetails(session) { | ||
that.user = session.name; | ||
that.key = session.key; | ||
} | ||
request.on("error", function(error) { | ||
function bubbleError(error) { | ||
that.emit("error", error); | ||
}); | ||
} | ||
}; | ||
LastFmSession.prototype.isAuthorised = function() { | ||
return this.key && this.key != ''; | ||
}; | ||
LastFmSession.prototype = Object.create(LastFmBase.prototype); | ||
module.exports = LastFmSession; |
@@ -1,17 +0,10 @@ | ||
var EventEmitter = require("events").EventEmitter; | ||
var utils = require("./utils"); | ||
var _ = require("underscore"); | ||
var _ = require("underscore") | ||
, LastFmBase = require("./lastfm-base"); | ||
var LastFmUpdate = function(lastfm, method, session, options) { | ||
EventEmitter.call(this); | ||
var that = this; | ||
options = options || {}; | ||
LastFmBase.call(this); | ||
if (options.error) { | ||
this.on("error", options.error); | ||
} | ||
if (options.success) { | ||
this.on("success", options.success); | ||
} | ||
utils.registerHandlers(this, options.handlers); | ||
registerEventHandlers(options); | ||
@@ -22,26 +15,27 @@ if (!session.isAuthorised()) { | ||
} | ||
if (method !== "scrobble" && method !== "nowplaying") { | ||
return; | ||
} | ||
if (!options) options = {}; | ||
update(method, options); | ||
if (method == "nowplaying") { | ||
nowPlaying(options); | ||
function registerEventHandlers(options) { | ||
if (options.error) { | ||
that.on("error", options.error); | ||
} | ||
if (options.success) { | ||
that.on("success", options.success); | ||
} | ||
that.registerHandlers(options.handlers); | ||
} | ||
if (method == "scrobble") { | ||
scrobble(options); | ||
} | ||
function nowPlaying(options) { | ||
var params = filterOptions(options); | ||
var request = lastfm.request("track.updateNowPlaying", params); | ||
request.on("success", handleResponse); | ||
request.on("error", bubbleError); | ||
} | ||
function scrobble(options) { | ||
if (!options.timestamp) { | ||
function update(method, options) { | ||
if (method == "scrobble" && !options.timestamp) { | ||
that.emit("error", new Error("Timestamp is required for scrobbling")); | ||
return; | ||
} | ||
var params = filterOptions(options); | ||
var request = lastfm.request("track.scrobble", params); | ||
var params = buildRequestParams(options), | ||
requestMethod = method == "scrobble" ? "track.scrobble" : "track.updateNowPlaying", | ||
request = lastfm.request(requestMethod, params); | ||
request.on("success", handleResponse); | ||
@@ -51,9 +45,4 @@ request.on("error", bubbleError); | ||
function handleResponse(data) { | ||
var response = JSON.parse(data); | ||
function handleResponse(response) { | ||
if (!response) return; | ||
if (response.error) { | ||
that.emit("error", new Error(response.message)); | ||
return; | ||
} | ||
that.emit("success", options.track); | ||
@@ -66,23 +55,12 @@ } | ||
function filterOptions(options) { | ||
var params = { | ||
sk: session.key | ||
}; | ||
_(Object.keys(options)).each(function(key) { | ||
if (key == "track" && typeof(options.track) == "object") { | ||
params.artist = options.track.artist["#text"]; | ||
params.track = options.track.name; | ||
return; | ||
} | ||
if (key != "handlers" && key != "success" && key != "error" && options[key]) { | ||
params[key] = options[key]; | ||
} | ||
}); | ||
return params; | ||
function buildRequestParams(params) { | ||
var requestParams = that.filterParameters(params, ["error", "success", "handlers"]); | ||
requestParams.sk = session.key; | ||
return requestParams; | ||
} | ||
} | ||
LastFmUpdate.prototype = Object.create(EventEmitter.prototype); | ||
LastFmUpdate.prototype = Object.create(LastFmBase.prototype); | ||
module.exports = LastFmUpdate; | ||
@@ -1,29 +0,35 @@ | ||
var EventEmitter = require("events").EventEmitter; | ||
var RecentTracksParser = require("./recenttracks-parser"); | ||
var utils = require("./utils"); | ||
var LastFmBase = require("./lastfm-base"); | ||
var RecentTracksStream = module.exports = function(lastfm, user, options) { | ||
if (!options) options = {}; | ||
var that = this; | ||
LastFmBase.call(this); | ||
options = options || {}; | ||
this.lastfm = lastfm; | ||
this.lastPlay = null; | ||
this.nowPlaying = null; | ||
this.rate = 10; | ||
this.parser = options.parser || new RecentTracksParser(); | ||
this.user = user; | ||
var rate = 10 | ||
, isStreaming = false | ||
, timeout | ||
, lastPlay = null | ||
, nowPlaying = null; | ||
EventEmitter.call(this); | ||
registerEventHandlers(options); | ||
utils.registerHandlers(this, options.handlers); | ||
if (options.autostart) { | ||
start(); | ||
} | ||
registerListeners(); | ||
this.start = function() { | ||
start(); | ||
} | ||
initParser(); | ||
this.stop = function() { | ||
stop(); | ||
} | ||
if (options.autostart) { | ||
this.start(); | ||
this.isStreaming = function() { | ||
return isStreaming; | ||
} | ||
function registerListeners() { | ||
function registerEventHandlers(options) { | ||
that.registerHandlers(options.handlers); | ||
var events = ["error", "lastPlayed", "nowPlaying", "stoppedPlaying", "scrobbled"]; | ||
@@ -33,9 +39,28 @@ events.forEach(function (event) { | ||
}); | ||
}; | ||
} | ||
function initParser() { | ||
that.parser.on("track", function(tracks) { | ||
function start() { | ||
isStreaming = true; | ||
check(); | ||
function check() { | ||
var request = lastfm.request("user.getrecenttracks", { | ||
user: user, | ||
limit: 1 | ||
}); | ||
request.on("success", handleSuccess); | ||
request.on("error", bubbleError); | ||
if (isStreaming) timeout = setTimeout(check, rate * 1000); | ||
} | ||
function handleSuccess(data) { | ||
if (!data || !data.recenttracks || !data.recenttracks.track) { | ||
that.emit("error", new Error("Unexpected response")); | ||
return; | ||
} | ||
var tracks = data.recenttracks.track; | ||
if (tracks instanceof Array) { | ||
that.processNowPlaying(tracks[0]); | ||
that.processLastPlay(tracks[1]); | ||
processNowPlaying(tracks[0]); | ||
processLastPlay(tracks[1]); | ||
return; | ||
@@ -46,67 +71,46 @@ } | ||
if (track["@attr"] && track["@attr"]["nowplaying"]) { | ||
that.processNowPlaying(track); | ||
processNowPlaying(track); | ||
return; | ||
} | ||
that.processLastPlay(track); | ||
if (that.nowPlaying) { | ||
that.emit("stoppedPlaying", that.nowPlaying); | ||
that.nowPlaying = null; | ||
processLastPlay(track); | ||
if (nowPlaying) { | ||
that.emit("stoppedPlaying", nowPlaying); | ||
nowPlaying = null; | ||
} | ||
}); | ||
} | ||
that.parser.on("error", function(error) { | ||
function bubbleError(error) { | ||
that.emit("error", error); | ||
}); | ||
} | ||
} | ||
}; | ||
RecentTracksStream.prototype = Object.create(EventEmitter.prototype); | ||
RecentTracksStream.prototype.processNowPlaying = function(track) { | ||
var sameTrack = (this.nowPlaying && this.nowPlaying.name == track.name); | ||
if (!sameTrack) { | ||
this.nowPlaying = track; | ||
this.emit("nowPlaying", track); | ||
function processNowPlaying(track) { | ||
var sameTrack = (nowPlaying && nowPlaying.name == track.name); | ||
if (!sameTrack) { | ||
nowPlaying = track; | ||
that.emit("nowPlaying", track); | ||
} | ||
} | ||
}; | ||
RecentTracksStream.prototype.processLastPlay = function(track) { | ||
if (!this.lastPlay) { | ||
this.lastPlay = track; | ||
this.emit("lastPlayed", track); | ||
return; | ||
} | ||
function processLastPlay(track) { | ||
if (!lastPlay) { | ||
lastPlay = track; | ||
that.emit("lastPlayed", track); | ||
return; | ||
} | ||
var sameTrack = (this.lastPlay.name == track.name); | ||
if (!sameTrack) { | ||
this.lastPlay = track; | ||
this.emit("scrobbled", track); | ||
var sameTrack = (lastPlay.name == track.name); | ||
if (!sameTrack) { | ||
lastPlay = track; | ||
that.emit("scrobbled", track); | ||
} | ||
} | ||
}; | ||
RecentTracksStream.prototype.start = function() { | ||
var that = this; | ||
this.isStreaming = true; | ||
var check = function() { | ||
var request = that.lastfm.request("user.getrecenttracks", { | ||
user: that.user, | ||
limit: 1 | ||
}); | ||
request.on("success", function(data) { | ||
that.parser.parse(data); | ||
}); | ||
request.on("error", function(error) { | ||
that.emit("error", error); | ||
}); | ||
if (that.isStreaming) that.timeout = setTimeout(check, that.rate * 1000); | ||
function stop() { | ||
clearTimeout(timeout); | ||
isStreaming = false; | ||
} | ||
check(); | ||
}; | ||
RecentTracksStream.prototype.stop = function() { | ||
clearTimeout(this.timeout); | ||
this.isStreaming = false; | ||
}; | ||
RecentTracksStream.prototype = Object.create(LastFmBase.prototype); |
{ | ||
"name": "lastfm", | ||
"description": "Read and write to Last.fm", | ||
"version": "0.6.3", | ||
"version": "0.7.0", | ||
"author": "James Scott <jammus@gmail.com>", | ||
"contributors": [ | ||
"Garrett Wilkin <garrett.wilkin@gmail.com> (http://geethink.com)" | ||
], | ||
"repository": { | ||
@@ -7,0 +10,0 @@ "type": "git", |
@@ -51,5 +51,5 @@ # lastfm-node | ||
- *success(data)* | ||
- *success(json)* | ||
Raw data returned by Last.fm. | ||
JSON response from Last.fm | ||
@@ -76,2 +76,6 @@ - *error(error)* | ||
- *isStreaming()* | ||
Boolean. True is nowplaying/recent track data is being actively fetched. | ||
- *on(event, listener)* | ||
@@ -143,6 +147,3 @@ | ||
Authorises user with Last.fm api. See last.fm documentation. | ||
Options: | ||
- *handlers* | ||
Default event handlers to attach to the authorise call. | ||
Authorises user with Last.fm api. See last.fm documentation. Options argument has handlers property that has default event handlers to attach to the LastFmSession instance. | ||
@@ -288,5 +289,7 @@ - *on(event, handler)* | ||
session.authorise(token, { | ||
authorised: function(session) { | ||
lastfm.update('nowplaying', session, { track: track } ); | ||
lastfm.update('scrobble', session, { track: track, timestamp: 12345678 }); | ||
handlers: { | ||
authorised: function(session) { | ||
lastfm.update('nowplaying', session, { track: track } ); | ||
lastfm.update('scrobble', session, { track: track, timestamp: 12345678 }); | ||
} | ||
} | ||
@@ -293,0 +296,0 @@ }); |
require("./lastfm-node-test.js"); | ||
require("./lastfm-recenttracks-parser-test.js"); | ||
require("./lastfm-recenttracks-stream-test.js"); | ||
@@ -10,1 +9,2 @@ require("./lastfm-session-test.js"); | ||
require("./lastfm-request-test.js"); | ||
require("./lastfm-base-test.js"); |
@@ -90,14 +90,2 @@ require("./common.js"); | ||
it("emits error if response contains error", function() { | ||
gently.expect(lastfm, "request", function() { | ||
return request; | ||
}); | ||
new LastFmInfo(lastfm, "track", { handlers: { | ||
error: gently.expect(function errorHandler(error) { | ||
assert.equal("You must supply either a track & artist name or a track mbid.", error.message); | ||
}) | ||
}}); | ||
request.emit("success", FakeData.NotEnoughTrackInfo); | ||
}); | ||
it("emits error when receiving unexpected data", function() { | ||
@@ -112,18 +100,5 @@ gently.expect(lastfm, "request", function() { | ||
}}); | ||
request.emit("success", FakeData.SuccessfulAuthorisation); | ||
request.emit("success", JSON.parse(FakeData.SuccessfulAuthorisation)); | ||
}); | ||
it("emits error if receiving junk", function() { | ||
gently.expect(lastfm, "request", function() { | ||
return request; | ||
}); | ||
new LastFmInfo(lastfm, "track", { handlers: { | ||
error: gently.expect(function errorHandler(error) { | ||
assert.ok(error.message.indexOf(FakeData.Garbage) > -1); | ||
assert.ok("Syntax error"); | ||
}) | ||
}}); | ||
request.emit("success", FakeData.Garbage); | ||
}); | ||
it("emits success with received data when matches expected type", function() { | ||
@@ -139,3 +114,3 @@ gently.expect(lastfm, "request", function() { | ||
}}); | ||
request.emit("success", FakeData.RunToYourGraveTrackInfo); | ||
request.emit("success", JSON.parse(FakeData.RunToYourGraveTrackInfo)); | ||
}); | ||
@@ -142,0 +117,0 @@ |
require("./common.js"); | ||
var LastFmInfo = require("lastfm/lastfm-info"); | ||
var fakes = require("./fakes"); | ||
describe("a track info request") | ||
var LastFmInfo = require("lastfm/lastfm-info") | ||
, fakes = require("./fakes"); | ||
(function() { | ||
describe("a track info request"); | ||
before(function() { | ||
@@ -32,11 +35,2 @@ this.gently = new Gently(); | ||
}); | ||
it("can accept basic track object", function() { | ||
this.gently.expect(this.lastfm, "request", function(method, params) { | ||
assert.equal("The Mae Shi", params.artist); | ||
assert.equal("Run To Your Grave", params.track); | ||
assert.equal("fakembid", params.mbid); | ||
return new fakes.LastFmRequest(); | ||
}); | ||
new LastFmInfo(this.lastfm, "track", { track: FakeTracks.RunToYourGrave }); | ||
}); | ||
})(); |
@@ -190,6 +190,35 @@ require('./common'); | ||
it("converts track object to separate parameters", function() { | ||
whenMethodIs("any.method"); | ||
andParamsAre({ | ||
track: { | ||
artist: { "#text": "The Mae Shi" }, | ||
name: "Run To Your Grave", | ||
mbid: "1234567890" | ||
} | ||
}); | ||
expectDataPair("artist", "The Mae Shi"); | ||
expectDataPair("track", "Run To Your Grave"); | ||
expectDataPair("mbid", "1234567890"); | ||
}); | ||
it("doesn't include mbid if one isn't supplied", function() { | ||
whenMethodIs("any.method"); | ||
andParamsAre({ | ||
track: { | ||
artist: { "#text": "The Mae Shi" }, | ||
name: "Run To Your Grave" | ||
} | ||
}); | ||
expectDataPair("artist", "The Mae Shi"); | ||
expectDataPair("track", "Run To Your Grave"); | ||
doNotExpectDataKey("mbid"); | ||
}); | ||
it("does not pass through event handler parameters", function() { | ||
whenMethodIs("any.method"); | ||
andParamsAre({ handlers: "handlers"}); | ||
andParamsAre({ handlers: "handlers", error: "error", success: "success" }); | ||
doNotExpectDataKey("handlers"); | ||
doNotExpectDataKey("error"); | ||
doNotExpectDataKey("success"); | ||
}); | ||
@@ -196,0 +225,0 @@ |
require("./common.js"); | ||
var RecentTracksParser = require("lastfm/recenttracks-parser"); | ||
var RecentTracksStream = require("lastfm/recenttracks-stream"); | ||
var fakes = require("./fakes"); | ||
var _ = require("underscore") | ||
, RecentTracksStream = require("lastfm/recenttracks-stream") | ||
, LastFmRequest = require("lastfm/lastfm-request") | ||
, fakes = require("./fakes"); | ||
@@ -18,10 +19,2 @@ (function() { | ||
it("configures user", function() { | ||
assert.equal("username", trackStream.user); | ||
}); | ||
it("checks every ten seconds", function() { | ||
assert.equal(10, trackStream.rate); | ||
}); | ||
it("accepts listeners", function() { | ||
@@ -32,4 +25,3 @@ trackStream.addListener("event", function() {}); | ||
it("is not streaming", function() { | ||
var isStreaming = trackStream.isStreaming; | ||
assert.ok(!trackStream.isStreaming); | ||
assert.ok(!trackStream.isStreaming()); | ||
}); | ||
@@ -89,34 +81,81 @@ | ||
(function() { | ||
var parser, lastfm, trackStream, gently; | ||
var requestEmits = [], | ||
previousEmits = []; | ||
function ifRequestHasPreviouslyEmit(emits) { | ||
previousEmits = emits; | ||
} | ||
function whenRequestEmits(count, event, object) { | ||
if (typeof count !== "number") { | ||
object = event; | ||
event = count; | ||
count = 1; | ||
} | ||
if (typeof event !== "string") { | ||
object = event; | ||
event = "success"; | ||
} | ||
requestEmits = [event, object, count]; | ||
} | ||
function expectStreamToEmit(count, expectation) { | ||
if (typeof count === "function") { | ||
expectation = count; | ||
count = 1; | ||
} | ||
var lastfm = new LastFmNode(), | ||
connection = new fakes.Client(80, lastfm.host), | ||
request = new fakes.LastFmRequest(), | ||
gently = new Gently(); | ||
gently.expect(lastfm, "request", function() { | ||
return request; | ||
}); | ||
var trackStream = new RecentTracksStream(lastfm, "username"); | ||
trackStream.start(); | ||
trackStream.stop(); | ||
for(var index = 0; index < previousEmits.length; index++) { | ||
request.emit("success", previousEmits[index]); | ||
} | ||
gently.expect(trackStream, "emit", count, expectation); | ||
for(var times = 0; times < requestEmits[2]; times++) { | ||
request.emit(requestEmits[0], requestEmits[1]); | ||
} | ||
} | ||
describe("An active stream"); | ||
before(function() { | ||
parser = new RecentTracksParser(); | ||
lastfm = new LastFmNode(); | ||
trackStream = new RecentTracksStream(lastfm, "username", { parser: parser }); | ||
gently = new Gently(); | ||
before(function() { | ||
previousEmits = []; | ||
requestEmits = []; | ||
}); | ||
it("bubbles errors", function() { | ||
gently.expect(trackStream, "emit", function(event) { | ||
whenRequestEmits("error", { error: 1, message: "An error" }); | ||
expectStreamToEmit(function(event, error) { | ||
assert.equal("error", event); | ||
assert.equal("An error", error.message); | ||
}); | ||
parser.emit("error", new Error()); | ||
}); | ||
it("emits last played when track received", function() { | ||
gently.expect(trackStream, "emit", function(event, track) { | ||
whenRequestEmits({ recenttracks: { track: | ||
FakeTracks.LambAndTheLion | ||
} }); | ||
expectStreamToEmit(function(event, track) { | ||
assert.equal("lastPlayed", event); | ||
assert.equal("Lamb and the Lion", track.name); | ||
}); | ||
parser.emit("track", FakeTracks.LambAndTheLion); | ||
}); | ||
it("emits now playing if track flagged now playing", function() { | ||
gently.expect(trackStream, "emit", function(event, track) { | ||
whenRequestEmits({ | ||
recenttracks: { track: FakeTracks.RunToYourGrave_NP } | ||
}); | ||
expectStreamToEmit(function(event, track) { | ||
assert.equal("nowPlaying", event); | ||
assert.equal("Run To Your Grave", track.name); | ||
}); | ||
parser.emit("track", FakeTracks.RunToYourGrave_NP); | ||
}); | ||
@@ -126,3 +165,6 @@ | ||
var count = 0; | ||
gently.expect(trackStream, "emit", 2, function(event, track) { | ||
whenRequestEmits({ | ||
recenttracks: { track: FakeTracks.NowPlayingAndScrobbled } | ||
}); | ||
expectStreamToEmit(2, function(event, track) { | ||
if (count == 0) { | ||
@@ -138,51 +180,74 @@ assert.equal("nowPlaying", event); | ||
}); | ||
parser.emit("track", FakeTracks.NowPlayingAndScrobbled); | ||
}); | ||
it("does not re-emit lastPlayed on receipt of same track", function() { | ||
gently.expect(trackStream, "emit", 1, function(event, track) { | ||
whenRequestEmits(2, { | ||
recenttracks: { track: FakeTracks.LambAndTheLion } | ||
}); | ||
expectStreamToEmit(1, function(event, track) { | ||
assert.equal("lastPlayed", event); | ||
assert.equal("Lamb and the Lion", track.name); | ||
}); | ||
parser.emit("track", FakeTracks.LambAndTheLion); | ||
parser.emit("track", FakeTracks.LambAndTheLion); | ||
}); | ||
it("does not re-emit nowPlaying on receipt of same track", function() { | ||
gently.expect(trackStream, "emit", 1, function(event, track) { | ||
whenRequestEmits(2, { | ||
recenttracks: { track: FakeTracks.RunToYourGrave_NP } | ||
}); | ||
expectStreamToEmit(1, function(event, track) { | ||
assert.equal("nowPlaying", event); | ||
assert.equal("Run To Your Grave", track.name); | ||
}); | ||
parser.emit("track", FakeTracks.RunToYourGrave_NP); | ||
parser.emit("track", FakeTracks.RunToYourGrave_NP); | ||
}); | ||
it("emits stoppedPlaying track when now playing stops", function() { | ||
parser.emit("track", FakeTracks.RunToYourGrave); | ||
parser.emit("track", FakeTracks.RunToYourGrave_NP); | ||
gently.expect(trackStream, "emit", 1, function(event, track) { | ||
ifRequestHasPreviouslyEmit([ | ||
{ recenttracks: { track: FakeTracks.RunToYourGrave } }, | ||
{ recenttracks: { track: FakeTracks.RunToYourGrave_NP } } | ||
]); | ||
whenRequestEmits({ | ||
recenttracks: { track: FakeTracks.RunToYourGrave } | ||
}); | ||
expectStreamToEmit(function(event, track) { | ||
assert.equal("stoppedPlaying", event); | ||
assert.equal("Run To Your Grave", track.name); | ||
}); | ||
parser.emit("track", FakeTracks.RunToYourGrave); | ||
}); | ||
it("emits scrobbled when last play changes", function() { | ||
parser.emit("track", FakeTracks.LambAndTheLion); | ||
parser.emit("track", FakeTracks.RunToYourGrave_NP); | ||
gently.expect(trackStream, "emit", 1, function(event, track) { | ||
ifRequestHasPreviouslyEmit([ | ||
{ recenttracks: { track: FakeTracks.LambAndTheLion } }, | ||
{ recenttracks: { track: FakeTracks.RunToYourGrave_NP } } | ||
]); | ||
whenRequestEmits({ | ||
recenttracks: { track: FakeTracks.RunToYourGrave } | ||
}); | ||
expectStreamToEmit(function(event, track) { | ||
assert.equal("scrobbled", event); | ||
assert.equal("Run To Your Grave", track.name); | ||
}); | ||
parser.emit("track", FakeTracks.RunToYourGrave); | ||
}); | ||
it("emits nowPlaying when track same as lastPlayed", function() { | ||
parser.emit("track", FakeTracks.RunToYourGrave); | ||
gently.expect(trackStream, "emit", function(event, track) { | ||
ifRequestHasPreviouslyEmit([ | ||
{ recenttracks: { track: FakeTracks.RunToYourGrave } } | ||
]); | ||
whenRequestEmits({ | ||
recenttracks: { track: FakeTracks.RunToYourGrave_NP } | ||
}); | ||
expectStreamToEmit(function(event, track) { | ||
assert.equal("nowPlaying", event); | ||
assert.equal("Run To Your Grave", track.name); | ||
}); | ||
parser.emit("track", FakeTracks.RunToYourGrave_NP); | ||
}); | ||
it("emits error when unexpected item is received", function() { | ||
whenRequestEmits({ | ||
something: "we've never seen before" | ||
}); | ||
expectStreamToEmit(function(event, error) { | ||
assert.equal("error", event); | ||
assert.equal("Unexpected response", error.message); | ||
}); | ||
}); | ||
})(); | ||
@@ -208,3 +273,3 @@ | ||
trackStream.stop(); | ||
assert.ok(!trackStream.isStreaming); | ||
assert.ok(!trackStream.isStreaming()); | ||
}); | ||
@@ -217,3 +282,3 @@ | ||
var trackStream = new RecentTracksStream(lastfm, "username", { autostart: true} ); | ||
assert.ok(trackStream.isStreaming); | ||
assert.ok(trackStream.isStreaming()); | ||
trackStream.stop(); | ||
@@ -220,0 +285,0 @@ }); |
require("./common"); | ||
var LastFmRequest = require("lastfm/lastfm-request"); | ||
var fakes = require("./fakes"); | ||
var _ = require("underscore"), | ||
LastFmRequest = require("lastfm/lastfm-request"), | ||
fakes = require("./fakes"); | ||
@@ -16,3 +17,3 @@ (function() { | ||
gently.expect(GENTLY_HIJACK.hijacked.http, "createClient", function() { | ||
return connection; | ||
return connection; | ||
}); | ||
@@ -38,33 +39,2 @@ }); | ||
it("emits data received when response is complete", function() { | ||
var chunkOne = "test"; | ||
var chunkTwo = "data"; | ||
gently.expect(connection, "request", function() { | ||
return request; | ||
}); | ||
var lastfmRequest = new LastFmRequest(lastfm); | ||
gently.expect(lastfmRequest, "emit", function(event, data) { | ||
assert.equal("success", event); | ||
assert.equal(chunkOne + chunkTwo, data); | ||
}); | ||
var response = new fakes.ClientResponse(); | ||
request.emit("response", response); | ||
response.emit("data", chunkOne); | ||
response.emit("data", chunkTwo); | ||
response.emit("end"); | ||
}); | ||
it("bubbles up connection errors", function() { | ||
var message = "Bubbled error"; | ||
gently.expect(connection, "request", function() { | ||
return request; | ||
}); | ||
var lastfmRequest = new LastFmRequest(lastfm); | ||
gently.expect(lastfmRequest, "emit", function(event, error) { | ||
assert.equal("error", event); | ||
assert.equal(message, error.message); | ||
}); | ||
connection.emit("error", new Error(message)); | ||
}); | ||
it("defaults user agent to lastfm-node", function() { | ||
@@ -87,2 +57,15 @@ gently.expect(connection, "request", function(method, url, options) { | ||
}); | ||
it("bubbles up connection errors", function() { | ||
var message = "Bubbled error"; | ||
gently.expect(connection, "request", function() { | ||
return request; | ||
}); | ||
var lastfmRequest = new LastFmRequest(lastfm); | ||
gently.expect(lastfmRequest, "emit", function(event, error) { | ||
assert.equal("error", event); | ||
assert.equal(message, error.message); | ||
}); | ||
connection.emit("error", new Error(message)); | ||
}); | ||
})(); | ||
@@ -138,1 +121,79 @@ | ||
})(); | ||
(function() { | ||
var lastfm, connection, url, gently, request, receivedData; | ||
describe("A Lastfm request which returns data") | ||
before(function() { | ||
lastfm = new LastFmNode(); | ||
connection = new fakes.Client(80, lastfm.host); | ||
request = new fakes.ClientRequest(); | ||
gently = new Gently(); | ||
gently.expect(GENTLY_HIJACK.hijacked.http, "createClient", function() { | ||
return connection; | ||
}); | ||
}); | ||
it("emits data as json", function() { | ||
whenReceiving("{\"testdata\":\"received\"}"); | ||
expectRequestToEmit(function(event, data) { | ||
assert.equal("success", event); | ||
assert.equal("received", data.testdata); | ||
}); | ||
}); | ||
it("emits error if received data cannot be parsed to json", function() { | ||
whenReceiving("{\"testdata\""); | ||
expectRequestToEmit(function(event, error) { | ||
assert.equal("error", event); | ||
assert.ok(error); | ||
}); | ||
}); | ||
it("emits error if json response contains a lastfm error", function() { | ||
whenReceiving("{\"error\": 2, \"message\": \"service does not exist\"}"); | ||
expectRequestToEmit(function(event, error) { | ||
assert.equal("error", event); | ||
assert.equal("service does not exist", error.message); | ||
}); | ||
}); | ||
it("accepts data in chunks", function() { | ||
whenReceiving(["{\"testda", "ta\":\"recei", "ved\"}"]); | ||
expectRequestToEmit(function(event, data) { | ||
assert.equal("success", event); | ||
assert.equal("received", data.testdata); | ||
}); | ||
}); | ||
it("does not covert to json if requested is different format", function() { | ||
var xml = "<somexml />"; | ||
lastfm.format = "xml"; | ||
whenReceiving(xml); | ||
expectRequestToEmit(function(event, data) { | ||
assert.equal(xml, data); | ||
}); | ||
}); | ||
function whenReceiving(data) { | ||
if (!data instanceof Array) { | ||
data = [data]; | ||
} | ||
receivedData = data; | ||
} | ||
function expectRequestToEmit(expectation) { | ||
gently.expect(connection, "request", function() { | ||
return request; | ||
}); | ||
var lastfmRequest = new LastFmRequest(lastfm); | ||
gently.expect(lastfmRequest, "emit", expectation); | ||
var response = new fakes.ClientResponse(); | ||
request.emit("response", response); | ||
_(receivedData).each(function(data) { | ||
response.emit("data", data); | ||
}); | ||
response.emit("end"); | ||
} | ||
})(); |
@@ -77,3 +77,3 @@ require('./common.js'); | ||
function whenReadRequestReturns(data) { | ||
returndata = data; | ||
returndata = JSON.parse(data); | ||
gently.expect(lastfm, "request", function() { | ||
@@ -129,8 +129,2 @@ return request; | ||
it("emits error when authorisation not successful", function() { | ||
whenReadRequestReturns(FakeData.AuthorisationError); | ||
andTokenIs("token"); | ||
expectError("Signature is invalid"); | ||
}); | ||
it("emits error when receiving unexpected return data", function() { | ||
@@ -137,0 +131,0 @@ whenReadRequestReturns(FakeData.SingleRecentTrack); |
@@ -47,3 +47,3 @@ require('./common.js'); | ||
function whenWriteRequestReturns(data) { | ||
returndata = data; | ||
returndata = JSON.parse(data); | ||
gently.expect(lastfm, "request", function(method, params) { | ||
@@ -110,12 +110,2 @@ return request; | ||
it("emits error when problem updating", function() { | ||
whenWriteRequestReturns(FakeData.UpdateError); | ||
andMethodIs("nowplaying"); | ||
andSessionIs(authorisedSession); | ||
andOptionsAre({ | ||
track: FakeTracks.RunToYourGrave | ||
}); | ||
expectError("Invalid method signature supplied"); | ||
}); | ||
describe("nowPlaying updates") | ||
@@ -138,4 +128,3 @@ before(function() { | ||
gently.expect(lastfm, "request", function(method, params) { | ||
assert.equal("The Mae Shi", params.artist); | ||
assert.equal("Run To Your Grave", params.track); | ||
assert.equal(FakeTracks.RunToYourGrave, params.track); | ||
assert.equal("key", params.sk); | ||
@@ -226,4 +215,3 @@ return request; | ||
gently.expect(lastfm, "request", function(method, params) { | ||
assert.equal("The Mae Shi", params.artist); | ||
assert.equal("Run To Your Grave", params.track); | ||
assert.equal(FakeTracks.RunToYourGrave, params.track); | ||
assert.equal("key", params.sk); | ||
@@ -230,0 +218,0 @@ assert.equal(12345678, params.timestamp); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
80560
28
1950
310