diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b705b2a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.10" +notifications: + irc: "irc.esper.net#spongy" \ No newline at end of file diff --git a/modules/cache.js b/modules/cache.js index 0f6f1ca..4bcb415 100644 --- a/modules/cache.js +++ b/modules/cache.js @@ -5,14 +5,14 @@ var exp = {}; // sets the timestamp for +uuid+ to now exp.update_timestamp = function(uuid) { - console.log("cache: updating timestamp for " + uuid); + console.log(uuid + " cache: updating timestamp"); var time = new Date().getTime(); redis.hmset(uuid, "t", time); }; // create the key +uuid+, store +hash+ and time exp.save_hash = function(uuid, hash) { - console.log("cache: saving hash for " + uuid); + console.log(uuid + " cache: saving hash"); var time = new Date().getTime(); redis.hmset(uuid, "h", hash, "t", time); }; diff --git a/modules/helpers.js b/modules/helpers.js index 16b0ea3..6c3ef21 100644 --- a/modules/helpers.js +++ b/modules/helpers.js @@ -20,17 +20,17 @@ function store_images(uuid, details, callback) { } else { var skinurl = skin_url(profile); if (skinurl) { - console.log(skinurl); + console.log(uuid + " " + skinurl); // set file paths var hash = get_hash(skinurl); if (details && details.h == hash) { // hash hasn't changed - console.log("hash has not changed"); + console.log(uuid + " hash has not changed"); cache.update_timestamp(uuid); callback(null, hash); } else { // hash has changed - console.log("new hash: " + hash); + console.log(uuid + "new hash: " + hash); var facepath = config.faces_dir + hash + ".png"; var helmpath = config.helms_dir + hash + ".png"; // download skin, extract face/helm @@ -81,15 +81,15 @@ function get_image_hash(uuid, callback) { } else { if (details && details.t + config.local_cache_time >= new Date().getTime()) { // uuid known + recently updated - console.log("uuid known & recently updated"); + console.log(uuid + " uuid known & recently updated"); callback(null, 1, details.h); } else { - console.log("uuid not known or too old"); + console.log(uuid + " uuid not known or too old"); store_images(uuid, details, function(err, hash) { if (err) { callback(err, -1, details && details.h); } else { - console.log("hash: " + hash); + console.log(uuid + " hash: " + hash); callback(null, (hash ? 2 : 3), hash); } }); diff --git a/modules/networking.js b/modules/networking.js index 9c90a35..79853cd 100644 --- a/modules/networking.js +++ b/modules/networking.js @@ -15,7 +15,7 @@ exp.get_profile = function(uuid, callback) { }, function (error, response, body) { if (!error && response.statusCode == 200) { // profile downloaded successfully - console.log("profile downloaded for " + uuid); + console.log(uuid + " profile downloaded"); callback(null, JSON.parse(body)); } else { if (error) { @@ -23,13 +23,13 @@ exp.get_profile = function(uuid, callback) { return; } else if (response.statusCode == 204 || response.statusCode == 404) { // we get 204 No Content when UUID doesn't exist (including 404 in case they change that) - console.log("uuid does not exist"); + console.log(uuid + " uuid does not exist"); } else if (response.statusCode == 429) { // Too Many Requests - console.warn("Too many requests for " + uuid); + console.warn(uuid + " Too many requests"); console.warn(body); } else { - console.error("Unknown error:"); + console.error(uuid + " Unknown error:"); console.error(response); console.error(body); } @@ -50,14 +50,14 @@ exp.skin_file = function(url, facename, helmname, callback) { }, function (error, response, body) { if (!error && response.statusCode == 200) { // skin downloaded successfully - console.log("skin downloaded."); + console.log(url + " skin downloaded"); skins.extract_face(body, facename, function(err) { if (err) { callback(err); } else { - console.log("face extracted."); + console.log(facename + " face extracted"); skins.extract_helm(facename, body, helmname, function(err) { - console.log("helm extracted."); + console.log(helmname + " helm extracted."); callback(err); }); } @@ -66,14 +66,14 @@ exp.skin_file = function(url, facename, helmname, callback) { if (error) { console.error("Error downloading '" + url + "': " + error); } else if (response.statusCode == 404) { - console.warn("Texture not found: " + url); + console.warn(url + " texture not found"); } else if (response.statusCode == 429) { // Too Many Requests // Never got this, seems like textures aren't limited - console.warn("Too many requests for " + url); + console.warn(url + " too many requests"); console.warn(body); } else { - console.error("Unknown error:"); + console.error(url + " unknown error:"); console.error(response); console.error(body); } diff --git a/package.json b/package.json index 4b37693..c0bfb12 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,26 @@ { "name": "crafatar", - "version": "0.0.0", + "version": "0.0.1", "private": true, + "author": "Jake0oo0", + "description": "A NodeJS application to server Minecraft avatars.", + "contributors": [{ + "name": "Jomo" + }], + "repository": { + "type": "git", + "url": "https://github.com/Jake0oo0/crafatar" + }, + "issues": { + "url": "https://github.com/Jake0oo0/crafatar/issues" + }, + "keywords": [ + "minecraft", + "avatar" + ], "scripts": { - "start": "node server.js" + "start": "node server.js", + "test": "node_modules/.bin/mocha -w" }, "dependencies": { "express": "~4.9.0", @@ -15,6 +32,7 @@ "jade": "~1.6.0", "lwip": "0.0.5", "request": "2.45.0", - "redis": " 0.12.1" + "redis": " 0.12.1", + "mocha": "2.0.1" } } \ No newline at end of file diff --git a/skins/faces/.gitkeep b/skins/faces/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/skins/helms/.gitkeep b/skins/helms/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..1a03d5b --- /dev/null +++ b/test/test.js @@ -0,0 +1,66 @@ +var assert = require('assert'); +var fs = require('fs') + +var networking = require('../modules/networking'); +var helpers = require('../modules/helpers'); +var config = require('../modules/config'); +var skins = require('../modules/skins'); + +var uuids = fs.readFileSync('test/uuids.txt').toString().split("\r\n"); +// Get a random UUID in order to prevent rate limiting +var uuid = uuids[Math.floor((Math.random() * 200) + 1)] + +// Only deletes files, doesn't delete directory. +var deleteFolderRecursive = function(path) { + if( fs.existsSync(path) ) { + fs.readdirSync(path).forEach(function(file,index){ + var curPath = path + "/" + file; + if(fs.lstatSync(curPath).isDirectory()) { + deleteFolderRecursive(curPath); + } else { + fs.unlinkSync(curPath); + } + }); + } +}; + +describe('Avatar Serving', function(){ + before(function() { + deleteFolderRecursive('skins/'); + }) + describe('UUID', function(){ + it("should be an invalid uuid", function(done){ + assert.equal(helpers.uuid_valid("invaliduuid"), false); + done(); + }); + it("should be a valid uuid", function(done){ + assert.equal(helpers.uuid_valid("0098cb60fa8e427cb299793cbd302c9a"), true); + done(); + }); + }); + describe('Avatar', function(){ + it("should be downloaded", function(done) { + helpers.get_avatar(uuid, false, 180, function(err, status, image) { + assert.equal(status, 2); + done(); + }); + }); + it("should be local", function(done) { + helpers.get_avatar(uuid, false, 180, function(err, status, image) { + assert.equal(status, 1); + done(); + }); + }); + }); + describe('Mojang Errors', function(){ + before(function() { + deleteFolderRecursive('skins/'); + }) + it("should be rate limited", function(done) { + helpers.get_avatar(uuid, false, 180, function(err, status, image) { + assert.equal(err, null); + done(); + }); + }); + }); +}); diff --git a/views/index.jade b/views/index.jade index 3732137..b49fd6d 100644 --- a/views/index.jade +++ b/views/index.jade @@ -48,7 +48,7 @@ block content img(src="/avatars/853c80ef3c3749fdaa49938b674adae6?size=64") .well.code <img src="#{domain}/avatars/853c80ef3c3749fdaa49938b674adae6?size=64"> p Get jeb_'s helmet avatar, 64 × 64 pixels - img(src="/avatars/853c80ef3c3749fdaa49938b674adae6?size=64&helm") + img(src="/avatars/853c80ef3c3749fdaa49938b674adae6?size=64&helm") .well.code <img src="#{domain}/avatars/853c80ef3c3749fdaa49938b674adae6?size=64&helm"> p Get jeb_'s avatar, 64 × 64 pixels, or fall back to steve if his avatar is not found img(src="/avatars/00000000000000000000000000000000?default=steve&size=64")