Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lastfm

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lastfm - npm Package Compare versions

Comparing version 0.6.3 to 0.7.0

lib/lastfm/lastfm-base.js

9

History.md
# 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

79

lib/lastfm/lastfm-info.js

@@ -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);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc