mirror of
https://github.com/azures04/crafatar.git
synced 2026-03-22 07:51:17 +01:00
Merge branch 'renders-new'
This commit is contained in:
commit
e8877c427a
51
lib/cache.js
51
lib/cache.js
@ -70,6 +70,15 @@ exp.info = function(callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// set model type to value of *slim*
|
||||||
|
exp.set_slim = function(rid, userId, slim, callback) {
|
||||||
|
logging.debug(rid, "setting slim for ", userId, "to " + slim);
|
||||||
|
// store userId in lower case if not null
|
||||||
|
userId = userId && userId.toLowerCase();
|
||||||
|
|
||||||
|
redis.hmset(userId, ["a", Number(slim)], callback);
|
||||||
|
};
|
||||||
|
|
||||||
// sets the timestamp for +userId+
|
// sets the timestamp for +userId+
|
||||||
// if +temp+ is true, the timestamp is set so that the record will be outdated after 60 seconds
|
// if +temp+ is true, the timestamp is set so that the record will be outdated after 60 seconds
|
||||||
// these 60 seconds match the duration of Mojang's rate limit ban
|
// these 60 seconds match the duration of Mojang's rate limit ban
|
||||||
@ -85,31 +94,34 @@ exp.update_timestamp = function(rid, userId, temp, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// create the key +userId+, store +skin_hash+, +cape_hash+ and time
|
// create the key +userId+, store +skin_hash+, +cape_hash+, +slim+ and current time
|
||||||
// if either +skin_hash+ or +cape_hash+ are undefined, they will not be stored
|
// if +skin_hash+ or +cape_hash+ are undefined, they aren't stored
|
||||||
// this feature can be used to write both cape and skin at separate times
|
// this is useful to store cape and skin at separate times, without overwriting the other
|
||||||
|
// +slim+ can be true (alex) or false (steve)
|
||||||
// +callback+ contans error
|
// +callback+ contans error
|
||||||
exp.save_hash = function(rid, userId, skin_hash, cape_hash, callback) {
|
exp.save_hash = function(rid, userId, skin_hash, cape_hash, slim, callback) {
|
||||||
logging.debug(rid, "caching skin:" + skin_hash + " cape:" + cape_hash);
|
logging.debug(rid, "caching skin:" + skin_hash + " cape:" + cape_hash + " slim:" + slim);
|
||||||
var time = Date.now();
|
// store shorter null value instead of "null" string
|
||||||
// store shorter null byte instead of "null"
|
|
||||||
skin_hash = skin_hash === null ? "" : skin_hash;
|
skin_hash = skin_hash === null ? "" : skin_hash;
|
||||||
cape_hash = cape_hash === null ? "" : cape_hash;
|
cape_hash = cape_hash === null ? "" : cape_hash;
|
||||||
// store userId in lower case if not null
|
// store userId in lower case if not null
|
||||||
userId = userId && userId.toLowerCase();
|
userId = userId && userId.toLowerCase();
|
||||||
if (skin_hash === undefined) {
|
|
||||||
redis.hmset(userId, "c", cape_hash, "t", time, function(err) {
|
var args = [];
|
||||||
callback(err);
|
if (cape_hash !== undefined) {
|
||||||
});
|
args.push("c", cape_hash);
|
||||||
} else if (cape_hash === undefined) {
|
|
||||||
redis.hmset(userId, "s", skin_hash, "t", time, function(err) {
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
redis.hmset(userId, "s", skin_hash, "c", cape_hash, "t", time, function(err) {
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
if (skin_hash !== undefined) {
|
||||||
|
args.push("s", skin_hash);
|
||||||
|
}
|
||||||
|
if (slim !== undefined) {
|
||||||
|
args.push("a", Number(!!slim));
|
||||||
|
}
|
||||||
|
args.push("t", Date.now());
|
||||||
|
|
||||||
|
redis.hmset(userId, args, function(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// removes the hash for +userId+ from the cache
|
// removes the hash for +userId+ from the cache
|
||||||
@ -131,6 +143,7 @@ exp.get_details = function(userId, callback) {
|
|||||||
details = {
|
details = {
|
||||||
skin: data.s === "" ? null : data.s,
|
skin: data.s === "" ? null : data.s,
|
||||||
cape: data.c === "" ? null : data.c,
|
cape: data.c === "" ? null : data.c,
|
||||||
|
slim: data.a === "1",
|
||||||
time: Number(data.t)
|
time: Number(data.t)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,14 +19,19 @@ function get_hash(url) {
|
|||||||
// gets the skin for +userId+ with +profile+
|
// gets the skin for +userId+ with +profile+
|
||||||
// uses +cache_details+ to determine if the skin needs to be downloaded or can be taken from cache
|
// uses +cache_details+ to determine if the skin needs to be downloaded or can be taken from cache
|
||||||
// face and face+helm images are extracted and stored to files
|
// face and face+helm images are extracted and stored to files
|
||||||
// callback: error, skin hash
|
// callback: error, skin hash, callback
|
||||||
function store_skin(rid, userId, profile, cache_details, callback) {
|
function store_skin(rid, userId, profile, cache_details, callback) {
|
||||||
networking.get_skin_url(rid, userId, profile, function(err, url) {
|
networking.get_skin_info(rid, userId, profile, function(err, url, slim) {
|
||||||
|
if (!err && userId.length > 16) {
|
||||||
|
// updating username with model info from uuid details
|
||||||
|
cache.set_slim(rid, profile.name, slim);
|
||||||
|
}
|
||||||
|
|
||||||
if (!err && url) {
|
if (!err && url) {
|
||||||
var skin_hash = get_hash(url);
|
var skin_hash = get_hash(url);
|
||||||
if (cache_details && cache_details.skin === skin_hash) {
|
if (cache_details && cache_details.skin === skin_hash) {
|
||||||
cache.update_timestamp(rid, userId, false, function(cache_err) {
|
cache.update_timestamp(rid, userId, false, function(cache_err) {
|
||||||
callback(cache_err, skin_hash);
|
callback(cache_err, skin_hash, slim);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
logging.debug(rid, "new skin hash:", skin_hash);
|
logging.debug(rid, "new skin hash:", skin_hash);
|
||||||
@ -36,25 +41,25 @@ function store_skin(rid, userId, profile, cache_details, callback) {
|
|||||||
fs.exists(facepath, function(exists) {
|
fs.exists(facepath, function(exists) {
|
||||||
if (exists) {
|
if (exists) {
|
||||||
logging.debug(rid, "skin already exists, not downloading");
|
logging.debug(rid, "skin already exists, not downloading");
|
||||||
callback(null, skin_hash);
|
callback(null, skin_hash, slim);
|
||||||
} else {
|
} else {
|
||||||
networking.get_from(rid, url, function(img, response, err1) {
|
networking.get_from(rid, url, function(img, response, err1) {
|
||||||
if (err1 || !img) {
|
if (err1 || !img) {
|
||||||
callback(err1, null);
|
callback(err1, null, slim);
|
||||||
} else {
|
} else {
|
||||||
skins.save_image(img, skinpath, function(skin_err, skin_img) {
|
skins.save_image(img, skinpath, function(skin_err, skin_img) {
|
||||||
if (skin_err) {
|
if (skin_err) {
|
||||||
callback(skin_err, null);
|
callback(skin_err, null, slim);
|
||||||
} else {
|
} else {
|
||||||
skins.extract_face(img, facepath, function(err2) {
|
skins.extract_face(img, facepath, function(err2) {
|
||||||
if (err2) {
|
if (err2) {
|
||||||
callback(err2, null);
|
callback(err2, null, slim);
|
||||||
} else {
|
} else {
|
||||||
logging.debug(rid, "face extracted");
|
logging.debug(rid, "face extracted");
|
||||||
skins.extract_helm(rid, facepath, img, helmpath, function(err3) {
|
skins.extract_helm(rid, facepath, img, helmpath, function(err3) {
|
||||||
logging.debug(rid, "helm extracted");
|
logging.debug(rid, "helm extracted");
|
||||||
logging.debug(rid, helmpath);
|
logging.debug(rid, helmpath);
|
||||||
callback(err3, skin_hash);
|
callback(err3, skin_hash, slim);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -128,7 +133,7 @@ function push_request(userId, type, fun) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calls back all queued requests that match userId and type
|
// calls back all queued requests that match userId and type
|
||||||
function resume(userId, type, err, hash) {
|
function resume(userId, type, err, hash, slim) {
|
||||||
var userId_safe = "!" + userId;
|
var userId_safe = "!" + userId;
|
||||||
var callbacks = requests[type][userId_safe];
|
var callbacks = requests[type][userId_safe];
|
||||||
if (callbacks) {
|
if (callbacks) {
|
||||||
@ -138,7 +143,7 @@ function resume(userId, type, err, hash) {
|
|||||||
|
|
||||||
for (var i = 0; i < callbacks.length; i++) {
|
for (var i = 0; i < callbacks.length; i++) {
|
||||||
// continue the request
|
// continue the request
|
||||||
callbacks[i](err, hash);
|
callbacks[i](err, hash, slim);
|
||||||
// remove from array
|
// remove from array
|
||||||
callbacks.splice(i, 1);
|
callbacks.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
@ -152,7 +157,7 @@ function resume(userId, type, err, hash) {
|
|||||||
// downloads the images for +userId+ while checking the cache
|
// downloads the images for +userId+ while checking the cache
|
||||||
// status based on +cache_details+. +type+ specifies which
|
// status based on +cache_details+. +type+ specifies which
|
||||||
// image type should be called back on
|
// image type should be called back on
|
||||||
// callback: error, image hash
|
// callback: error, image hash, slim
|
||||||
function store_images(rid, userId, cache_details, type, callback) {
|
function store_images(rid, userId, cache_details, type, callback) {
|
||||||
var is_uuid = userId.length > 16;
|
var is_uuid = userId.length > 16;
|
||||||
if (requests[type]["!" + userId]) {
|
if (requests[type]["!" + userId]) {
|
||||||
@ -167,34 +172,34 @@ function store_images(rid, userId, cache_details, type, callback) {
|
|||||||
// error or uuid without profile
|
// error or uuid without profile
|
||||||
if (!err && !profile) {
|
if (!err && !profile) {
|
||||||
// no error, but uuid without profile
|
// no error, but uuid without profile
|
||||||
cache.save_hash(rid, userId, null, null, function(cache_err) {
|
cache.save_hash(rid, userId, null, null, undefined, function(cache_err) {
|
||||||
// we have no profile, so we have neither skin nor cape
|
// we have no profile, so we have neither skin nor cape
|
||||||
resume(userId, "skin", cache_err, null);
|
resume(userId, "skin", cache_err, null, false);
|
||||||
resume(userId, "cape", cache_err, null);
|
resume(userId, "cape", cache_err, null, false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// an error occured, not caching. we can try in 60 seconds
|
// an error occured, not caching. we can try in 60 seconds
|
||||||
resume(userId, type, err, null);
|
resume(userId, type, err, null, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no error and we have a profile (if it's a uuid)
|
// no error and we have a profile (if it's a uuid)
|
||||||
store_skin(rid, userId, profile, cache_details, function(store_err, skin_hash) {
|
store_skin(rid, userId, profile, cache_details, function(store_err, skin_hash, slim) {
|
||||||
if (store_err && !skin_hash) {
|
if (store_err && !skin_hash) {
|
||||||
// an error occured, not caching. we can try in 60 seconds
|
// an error occured, not caching. we can try in 60 seconds
|
||||||
resume(userId, "skin", store_err, null);
|
resume(userId, "skin", store_err, null, slim);
|
||||||
} else {
|
} else {
|
||||||
cache.save_hash(rid, userId, skin_hash, undefined, function(cache_err) {
|
cache.save_hash(rid, userId, skin_hash, undefined, slim, function(cache_err) {
|
||||||
resume(userId, "skin", (store_err || cache_err), skin_hash);
|
resume(userId, "skin", (store_err || cache_err), skin_hash, slim);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
store_cape(rid, userId, profile, cache_details, function(store_err, cape_hash) {
|
store_cape(rid, userId, profile, cache_details, function(store_err, cape_hash) {
|
||||||
if (store_err && !cape_hash) {
|
if (store_err && !cape_hash) {
|
||||||
// an error occured, not caching. we can try in 60 seconds
|
// an error occured, not caching. we can try in 60 seconds
|
||||||
resume(userId, "cape", (store_err), cape_hash);
|
resume(userId, "cape", (store_err), cape_hash, false);
|
||||||
} else {
|
} else {
|
||||||
cache.save_hash(rid, userId, undefined, cape_hash, function(cache_err) {
|
cache.save_hash(rid, userId, undefined, cape_hash, undefined, function(cache_err) {
|
||||||
resume(userId, "cape", (store_err || cache_err), cape_hash);
|
resume(userId, "cape", (store_err || cache_err), cape_hash, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -212,7 +217,7 @@ exp.id_valid = function(userId) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// decides whether to get a +type+ image for +userId+ from disk or to download it
|
// decides whether to get a +type+ image for +userId+ from disk or to download it
|
||||||
// callback: error, status, hash
|
// callback: error, status, hash, slim
|
||||||
// for status, see response.js
|
// for status, see response.js
|
||||||
exp.get_image_hash = function(rid, userId, type, callback) {
|
exp.get_image_hash = function(rid, userId, type, callback) {
|
||||||
cache.get_details(userId, function(err, cache_details) {
|
cache.get_details(userId, function(err, cache_details) {
|
||||||
@ -221,31 +226,32 @@ exp.get_image_hash = function(rid, userId, type, callback) {
|
|||||||
cached_hash = type === "skin" ? cache_details.skin : cache_details.cape;
|
cached_hash = type === "skin" ? cache_details.skin : cache_details.cape;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err, -1, null);
|
callback(err, -1, null, false);
|
||||||
} else {
|
} else {
|
||||||
if (cache_details && cache_details[type] !== undefined && cache_details.time + config.caching.local * 1000 >= Date.now()) {
|
if (cache_details && cache_details[type] !== undefined && cache_details.time + config.caching.local * 1000 >= Date.now()) {
|
||||||
// use cached image
|
// use cached image
|
||||||
logging.debug(rid, "userId cached & recently updated");
|
logging.debug(rid, "userId cached & recently updated");
|
||||||
callback(null, (cached_hash ? 1 : 0), cached_hash);
|
callback(null, (cached_hash ? 1 : 0), cached_hash, cache_details.slim);
|
||||||
} else {
|
} else {
|
||||||
// download image
|
// download image
|
||||||
if (cache_details) {
|
if (cache_details && cache_details[type] !== undefined) {
|
||||||
logging.debug(rid, "userId cached, but too old");
|
logging.debug(rid, "userId cached, but too old");
|
||||||
|
logging.debug(rid, JSON.stringify(cache_details));
|
||||||
} else {
|
} else {
|
||||||
logging.debug(rid, "userId not cached");
|
logging.debug(rid, "userId not cached");
|
||||||
}
|
}
|
||||||
store_images(rid, userId, cache_details, type, function(store_err, new_hash) {
|
store_images(rid, userId, cache_details, type, function(store_err, new_hash, slim) {
|
||||||
if (store_err) {
|
if (store_err) {
|
||||||
// we might have a cached hash although an error occured
|
// we might have a cached hash although an error occured
|
||||||
// (e.g. Mojang servers not reachable, using outdated hash)
|
// (e.g. Mojang servers not reachable, using outdated hash)
|
||||||
cache.update_timestamp(rid, userId, true, function(err2) {
|
cache.update_timestamp(rid, userId, true, function(err2) {
|
||||||
callback(err2 || store_err, -1, cache_details && cached_hash);
|
callback(err2 || store_err, -1, cache_details && cached_hash, slim);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var status = cache_details && (cached_hash === new_hash) ? 3 : 2;
|
var status = cache_details && (cached_hash === new_hash) ? 3 : 2;
|
||||||
logging.debug(rid, "cached hash:", (cache_details && cached_hash));
|
logging.debug(rid, "cached hash:", (cache_details && cached_hash));
|
||||||
logging.debug(rid, "new hash:", new_hash);
|
logging.debug(rid, "new hash:", new_hash);
|
||||||
callback(null, status, new_hash);
|
callback(null, status, new_hash, slim);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -259,7 +265,7 @@ exp.get_image_hash = function(rid, userId, type, callback) {
|
|||||||
// image is the user's face+overlay when overlay is true, or the face otherwise
|
// image is the user's face+overlay when overlay is true, or the face otherwise
|
||||||
// for status, see get_image_hash
|
// for status, see get_image_hash
|
||||||
exp.get_avatar = function(rid, userId, overlay, size, callback) {
|
exp.get_avatar = function(rid, userId, overlay, size, callback) {
|
||||||
exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash) {
|
exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash, slim) {
|
||||||
if (skin_hash) {
|
if (skin_hash) {
|
||||||
var facepath = path.join(config.directories.faces, skin_hash + ".png");
|
var facepath = path.join(config.directories.faces, skin_hash + ".png");
|
||||||
var helmpath = path.join(config.directories.helms, skin_hash + ".png");
|
var helmpath = path.join(config.directories.helms, skin_hash + ".png");
|
||||||
@ -284,25 +290,25 @@ exp.get_avatar = function(rid, userId, overlay, size, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// handles requests for +userId+ skins
|
// handles requests for +userId+ skins
|
||||||
// callback: error, skin hash, status, image buffer
|
// callback: error, skin hash, status, image buffer, slim
|
||||||
exp.get_skin = function(rid, userId, callback) {
|
exp.get_skin = function(rid, userId, callback) {
|
||||||
exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash) {
|
exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash, slim) {
|
||||||
if (skin_hash) {
|
if (skin_hash) {
|
||||||
var skinpath = path.join(config.directories.skins, skin_hash + ".png");
|
var skinpath = path.join(config.directories.skins, skin_hash + ".png");
|
||||||
fs.exists(skinpath, function(exists) {
|
fs.exists(skinpath, function(exists) {
|
||||||
if (exists) {
|
if (exists) {
|
||||||
logging.debug(rid, "skin already exists, not downloading");
|
logging.debug(rid, "skin already exists, not downloading");
|
||||||
skins.open_skin(rid, skinpath, function(skin_err, img) {
|
skins.open_skin(rid, skinpath, function(skin_err, img) {
|
||||||
callback(skin_err || err, skin_hash, status, img);
|
callback(skin_err || err, skin_hash, status, img, slim);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
networking.save_texture(rid, skin_hash, skinpath, function(net_err, response, img) {
|
networking.save_texture(rid, skin_hash, skinpath, function(net_err, response, img) {
|
||||||
callback(net_err || err, skin_hash, status, img);
|
callback(net_err || err, skin_hash, status, img, slim);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
callback(err, null, status, null);
|
callback(err, null, status, null, slim);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -318,12 +324,12 @@ function get_type(overlay, body) {
|
|||||||
// handles creations of 3D renders
|
// handles creations of 3D renders
|
||||||
// callback: error, skin hash, image buffer
|
// callback: error, skin hash, image buffer
|
||||||
exp.get_render = function(rid, userId, scale, overlay, body, callback) {
|
exp.get_render = function(rid, userId, scale, overlay, body, callback) {
|
||||||
exp.get_skin(rid, userId, function(err, skin_hash, status, img) {
|
exp.get_skin(rid, userId, function(err, skin_hash, status, img, slim) {
|
||||||
if (!skin_hash) {
|
if (!skin_hash) {
|
||||||
callback(err, status, skin_hash, null);
|
callback(err, status, skin_hash, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var renderpath = path.join(config.directories.renders, [skin_hash, scale, get_type(overlay, body)].join("-") + ".png");
|
var renderpath = path.join(config.directories.renders, [skin_hash, scale, get_type(overlay, body), slim ? "s" : "t"].join("-") + ".png");
|
||||||
fs.exists(renderpath, function(exists) {
|
fs.exists(renderpath, function(exists) {
|
||||||
if (exists) {
|
if (exists) {
|
||||||
renders.open_render(rid, renderpath, function(render_err, rendered_img) {
|
renders.open_render(rid, renderpath, function(render_err, rendered_img) {
|
||||||
@ -335,7 +341,7 @@ exp.get_render = function(rid, userId, scale, overlay, body, callback) {
|
|||||||
callback(err, 0, skin_hash, null);
|
callback(err, 0, skin_hash, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
renders.draw_model(rid, img, scale, overlay, body, function(draw_err, drawn_img) {
|
renders.draw_model(rid, img, scale, overlay, body, slim || userId.toLowerCase() === "mhf_alex", function(draw_err, drawn_img) {
|
||||||
if (draw_err) {
|
if (draw_err) {
|
||||||
callback(draw_err, -1, skin_hash, null);
|
callback(draw_err, -1, skin_hash, null);
|
||||||
} else if (!drawn_img) {
|
} else if (!drawn_img) {
|
||||||
@ -354,7 +360,7 @@ exp.get_render = function(rid, userId, scale, overlay, body, callback) {
|
|||||||
// handles requests for +userId+ capes
|
// handles requests for +userId+ capes
|
||||||
// callback: error, cape hash, status, image buffer
|
// callback: error, cape hash, status, image buffer
|
||||||
exp.get_cape = function(rid, userId, callback) {
|
exp.get_cape = function(rid, userId, callback) {
|
||||||
exp.get_image_hash(rid, userId, "cape", function(err, status, cape_hash) {
|
exp.get_image_hash(rid, userId, "cape", function(err, status, cape_hash, slim) {
|
||||||
if (!cape_hash) {
|
if (!cape_hash) {
|
||||||
callback(err, null, status, null);
|
callback(err, null, status, null);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -3,6 +3,7 @@ var logging = require("./logging");
|
|||||||
var request = require("request");
|
var request = require("request");
|
||||||
var config = require("../config");
|
var config = require("../config");
|
||||||
var skins = require("./skins");
|
var skins = require("./skins");
|
||||||
|
require("./object-patch");
|
||||||
|
|
||||||
var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";
|
var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";
|
||||||
var skins_url = "https://skins.minecraft.net/MinecraftSkins/";
|
var skins_url = "https://skins.minecraft.net/MinecraftSkins/";
|
||||||
@ -12,50 +13,22 @@ var mojang_urls = [skins_url, capes_url];
|
|||||||
|
|
||||||
var exp = {};
|
var exp = {};
|
||||||
|
|
||||||
// extracts the +type+ [SKIN|CAPE] URL
|
// helper method that calls `get_username_url` or `get_uuid_info` based on the +usedId+
|
||||||
// from the nested & encoded +profile+ object
|
|
||||||
// returns the URL or null if not present
|
|
||||||
function extract_url(profile, type) {
|
|
||||||
var url = null;
|
|
||||||
if (profile && profile.properties) {
|
|
||||||
profile.properties.forEach(function(prop) {
|
|
||||||
if (prop.name === "textures") {
|
|
||||||
var json = new Buffer(prop.value, "base64").toString();
|
|
||||||
var props = JSON.parse(json);
|
|
||||||
url = props && props.textures && props.textures[type] && props.textures[type].url || null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper method that calls `get_username_url` or `get_uuid_url` based on the +usedId+
|
|
||||||
// +userId+ is used for usernames, while +profile+ is used for UUIDs
|
// +userId+ is used for usernames, while +profile+ is used for UUIDs
|
||||||
function get_url(rid, userId, profile, type, callback) {
|
// callback: error, url, slim
|
||||||
|
function get_info(rid, userId, profile, type, callback) {
|
||||||
if (userId.length <= 16) {
|
if (userId.length <= 16) {
|
||||||
// username
|
// username
|
||||||
exp.get_username_url(rid, userId, type, function(err, url) {
|
exp.get_username_url(rid, userId, type, function(err, url) {
|
||||||
callback(err, url || null);
|
callback(err, url || null, false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
exp.get_uuid_url(profile, type, function(url) {
|
exp.get_uuid_info(profile, type, function(url, slim) {
|
||||||
callback(null, url || null);
|
callback(null, url || null, slim);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// exracts the skin URL of a +profile+ object
|
|
||||||
// returns null when no URL found (user has no skin)
|
|
||||||
exp.extract_skin_url = function(profile) {
|
|
||||||
return extract_url(profile, "SKIN");
|
|
||||||
};
|
|
||||||
|
|
||||||
// exracts the cape URL of a +profile+ object
|
|
||||||
// returns null when no URL found (user has no cape)
|
|
||||||
exp.extract_cape_url = function(profile) {
|
|
||||||
return extract_url(profile, "CAPE");
|
|
||||||
};
|
|
||||||
|
|
||||||
// performs a GET request to the +url+
|
// performs a GET request to the +url+
|
||||||
// +options+ object includes these options:
|
// +options+ object includes these options:
|
||||||
// encoding (string), default is to return a buffer
|
// encoding (string), default is to return a buffer
|
||||||
@ -133,6 +106,7 @@ exp.get_from = function(rid, url, callback) {
|
|||||||
// the skin url is taken from the HTTP redirect
|
// the skin url is taken from the HTTP redirect
|
||||||
// type reference is above
|
// type reference is above
|
||||||
exp.get_username_url = function(rid, name, type, callback) {
|
exp.get_username_url = function(rid, name, type, callback) {
|
||||||
|
type = Number(type === "CAPE");
|
||||||
exp.get_from(rid, mojang_urls[type] + name + ".png", function(body, response, err) {
|
exp.get_from(rid, mojang_urls[type] + name + ".png", function(body, response, err) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (response) {
|
if (response) {
|
||||||
@ -147,15 +121,24 @@ exp.get_username_url = function(rid, name, type, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// gets the URL for a skin/cape from the profile
|
// gets the URL for a skin/cape from the profile
|
||||||
// +type+ specifies which to retrieve
|
// +type+ "SKIN" or "CAPE", specifies which to retrieve
|
||||||
exp.get_uuid_url = function(profile, type, callback) {
|
// callback: url, slim
|
||||||
var url = null;
|
exp.get_uuid_info = function(profile, type, callback) {
|
||||||
if (type === 0) {
|
var properties = Object.get(profile, "properties") || [];
|
||||||
url = exp.extract_skin_url(profile);
|
properties.forEach(function(prop) {
|
||||||
} else if (type === 1) {
|
if (prop.name === "textures") {
|
||||||
url = exp.extract_cape_url(profile);
|
var json = new Buffer(prop.value, "base64").toString();
|
||||||
|
profile = JSON.parse(json);
|
||||||
}
|
}
|
||||||
callback(url || null);
|
});
|
||||||
|
|
||||||
|
var url = Object.get(profile, "textures." + type + ".url");
|
||||||
|
var slim;
|
||||||
|
if (type === "SKIN") {
|
||||||
|
slim = Object.get(profile, "textures.SKIN.metadata.model") === "slim";
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(url || null, !!slim);
|
||||||
};
|
};
|
||||||
|
|
||||||
// make a request to sessionserver for +uuid+
|
// make a request to sessionserver for +uuid+
|
||||||
@ -181,20 +164,17 @@ exp.get_profile = function(rid, uuid, callback) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// get the skin URL for +userId+
|
// get the skin URL and type for +userId+
|
||||||
// +profile+ is used if +userId+ is a uuid
|
// +profile+ is used if +userId+ is a uuid
|
||||||
exp.get_skin_url = function(rid, userId, profile, callback) {
|
// callback: error, url, slim
|
||||||
get_url(rid, userId, profile, 0, function(err, url) {
|
exp.get_skin_info = function(rid, userId, profile, callback) {
|
||||||
callback(err, url);
|
get_info(rid, userId, profile, "SKIN", callback);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// get the cape URL for +userId+
|
// get the cape URL for +userId+
|
||||||
// +profile+ is used if +userId+ is a uuid
|
// +profile+ is used if +userId+ is a uuid
|
||||||
exp.get_cape_url = function(rid, userId, profile, callback) {
|
exp.get_cape_url = function(rid, userId, profile, callback) {
|
||||||
get_url(rid, userId, profile, 1, function(err, url) {
|
get_info(rid, userId, profile, "CAPE", callback);
|
||||||
callback(err, url);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// download the +tex_hash+ image from the texture server
|
// download the +tex_hash+ image from the texture server
|
||||||
|
|||||||
22
lib/object-patch.js
Normal file
22
lib/object-patch.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Adds Object.get function
|
||||||
|
// +pathstr+ is a string of dot-separated nested properties on +ojb+
|
||||||
|
// returns undefined if any of the properties do not exist
|
||||||
|
// returns the value of the last property otherwise
|
||||||
|
//
|
||||||
|
// Object.get({"foo": {"bar": 123}}, "foo.bar"); // 123
|
||||||
|
// Object.get({"foo": {"bar": 123}}, "bar.foo"); // undefined
|
||||||
|
Object.get = function(obj, pathstr) {
|
||||||
|
var path = pathstr.split(".");
|
||||||
|
var result = obj;
|
||||||
|
|
||||||
|
for (var i = 0; i < path.length; i++) {
|
||||||
|
var key = path[i];
|
||||||
|
if (!result || !result.hasOwnProperty(key)) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
result = result[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
394
lib/renders.js
394
lib/renders.js
@ -8,200 +8,246 @@ var Canvas = require("canvas");
|
|||||||
var Image = Canvas.Image;
|
var Image = Canvas.Image;
|
||||||
var exp = {};
|
var exp = {};
|
||||||
|
|
||||||
// scales an image from the +imagedata+ onto the +context+
|
// set alpha values to 255
|
||||||
// scaled by a factor of +scale+ with options +d_x+ and +d_y+
|
function removeTransparency(canvas) {
|
||||||
function scale_image(imageData, context, d_x, d_y, scale) {
|
var ctx = canvas.getContext("2d");
|
||||||
var width = imageData.width;
|
var imagedata = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
var height = imageData.height;
|
|
||||||
context.clearRect(0, 0, width, height); // Clear the spot where it originated from
|
|
||||||
for (var y = 0; y < height; y++) { // height original
|
|
||||||
for (var x = 0; x < width; x++) { // width original
|
|
||||||
// Gets original colour, then makes a scaled square of the same colour
|
|
||||||
var index = (x + y * width) * 4;
|
|
||||||
context.fillStyle = "rgba(" + imageData.data[index + 0] + ", " + imageData.data[index + 1] + ", " + imageData.data[index + 2] + ", " + imageData.data[index + 3] + ")";
|
|
||||||
context.fillRect(d_x + x * scale, d_y + y * scale, scale, scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// makes images less worse by using binary transparency
|
|
||||||
function enhance(context) {
|
|
||||||
var imagedata = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
|
|
||||||
var data = imagedata.data;
|
var data = imagedata.data;
|
||||||
// data is [r,g,b,a, r,g,b,a, *]
|
// data is [r,g,b,a, r,g,b,a, *]
|
||||||
for (var i = 3; i < data.length; i += 4) {
|
for (var i = 0; i < data.length; i += 4) {
|
||||||
// round to 0 or 255
|
// usually we would have to check for alpha = 0
|
||||||
data[i] = Math.round(data[i] / 255) * 255;
|
// and set color to black here
|
||||||
|
// but node-canvas already does that for us
|
||||||
|
|
||||||
|
// remove transparency
|
||||||
|
data[i + 3] = 255;
|
||||||
}
|
}
|
||||||
context.putImageData(imagedata, 0, 0);
|
ctx.putImageData(imagedata, 0, 0);
|
||||||
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
// draws the helmet on to the +skin_canvas+
|
function hasTransparency(canvas) {
|
||||||
// using the skin from the +model_ctx+ at the +scale+
|
var ctx = canvas.getContext("2d");
|
||||||
exp.draw_helmet = function(skin_canvas, model_ctx, scale) {
|
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
|
||||||
// Helmet - Front
|
for (var i = 3; i < imageData.length; i += 4) {
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
if (imageData[i] < 255) {
|
||||||
model_ctx.drawImage(skin_canvas, 40 * scale, 8 * scale, 8 * scale, 8 * scale, 10 * scale, 13 / 1.2 * scale, 8 * scale, 8 * scale);
|
// found pixel with translucent alpha value
|
||||||
// Helmet - Right
|
return true;
|
||||||
model_ctx.setTransform(1, 0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 32 * scale, 8 * scale, 8 * scale, 8 * scale, 2 * scale, 3 / 1.2 * scale, 8 * scale, 8 * scale);
|
|
||||||
// Helmet - Top
|
|
||||||
model_ctx.setTransform(-1, 0.5, 1, 0.5, 0, 0);
|
|
||||||
model_ctx.scale(-1, 1);
|
|
||||||
model_ctx.drawImage(skin_canvas, 40 * scale, 0, 8 * scale, 8 * scale, -3 * scale, 5 * scale, 8 * scale, 8 * scale);
|
|
||||||
};
|
|
||||||
|
|
||||||
// draws the head on to the +skin_canvas+
|
|
||||||
// using the skin from the +model_ctx+ at the +scale+
|
|
||||||
exp.draw_head = function(skin_canvas, model_ctx, scale) {
|
|
||||||
// Head - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 8 * scale, 8 * scale, 8 * scale, 8 * scale, 10 * scale, 13 / 1.2 * scale, 8 * scale, 8 * scale);
|
|
||||||
// Head - Right
|
|
||||||
model_ctx.setTransform(1, 0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 0, 8 * scale, 8 * scale, 8 * scale, 2 * scale, 3 / 1.2 * scale, 8 * scale, 8 * scale);
|
|
||||||
// Head - Top
|
|
||||||
model_ctx.setTransform(-1, 0.5, 1, 0.5, 0, 0);
|
|
||||||
model_ctx.scale(-1, 1);
|
|
||||||
model_ctx.drawImage(skin_canvas, 8 * scale, 0, 8 * scale, 8 * scale, -3 * scale, 5 * scale, 8 * scale, 8 * scale);
|
|
||||||
};
|
|
||||||
|
|
||||||
// draws the body on to the +skin_canvas+
|
|
||||||
// using the skin from the +model_ctx+ at the +scale+
|
|
||||||
// parts are labeled as if drawn from the skin's POV
|
|
||||||
exp.draw_body = function(rid, skin_canvas, model_ctx, scale) {
|
|
||||||
if (skin_canvas.height === 32 * scale) {
|
|
||||||
logging.debug(rid, "uses old skin format");
|
|
||||||
// Left Leg
|
|
||||||
// Left Leg - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.scale(-1, 1);
|
|
||||||
model_ctx.drawImage(skin_canvas, 4 * scale, 20 * scale, 4 * scale, 12 * scale, -16 * scale, 34.4 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
|
|
||||||
// Right Leg
|
|
||||||
// Right Leg - Right
|
|
||||||
model_ctx.setTransform(1, 0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 0 * scale, 20 * scale, 4 * scale, 12 * scale, 4 * scale, 26.4 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Right Leg - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 4 * scale, 20 * scale, 4 * scale, 12 * scale, 8 * scale, 34.4 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
|
|
||||||
// Arm Left
|
|
||||||
// Arm Left - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.scale(-1, 1);
|
|
||||||
model_ctx.drawImage(skin_canvas, 44 * scale, 20 * scale, 4 * scale, 12 * scale, -20 * scale, 20 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Arm Left - Top
|
|
||||||
model_ctx.setTransform(-1, 0.5, 1, 0.5, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 44 * scale, 16 * scale, 4 * scale, 4 * scale, 0, 16 * scale, 4 * scale, 4 * scale);
|
|
||||||
|
|
||||||
// Body
|
|
||||||
// Body - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 20 * scale, 20 * scale, 8 * scale, 12 * scale, 8 * scale, 20 / 1.2 * scale, 8 * scale, 12 * scale);
|
|
||||||
|
|
||||||
// Arm Right
|
|
||||||
// Arm Right - Right
|
|
||||||
model_ctx.setTransform(1, 0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 40 * scale, 20 * scale, 4 * scale, 12 * scale, 0, 16 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Arm Right - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 44 * scale, 20 * scale, 4 * scale, 12 * scale, 4 * scale, 20 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Arm Right - Top
|
|
||||||
model_ctx.setTransform(-1, 0.5, 1, 0.5, 0, 0);
|
|
||||||
model_ctx.scale(-1, 1);
|
|
||||||
model_ctx.drawImage(skin_canvas, 44 * scale, 16 * scale, 4 * scale, 4 * scale, -16 * scale, 16 * scale, 4 * scale, 4 * scale);
|
|
||||||
} else {
|
|
||||||
logging.debug(rid, "uses new skin format");
|
|
||||||
// Left Leg
|
|
||||||
// Left Leg - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 20 * scale, 52 * scale, 4 * scale, 12 * scale, 12 * scale, 34.4 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
|
|
||||||
// Right Leg
|
|
||||||
// Right Leg - Right
|
|
||||||
model_ctx.setTransform(1, 0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 0, 20 * scale, 4 * scale, 12 * scale, 4 * scale, 26.4 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Right Leg - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 4 * scale, 20 * scale, 4 * scale, 12 * scale, 8 * scale, 34.4 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
|
|
||||||
// Arm Left
|
|
||||||
// Arm Left - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 36 * scale, 52 * scale, 4 * scale, 12 * scale, 16 * scale, 20 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Arm Left - Top
|
|
||||||
model_ctx.setTransform(-1, 0.5, 1, 0.5, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 36 * scale, 48 * scale, 4 * scale, 4 * scale, 0, 16 * scale, 4 * scale, 4 * scale);
|
|
||||||
|
|
||||||
// Body
|
|
||||||
// Body - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 20 * scale, 20 * scale, 8 * scale, 12 * scale, 8 * scale, 20 / 1.2 * scale, 8 * scale, 12 * scale);
|
|
||||||
|
|
||||||
// Arm Right
|
|
||||||
// Arm Right - Right
|
|
||||||
model_ctx.setTransform(1, 0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 40 * scale, 20 * scale, 4 * scale, 12 * scale, 0, 16 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Arm Right - Front
|
|
||||||
model_ctx.setTransform(1, -0.5, 0, 1.2, 0, 0);
|
|
||||||
model_ctx.drawImage(skin_canvas, 44 * scale, 20 * scale, 4 * scale, 12 * scale, 4 * scale, 20 / 1.2 * scale, 4 * scale, 12 * scale);
|
|
||||||
// Arm Right - Top
|
|
||||||
model_ctx.setTransform(-1, 0.5, 1, 0.5, 0, 0);
|
|
||||||
model_ctx.scale(-1, 1);
|
|
||||||
model_ctx.drawImage(skin_canvas, 44 * scale, 16 * scale, 4 * scale, 4 * scale, -16 * scale, 16 * scale, 4 * scale, 4 * scale);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// sets up the necessary components to draw the skin model
|
|
||||||
// uses the +img+ skin with options of drawing
|
|
||||||
// the +overlay+ and the +body+
|
|
||||||
// callback: error, image buffer
|
|
||||||
exp.draw_model = function(rid, img, scale, overlay, body, callback) {
|
|
||||||
var image = new Image();
|
|
||||||
|
|
||||||
image.onerror = function(err) {
|
|
||||||
callback(err, null);
|
|
||||||
};
|
|
||||||
|
|
||||||
image.onload = function() {
|
|
||||||
var width = 64 * scale;
|
|
||||||
var original_height = image.height === 32 ? 32 : 64;
|
|
||||||
var height = original_height * scale;
|
|
||||||
var model_canvas = new Canvas(20 * scale, (body ? 44.8 : 17.6) * scale);
|
|
||||||
var skin_canvas = new Canvas(width, height);
|
|
||||||
var model_ctx = model_canvas.getContext("2d");
|
|
||||||
var skin_ctx = skin_canvas.getContext("2d");
|
|
||||||
|
|
||||||
skin_ctx.drawImage(image, 0, 0, 64, original_height);
|
|
||||||
// Scale it
|
|
||||||
scale_image(skin_ctx.getImageData(0, 0, 64, original_height), skin_ctx, 0, 0, scale);
|
|
||||||
if (body) {
|
|
||||||
exp.draw_body(rid, skin_canvas, model_ctx, scale);
|
|
||||||
}
|
}
|
||||||
exp.draw_head(skin_canvas, model_ctx, scale);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resize(src, scale) {
|
||||||
|
var dst = new Canvas();
|
||||||
|
dst.width = scale * src.width;
|
||||||
|
dst.height = scale * src.height;
|
||||||
|
var context = dst.getContext("2d");
|
||||||
|
|
||||||
|
// don't blur on resize
|
||||||
|
context.patternQuality = "fast";
|
||||||
|
|
||||||
|
context.drawImage(src, 0, 0, src.width * scale, src.height * scale);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPart(src, x, y, width, height, scale) {
|
||||||
|
var dst = new Canvas();
|
||||||
|
dst.width = scale * width;
|
||||||
|
dst.height = scale * height;
|
||||||
|
var context = dst.getContext("2d");
|
||||||
|
|
||||||
|
// don't blur on resize
|
||||||
|
context.patternQuality = "fast";
|
||||||
|
|
||||||
|
context.drawImage(src, x, y, width, height, 0, 0, width * scale, height * scale);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
function flip(src) {
|
||||||
|
var dst = new Canvas();
|
||||||
|
dst.width = src.width;
|
||||||
|
dst.height = src.height;
|
||||||
|
var context = dst.getContext("2d");
|
||||||
|
context.scale(-1, 1);
|
||||||
|
context.drawImage(src, -src.width, 0);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skew for isometric perspective
|
||||||
|
var skew_a = 26 / 45; // 0.57777777
|
||||||
|
var skew_b = skew_a * 2; // 1.15555555
|
||||||
|
|
||||||
|
exp.draw_model = function(rid, img, scale, overlay, is_body, slim, callback) {
|
||||||
|
var canvas = new Canvas();
|
||||||
|
canvas.width = scale * 20;
|
||||||
|
canvas.height = scale * (is_body ? 45.1 : 18.5);
|
||||||
|
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
var skin = new Image();
|
||||||
|
|
||||||
|
skin.onload = function() {
|
||||||
|
var old_skin = skin.height === 32;
|
||||||
|
var arm_width = slim ? 3 : 4;
|
||||||
|
|
||||||
|
/* eslint-disable no-multi-spaces */
|
||||||
|
var head_top = resize(removeTransparency(getPart(skin, 8, 0, 8, 8, 1)), scale);
|
||||||
|
var head_front = resize(removeTransparency(getPart(skin, 8, 8, 8, 8, 1)), scale);
|
||||||
|
var head_right = resize(removeTransparency(getPart(skin, 0, 8, 8, 8, 1)), scale);
|
||||||
|
|
||||||
|
var arm_right_top = resize(removeTransparency(getPart(skin, 44, 16, arm_width, 4, 1)), scale);
|
||||||
|
var arm_right_front = resize(removeTransparency(getPart(skin, 44, 20, arm_width, 12, 1)), scale);
|
||||||
|
var arm_right_side = resize(removeTransparency(getPart(skin, 40, 20, 4, 12, 1)), scale);
|
||||||
|
|
||||||
|
var arm_left_top = old_skin ? flip(arm_right_top) : resize(removeTransparency(getPart(skin, 36, 48, arm_width, 4, 1)), scale);
|
||||||
|
var arm_left_front = old_skin ? flip(arm_right_front) : resize(removeTransparency(getPart(skin, 36, 52, arm_width, 12, 1)), scale);
|
||||||
|
|
||||||
|
var leg_right_front = resize(removeTransparency(getPart(skin, 4, 20, 4, 12, 1)), scale);
|
||||||
|
var leg_right_side = resize(removeTransparency(getPart(skin, 0, 20, 4, 12, 1)), scale);
|
||||||
|
|
||||||
|
var leg_left_front = old_skin ? flip(leg_right_front) : resize(removeTransparency(getPart(skin, 20, 52, 4, 12, 1)), scale);
|
||||||
|
|
||||||
|
var body_front = resize(removeTransparency(getPart(skin, 20, 20, 8, 12, 1)), scale);
|
||||||
|
/* eslint-enable no-multi-spaces */
|
||||||
|
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
exp.draw_helmet(skin_canvas, model_ctx, scale);
|
if (hasTransparency(getPart(skin, 32, 0, 32, 32, 1))) {
|
||||||
|
// render head overlay
|
||||||
|
head_top.getContext("2d").drawImage(getPart(skin, 40, 0, 8, 8, scale), 0, 0);
|
||||||
|
head_front.getContext("2d").drawImage(getPart(skin, 40, 8, 8, 8, scale), 0, 0);
|
||||||
|
head_right.getContext("2d").drawImage(getPart(skin, 32, 8, 8, 8, scale), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This is a temporary fix for #32
|
if (!old_skin) {
|
||||||
enhance(model_ctx);
|
// See #117
|
||||||
|
// if MC-89760 gets fixed, we can (probably) simply check the whole skin for transparency
|
||||||
|
|
||||||
model_canvas.toBuffer(function(err, buf) {
|
/* eslint-disable no-multi-spaces */
|
||||||
|
var body_region = getPart(skin, 16, 32, 32, 16, 1);
|
||||||
|
var right_arm_region = getPart(skin, 48, 48, 16, 16, 1);
|
||||||
|
var left_arm_region = getPart(skin, 40, 32, 16, 16, 1);
|
||||||
|
var right_leg_region = getPart(skin, 0, 32, 16, 16, 1);
|
||||||
|
var left_leg_region = getPart(skin, 0, 48, 16, 16, 1);
|
||||||
|
/* eslint-enable no-multi-spaces */
|
||||||
|
|
||||||
|
if (hasTransparency(body_region)) {
|
||||||
|
// render body overlay
|
||||||
|
body_front.getContext("2d").drawImage(getPart(skin, 20, 36, 8, 12, scale), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTransparency(right_arm_region)) {
|
||||||
|
// render right arm overlay
|
||||||
|
arm_right_top.getContext("2d").drawImage(getPart(skin, 44, 32, arm_width, 4, scale), 0, 0);
|
||||||
|
arm_right_front.getContext("2d").drawImage(getPart(skin, 44, 36, arm_width, 12, scale), 0, 0);
|
||||||
|
arm_right_side.getContext("2d").drawImage(getPart(skin, 40, 36, 4, 12, scale), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTransparency(left_arm_region)) {
|
||||||
|
// render left arm overlay
|
||||||
|
arm_left_top.getContext("2d").drawImage(getPart(skin, 36 + 16, 48, arm_width, 4, scale), 0, 0);
|
||||||
|
arm_left_front.getContext("2d").drawImage(getPart(skin, 36 + 16, 52, arm_width, 12, scale), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTransparency(right_leg_region)) {
|
||||||
|
// render right leg overlay
|
||||||
|
leg_right_front.getContext("2d").drawImage(getPart(skin, 4, 36, 4, 12, scale), 0, 0);
|
||||||
|
leg_right_side.getContext("2d").drawImage(getPart(skin, 0, 36, 4, 12, scale), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTransparency(left_leg_region)) {
|
||||||
|
// render left leg overlay
|
||||||
|
leg_left_front.getContext("2d").drawImage(getPart(skin, 4, 52, 4, 12, scale), 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var x = 0;
|
||||||
|
var y = 0;
|
||||||
|
var z = 0;
|
||||||
|
|
||||||
|
var z_offset = scale * 3;
|
||||||
|
var x_offset = scale * 2;
|
||||||
|
|
||||||
|
if (is_body) {
|
||||||
|
// pre-render front onto separate canvas
|
||||||
|
var front = new Canvas();
|
||||||
|
front.width = scale * 16;
|
||||||
|
front.height = scale * 24;
|
||||||
|
var frontc = front.getContext("2d");
|
||||||
|
frontc.patternQuality = "fast";
|
||||||
|
|
||||||
|
frontc.drawImage(arm_right_front, (4 - arm_width) * scale, 0 * scale, arm_width * scale, 12 * scale);
|
||||||
|
frontc.drawImage(arm_left_front, 12 * scale, 0 * scale, arm_width * scale, 12 * scale);
|
||||||
|
frontc.drawImage(body_front, 4 * scale, 0 * scale, 8 * scale, 12 * scale);
|
||||||
|
frontc.drawImage(leg_right_front, 4 * scale, 12 * scale, 4 * scale, 12 * scale);
|
||||||
|
frontc.drawImage(leg_left_front, 8 * scale, 12 * scale, 4 * scale, 12 * scale);
|
||||||
|
|
||||||
|
|
||||||
|
// top
|
||||||
|
x = x_offset + scale * 2;
|
||||||
|
y = scale * -arm_width;
|
||||||
|
z = z_offset + scale * 8;
|
||||||
|
ctx.setTransform(1, -skew_a, 1, skew_a, 0, 0);
|
||||||
|
ctx.drawImage(arm_right_top, y - z - 0.5, x + z, arm_right_top.width + 1, arm_right_top.height + 1);
|
||||||
|
|
||||||
|
y = scale * 8;
|
||||||
|
ctx.drawImage(arm_left_top, y - z, x + z, arm_left_top.width, arm_left_top.height + 1);
|
||||||
|
|
||||||
|
// right side
|
||||||
|
ctx.setTransform(1, skew_a, 0, skew_b, 0, 0);
|
||||||
|
x = x_offset + scale * 2;
|
||||||
|
y = 0;
|
||||||
|
z = z_offset + scale * 20;
|
||||||
|
ctx.drawImage(leg_right_side, x + y, z - y, leg_right_side.width, leg_right_side.height);
|
||||||
|
|
||||||
|
x = x_offset + scale * 2;
|
||||||
|
y = scale * -arm_width;
|
||||||
|
z = z_offset + scale * 8;
|
||||||
|
ctx.drawImage(arm_right_side, x + y, z - y - 0.5, arm_right_side.width, arm_right_side.height + 1);
|
||||||
|
|
||||||
|
// front
|
||||||
|
z = z_offset + scale * 12;
|
||||||
|
y = 0;
|
||||||
|
ctx.setTransform(1, -skew_a, 0, skew_b, 0, skew_a);
|
||||||
|
ctx.drawImage(front, y + x, x + z - 0.5, front.width, front.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// head top
|
||||||
|
x = x_offset;
|
||||||
|
y = -0.5;
|
||||||
|
z = z_offset;
|
||||||
|
ctx.setTransform(1, -skew_a, 1, skew_a, 0, 0);
|
||||||
|
ctx.drawImage(head_top, y - z, x + z, head_top.width, head_top.height + 1);
|
||||||
|
|
||||||
|
// head front
|
||||||
|
x = x_offset + 8 * scale;
|
||||||
|
y = 0;
|
||||||
|
z = z_offset - 0.5;
|
||||||
|
ctx.setTransform(1, -skew_a, 0, skew_b, 0, skew_a);
|
||||||
|
ctx.drawImage(head_front, y + x, x + z, head_front.width, head_front.height);
|
||||||
|
|
||||||
|
// head right
|
||||||
|
x = x_offset;
|
||||||
|
y = 0;
|
||||||
|
z = z_offset;
|
||||||
|
ctx.setTransform(1, skew_a, 0, skew_b, 0, 0);
|
||||||
|
ctx.drawImage(head_right, x + y, z - y - 0.5, head_right.width, head_right.height + 1);
|
||||||
|
|
||||||
|
canvas.toBuffer(function(err, buf) {
|
||||||
|
if (err) {
|
||||||
|
logging.error(rid, "error creating buffer:", err);
|
||||||
|
}
|
||||||
callback(err, buf);
|
callback(err, buf);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
image.src = img;
|
skin.src = img;
|
||||||
};
|
};
|
||||||
|
|
||||||
// helper method to open a render from +renderpath+
|
// helper method to open a render from +renderpath+
|
||||||
// callback: error, image buffer
|
// callback: error, image buffer
|
||||||
exp.open_render = function(rid, renderpath, callback) {
|
exp.open_render = function(rid, renderpath, callback) {
|
||||||
fs.readFile(renderpath, function(err, buf) {
|
fs.readFile(renderpath, callback);
|
||||||
callback(err, buf);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = exp;
|
module.exports = exp;
|
||||||
@ -63,20 +63,16 @@ module.exports = function(request, response, result) {
|
|||||||
headers["X-Storage-Type"] = human_status[result.status];
|
headers["X-Storage-Type"] = human_status[result.status];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.body) {
|
// use crc32 as a hash function for Etag
|
||||||
// use Mojang's image hash if available
|
var etag = "\"" + crc(result.body || "") + "\"";
|
||||||
// use crc32 as a hash function otherwise
|
|
||||||
var etag = result.hash && result.hash.substr(0, 10) || crc(result.body);
|
|
||||||
headers.Etag = "\"" + etag + "\"";
|
|
||||||
|
|
||||||
// handle etag caching
|
// handle etag caching
|
||||||
var incoming_etag = request.headers["if-none-match"];
|
var incoming_etag = request.headers["if-none-match"];
|
||||||
if (incoming_etag && incoming_etag === headers.Etag) {
|
if (incoming_etag && incoming_etag === etag) {
|
||||||
response.writeHead(304, headers);
|
response.writeHead(304, headers);
|
||||||
response.end();
|
response.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (result.redirect) {
|
if (result.redirect) {
|
||||||
headers.Location = result.redirect;
|
headers.Location = result.redirect;
|
||||||
@ -87,12 +83,16 @@ module.exports = function(request, response, result) {
|
|||||||
|
|
||||||
if (result.status === -2) {
|
if (result.status === -2) {
|
||||||
response.writeHead(result.code || 422, headers);
|
response.writeHead(result.code || 422, headers);
|
||||||
response.end(result.body);
|
|
||||||
} else if (result.status === -1) {
|
} else if (result.status === -1) {
|
||||||
response.writeHead(500, headers);
|
response.writeHead(500, headers);
|
||||||
response.end(result.body);
|
|
||||||
} else {
|
} else {
|
||||||
response.writeHead(result.body ? 200 : 404, headers);
|
if (result.body) {
|
||||||
response.end(result.body);
|
headers.Etag = etag;
|
||||||
|
response.writeHead(200, headers);
|
||||||
|
} else {
|
||||||
|
response.writeHead(404, headers);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.end(result.body);
|
||||||
};
|
};
|
||||||
@ -7,7 +7,8 @@ var url = require("url");
|
|||||||
|
|
||||||
function handle_default(img_status, userId, size, def, req, err, callback) {
|
function handle_default(img_status, userId, size, def, req, err, callback) {
|
||||||
def = def || skins.default_skin(userId);
|
def = def || skins.default_skin(userId);
|
||||||
if (def !== "steve" && def !== "mhf_steve" && def !== "alex" && def !== "mhf_alex") {
|
var defname = def.toLowerCase();
|
||||||
|
if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") {
|
||||||
if (helpers.id_valid(def)) {
|
if (helpers.id_valid(def)) {
|
||||||
// clean up the old URL to match new image
|
// clean up the old URL to match new image
|
||||||
var parsed = req.url;
|
var parsed = req.url;
|
||||||
@ -29,7 +30,7 @@ function handle_default(img_status, userId, size, def, req, err, callback) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle steve and alex
|
// handle steve and alex
|
||||||
def = def.toLowerCase();
|
def = defname;
|
||||||
if (def.substr(0, 4) !== "mhf_") {
|
if (def.substr(0, 4) !== "mhf_") {
|
||||||
def = "mhf_" + def;
|
def = "mhf_" + def;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,8 @@ var fs = require("fs");
|
|||||||
// overlay is query param
|
// overlay is query param
|
||||||
function handle_default(rid, scale, overlay, body, img_status, userId, size, def, req, err, callback) {
|
function handle_default(rid, scale, overlay, body, img_status, userId, size, def, req, err, callback) {
|
||||||
def = def || skins.default_skin(userId);
|
def = def || skins.default_skin(userId);
|
||||||
if (def !== "steve" && def !== "mhf_steve" && def !== "alex" && def !== "mhf_alex") {
|
var defname = def.toLowerCase();
|
||||||
|
if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") {
|
||||||
if (helpers.id_valid(def)) {
|
if (helpers.id_valid(def)) {
|
||||||
// clean up the old URL to match new image
|
// clean up the old URL to match new image
|
||||||
var parsed = req.url;
|
var parsed = req.url;
|
||||||
@ -34,13 +35,13 @@ function handle_default(rid, scale, overlay, body, img_status, userId, size, def
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle steve and alex
|
// handle steve and alex
|
||||||
def = def.toLowerCase();
|
def = defname;
|
||||||
if (def.substr(0, 4) !== "mhf_") {
|
if (def.substr(0, 4) !== "mhf_") {
|
||||||
def = "mhf_" + def;
|
def = "mhf_" + def;
|
||||||
}
|
}
|
||||||
fs.readFile(path.join(__dirname, "..", "public", "images", def + "_skin.png"), function (fs_err, buf) {
|
fs.readFile(path.join(__dirname, "..", "public", "images", def + "_skin.png"), function(fs_err, buf) {
|
||||||
// we render the default skins, but not custom images
|
// we render the default skins, but not custom images
|
||||||
renders.draw_model(rid, buf, scale, overlay, body, function(render_err, def_img) {
|
renders.draw_model(rid, buf, scale, overlay, body, def === "mhf_alex", function(render_err, def_img) {
|
||||||
callback({
|
callback({
|
||||||
status: img_status,
|
status: img_status,
|
||||||
body: def_img,
|
body: def_img,
|
||||||
@ -55,7 +56,7 @@ function handle_default(rid, scale, overlay, body, img_status, userId, size, def
|
|||||||
|
|
||||||
// GET render request
|
// GET render request
|
||||||
module.exports = function(req, callback) {
|
module.exports = function(req, callback) {
|
||||||
var raw_type = (req.url.path_list[1] || "");
|
var raw_type = req.url.path_list[1] || "";
|
||||||
var rid = req.id;
|
var rid = req.id;
|
||||||
var body = raw_type === "body";
|
var body = raw_type === "body";
|
||||||
var userId = (req.url.path_list[2] || "").split(".")[0];
|
var userId = (req.url.path_list[2] || "").split(".")[0];
|
||||||
|
|||||||
@ -8,7 +8,8 @@ var url = require("url");
|
|||||||
|
|
||||||
function handle_default(img_status, userId, def, req, err, callback) {
|
function handle_default(img_status, userId, def, req, err, callback) {
|
||||||
def = def || skins.default_skin(userId);
|
def = def || skins.default_skin(userId);
|
||||||
if (def !== "steve" && def !== "mhf_steve" && def !== "alex" && def !== "mhf_alex") {
|
var defname = def.toLowerCase();
|
||||||
|
if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") {
|
||||||
if (helpers.id_valid(def)) {
|
if (helpers.id_valid(def)) {
|
||||||
// clean up the old URL to match new image
|
// clean up the old URL to match new image
|
||||||
var parsed = req.url;
|
var parsed = req.url;
|
||||||
@ -30,7 +31,7 @@ function handle_default(img_status, userId, def, req, err, callback) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle steve and alex
|
// handle steve and alex
|
||||||
def = def.toLowerCase();
|
def = defname;
|
||||||
if (def.substr(0, 4) !== "mhf_") {
|
if (def.substr(0, 4) !== "mhf_") {
|
||||||
def = "mhf_" + def;
|
def = "mhf_" + def;
|
||||||
}
|
}
|
||||||
@ -83,7 +84,7 @@ module.exports = function(req, callback) {
|
|||||||
userId = userId.replace(/-/g, "");
|
userId = userId.replace(/-/g, "");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
helpers.get_skin(rid, userId, function(err, hash, status, image) {
|
helpers.get_skin(rid, userId, function(err, hash, status, image, slim) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.code === "ENOENT") {
|
if (err.code === "ENOENT") {
|
||||||
// no such file
|
// no such file
|
||||||
|
|||||||
@ -104,8 +104,12 @@ exp.resize_img = function(inname, size, callback) {
|
|||||||
// returns "mhf_alex" or "mhf_steve" calculated by the +uuid+
|
// returns "mhf_alex" or "mhf_steve" calculated by the +uuid+
|
||||||
exp.default_skin = function(uuid) {
|
exp.default_skin = function(uuid) {
|
||||||
if (uuid.length <= 16) {
|
if (uuid.length <= 16) {
|
||||||
|
if (uuid.toLowerCase() === "mhf_alex") {
|
||||||
|
return uuid;
|
||||||
|
} else {
|
||||||
// we can't get the skin type by username
|
// we can't get the skin type by username
|
||||||
return "mhf_steve";
|
return "mhf_steve";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// great thanks to Minecrell for research into Minecraft and Java's UUID hashing!
|
// great thanks to Minecrell for research into Minecraft and Java's UUID hashing!
|
||||||
// https://git.io/xJpV
|
// https://git.io/xJpV
|
||||||
|
|||||||
@ -34,7 +34,7 @@
|
|||||||
"iojs": "2.0.x"
|
"iojs": "2.0.x"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"canvas": "^1.2.9",
|
"canvas": "^1.3.4",
|
||||||
"crc": "~3.3.0",
|
"crc": "~3.3.0",
|
||||||
"ejs": "^2.3.4",
|
"ejs": "^2.3.4",
|
||||||
"lwip": "~0.0.7",
|
"lwip": "~0.0.7",
|
||||||
|
|||||||
326
test/test.js
326
test/test.js
@ -17,7 +17,7 @@ var fs = require("fs");
|
|||||||
config.server.http_timeout *= 3;
|
config.server.http_timeout *= 3;
|
||||||
|
|
||||||
// no spam
|
// no spam
|
||||||
if (process.env.VERBOSE_TEST !== "true") {
|
if (process.env.VERBOSE_TEST !== "true" && process.env.TRAVIS !== "true") {
|
||||||
logging.log = logging.debug = logging.warn = logging.error = function() {};
|
logging.log = logging.debug = logging.warn = logging.error = function() {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,10 @@ var alex_ids = [
|
|||||||
"fffffff1" + "fffffff1" + "fffffff1" + "fffffff0",
|
"fffffff1" + "fffffff1" + "fffffff1" + "fffffff0",
|
||||||
];
|
];
|
||||||
|
|
||||||
var rid = "TestReqID: ";
|
// generates a 12 character random string
|
||||||
|
function rid() {
|
||||||
|
return Math.random().toString(36).substring(2, 14);
|
||||||
|
}
|
||||||
|
|
||||||
function getRandomInt(min, max) {
|
function getRandomInt(min, max) {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
@ -120,14 +123,14 @@ describe("Crafatar", function() {
|
|||||||
});
|
});
|
||||||
it("should not exist (uuid)", function(done) {
|
it("should not exist (uuid)", function(done) {
|
||||||
var number = getRandomInt(0, 9).toString();
|
var number = getRandomInt(0, 9).toString();
|
||||||
networking.get_profile(rid, Array(33).join(number), function(err, profile) {
|
networking.get_profile(rid(), Array(33).join(number), function(err, profile) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(profile, null);
|
assert.strictEqual(profile, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("should not exist (username)", function(done) {
|
it("should not exist (username)", function(done) {
|
||||||
networking.get_username_url(rid, "Steve", 0, function(err, profile) {
|
networking.get_username_url(rid(), "Steve", 0, function(err, profile) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -136,10 +139,10 @@ describe("Crafatar", function() {
|
|||||||
describe("Avatar", function() {
|
describe("Avatar", function() {
|
||||||
it("uuid's account should exist, but skin should not", function(done) {
|
it("uuid's account should exist, but skin should not", function(done) {
|
||||||
// profile "Alex" - hoping it'll never have a skin
|
// profile "Alex" - hoping it'll never have a skin
|
||||||
networking.get_profile(rid, "ec561538f3fd461daff5086b22154bce", function(err, profile) {
|
networking.get_profile(rid(), "ec561538f3fd461daff5086b22154bce", function(err, profile) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.notStrictEqual(profile, null);
|
assert.notStrictEqual(profile, null);
|
||||||
networking.get_uuid_url(profile, 1, function(url) {
|
networking.get_uuid_info(profile, "CAPE", function(url) {
|
||||||
assert.strictEqual(url, null);
|
assert.strictEqual(url, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -172,7 +175,7 @@ describe("Crafatar", function() {
|
|||||||
it("should time out on uuid info download", function(done) {
|
it("should time out on uuid info download", function(done) {
|
||||||
var original_timeout = config.server.http_timeout;
|
var original_timeout = config.server.http_timeout;
|
||||||
config.server.http_timeout = 1;
|
config.server.http_timeout = 1;
|
||||||
networking.get_profile(rid, "069a79f444e94726a5befca90e38aaf5", function(err, profile) {
|
networking.get_profile(rid(), "069a79f444e94726a5befca90e38aaf5", function(err, profile) {
|
||||||
assert.strictEqual(err.code, "ETIMEDOUT");
|
assert.strictEqual(err.code, "ETIMEDOUT");
|
||||||
config.server.http_timeout = original_timeout;
|
config.server.http_timeout = original_timeout;
|
||||||
done();
|
done();
|
||||||
@ -181,7 +184,7 @@ describe("Crafatar", function() {
|
|||||||
it("should time out on username info download", function(done) {
|
it("should time out on username info download", function(done) {
|
||||||
var original_timeout = config.server.http_timeout;
|
var original_timeout = config.server.http_timeout;
|
||||||
config.server.http_timeout = 1;
|
config.server.http_timeout = 1;
|
||||||
networking.get_username_url(rid, "jomo", 0, function(err, url) {
|
networking.get_username_url(rid(), "jomo", 0, function(err, url) {
|
||||||
assert.strictEqual(err.code, "ETIMEDOUT");
|
assert.strictEqual(err.code, "ETIMEDOUT");
|
||||||
config.server.http_timeout = original_timeout;
|
config.server.http_timeout = original_timeout;
|
||||||
done();
|
done();
|
||||||
@ -190,7 +193,7 @@ describe("Crafatar", function() {
|
|||||||
it("should time out on skin download", function(done) {
|
it("should time out on skin download", function(done) {
|
||||||
var original_timeout = config.http_timeout;
|
var original_timeout = config.http_timeout;
|
||||||
config.server.http_timeout = 1;
|
config.server.http_timeout = 1;
|
||||||
networking.get_from(rid, "http://textures.minecraft.net/texture/477be35554684c28bdeee4cf11c591d3c88afb77e0b98da893fd7bc318c65184", function(body, res, error) {
|
networking.get_from(rid(), "http://textures.minecraft.net/texture/477be35554684c28bdeee4cf11c591d3c88afb77e0b98da893fd7bc318c65184", function(body, res, error) {
|
||||||
assert.strictEqual(error.code, "ETIMEDOUT");
|
assert.strictEqual(error.code, "ETIMEDOUT");
|
||||||
config.server.http_timeout = original_timeout;
|
config.server.http_timeout = original_timeout;
|
||||||
done();
|
done();
|
||||||
@ -198,14 +201,14 @@ describe("Crafatar", function() {
|
|||||||
});
|
});
|
||||||
it("should not find the skin", function(done) {
|
it("should not find the skin", function(done) {
|
||||||
assert.doesNotThrow(function() {
|
assert.doesNotThrow(function() {
|
||||||
networking.get_from(rid, "http://textures.minecraft.net/texture/this-does-not-exist", function(img, response, err) {
|
networking.get_from(rid(), "http://textures.minecraft.net/texture/this-does-not-exist", function(img, response, err) {
|
||||||
assert.strictEqual(err, null); // no error here, but it shouldn't throw exceptions
|
assert.strictEqual(err, null); // no error here, but it shouldn't throw exceptions
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("should not find the file", function(done) {
|
it("should not find the file", function(done) {
|
||||||
skins.open_skin(rid, "non/existent/path", function(err, img) {
|
skins.open_skin(rid(), "non/existent/path", function(err, img) {
|
||||||
assert(err);
|
assert(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -233,7 +236,6 @@ describe("Crafatar", function() {
|
|||||||
assert.ifError(error);
|
assert.ifError(error);
|
||||||
assert.ifError(body);
|
assert.ifError(body);
|
||||||
assert.equal(res.statusCode, 304);
|
assert.equal(res.statusCode, 304);
|
||||||
assert(res.headers.etag);
|
|
||||||
assert_headers(res);
|
assert_headers(res);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
@ -338,440 +340,396 @@ describe("Crafatar", function() {
|
|||||||
var server_tests = {
|
var server_tests = {
|
||||||
"avatar with existing username": {
|
"avatar with existing username": {
|
||||||
url: "http://localhost:3000/avatars/jeb_?size=16",
|
url: "http://localhost:3000/avatars/jeb_?size=16",
|
||||||
etag: '"a846b82963"',
|
crc32: [1623808067]
|
||||||
crc32: 1623808067
|
|
||||||
},
|
},
|
||||||
"avatar with non-existent username": {
|
"avatar with non-existent username": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16",
|
url: "http://localhost:3000/avatars/0?size=16",
|
||||||
etag: '"mhf_steve"',
|
|
||||||
crc32: [2416827277, 1243826040]
|
crc32: [2416827277, 1243826040]
|
||||||
},
|
},
|
||||||
"avatar with non-existent username defaulting to alex": {
|
"avatar with non-existent username defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&default=mhf_alex",
|
url: "http://localhost:3000/avatars/0?size=16&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
|
||||||
crc32: [862751081, 809395677]
|
crc32: [862751081, 809395677]
|
||||||
},
|
},
|
||||||
"avatar with non-existent username defaulting to username": {
|
"avatar with non-existent username defaulting to username": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&default=jeb_",
|
url: "http://localhost:3000/avatars/0?size=16&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/jeb_?size=16"
|
redirect: "/avatars/jeb_?size=16"
|
||||||
},
|
},
|
||||||
"avatar with non-existent username defaulting to uuid": {
|
"avatar with non-existent username defaulting to uuid": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/avatars/0?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16"
|
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16"
|
||||||
},
|
},
|
||||||
"avatar with non-existent username defaulting to url": {
|
"avatar with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/avatars/0?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"overlay avatar with existing username": {
|
"overlay avatar with existing username": {
|
||||||
url: "http://localhost:3000/avatars/jeb_?size=16&overlay",
|
url: "http://localhost:3000/avatars/jeb_?size=16&overlay",
|
||||||
etag: '"a846b82963"',
|
crc32: [646871998]
|
||||||
crc32: 646871998
|
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent username": {
|
"overlay avatar with non-existent username": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&overlay",
|
url: "http://localhost:3000/avatars/0?size=16&overlay",
|
||||||
etag: '"mhf_steve"',
|
|
||||||
crc32: [2416827277, 1243826040]
|
crc32: [2416827277, 1243826040]
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent username defaulting to alex": {
|
"overlay avatar with non-existent username defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&overlay&default=mhf_alex",
|
url: "http://localhost:3000/avatars/0?size=16&overlay&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
|
||||||
crc32: [862751081, 809395677]
|
crc32: [862751081, 809395677]
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent username defaulting to username": {
|
"overlay avatar with non-existent username defaulting to username": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&overlay&default=jeb_",
|
url: "http://localhost:3000/avatars/0?size=16&overlay&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/jeb_?size=16&overlay="
|
redirect: "/avatars/jeb_?size=16&overlay="
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent username defaulting to uuid": {
|
"overlay avatar with non-existent username defaulting to uuid": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/avatars/0?size=16&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16&overlay="
|
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16&overlay="
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent username defaulting to url": {
|
"overlay avatar with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/avatars/0?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/avatars/0?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"avatar with existing uuid": {
|
"avatar with existing uuid": {
|
||||||
url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
|
url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
|
||||||
etag: '"a846b82963"',
|
crc32: [1623808067]
|
||||||
crc32: 1623808067
|
|
||||||
},
|
},
|
||||||
"avatar with non-existent uuid": {
|
"avatar with non-existent uuid": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16",
|
||||||
etag: '"mhf_steve"',
|
|
||||||
crc32: [2416827277, 1243826040]
|
crc32: [2416827277, 1243826040]
|
||||||
},
|
},
|
||||||
"avatar with non-existent uuid defaulting to alex": {
|
"avatar with non-existent uuid defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=mhf_alex",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
|
||||||
crc32: [862751081, 809395677]
|
crc32: [862751081, 809395677]
|
||||||
},
|
},
|
||||||
"avatar with non-existent uuid defaulting to username": {
|
"avatar with non-existent uuid defaulting to username": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/jeb_?size=16"
|
redirect: "/avatars/jeb_?size=16"
|
||||||
},
|
},
|
||||||
"avatar with non-existent uuid defaulting to uuid": {
|
"avatar with non-existent uuid defaulting to uuid": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16"
|
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16"
|
||||||
},
|
},
|
||||||
"avatar with non-existent uuid defaulting to url": {
|
"avatar with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"overlay avatar with existing uuid": {
|
"overlay avatar with existing uuid": {
|
||||||
url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16&overlay",
|
url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16&overlay",
|
||||||
etag: '"a846b82963"',
|
crc32: [646871998]
|
||||||
crc32: 646871998
|
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent uuid": {
|
"overlay avatar with non-existent uuid": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay",
|
||||||
etag: '"mhf_steve"',
|
|
||||||
crc32: [2416827277, 1243826040]
|
crc32: [2416827277, 1243826040]
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent uuid defaulting to alex": {
|
"overlay avatar with non-existent uuid defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=mhf_alex",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
|
||||||
crc32: [862751081, 809395677]
|
crc32: [862751081, 809395677]
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent uuid defaulting to username": {
|
"overlay avatar with non-existent uuid defaulting to username": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/jeb_?size=16"
|
redirect: "/avatars/jeb_?size=16"
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent uuid defaulting to uuid": {
|
"overlay avatar with non-existent uuid defaulting to uuid": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16"
|
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16"
|
||||||
},
|
},
|
||||||
"overlay avatar with non-existent uuid defaulting to url": {
|
"overlay avatar with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"cape with existing username": {
|
"cape with existing username": {
|
||||||
url: "http://localhost:3000/capes/jeb_",
|
url: "http://localhost:3000/capes/jeb_",
|
||||||
etag: '"3f688e0e69"',
|
|
||||||
crc32: [989800403, 1901140141]
|
crc32: [989800403, 1901140141]
|
||||||
},
|
},
|
||||||
"cape with non-existent username": {
|
"cape with non-existent username": {
|
||||||
url: "http://localhost:3000/capes/0",
|
url: "http://localhost:3000/capes/0",
|
||||||
crc32: 0
|
crc32: [0]
|
||||||
},
|
},
|
||||||
"cape with non-existent username defaulting to url": {
|
"cape with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/capes/0?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/capes/0?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"cape with existing uuid": {
|
"cape with existing uuid": {
|
||||||
url: "http://localhost:3000/capes/853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/capes/853c80ef3c3749fdaa49938b674adae6",
|
||||||
etag: '"3f688e0e69"',
|
|
||||||
crc32: [989800403, 1901140141]
|
crc32: [989800403, 1901140141]
|
||||||
},
|
},
|
||||||
"cape with non-existent uuid": {
|
"cape with non-existent uuid": {
|
||||||
url: "http://localhost:3000/capes/00000000000000000000000000000000",
|
url: "http://localhost:3000/capes/00000000000000000000000000000000",
|
||||||
crc32: 0
|
crc32: [0]
|
||||||
},
|
},
|
||||||
"cape with non-existent uuid defaulting to url": {
|
"cape with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/capes/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/capes/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"skin with existing username": {
|
"skin with existing username": {
|
||||||
url: "http://localhost:3000/skins/jeb_",
|
url: "http://localhost:3000/skins/jeb_",
|
||||||
etag: '"a846b82963"',
|
crc32: [26500336]
|
||||||
crc32: 26500336
|
|
||||||
},
|
},
|
||||||
"skin with non-existent username": {
|
"skin with non-existent username": {
|
||||||
url: "http://localhost:3000/skins/0",
|
url: "http://localhost:3000/skins/0",
|
||||||
etag: '"mhf_steve"',
|
crc32: [981937087]
|
||||||
crc32: 981937087
|
|
||||||
},
|
},
|
||||||
"skin with non-existent username defaulting to alex": {
|
"skin with non-existent username defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/skins/0?default=mhf_alex",
|
url: "http://localhost:3000/skins/0?default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [2298915739]
|
||||||
crc32: 2298915739
|
|
||||||
},
|
},
|
||||||
"skin with non-existent username defaulting to username": {
|
"skin with non-existent username defaulting to username": {
|
||||||
url: "http://localhost:3000/skins/0?size=16&default=jeb_",
|
url: "http://localhost:3000/skins/0?size=16&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/skins/jeb_?size=16"
|
redirect: "/skins/jeb_?size=16"
|
||||||
},
|
},
|
||||||
"skin with non-existent username defaulting to uuid": {
|
"skin with non-existent username defaulting to uuid": {
|
||||||
url: "http://localhost:3000/skins/0?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/skins/0?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/skins/853c80ef3c3749fdaa49938b674adae6?size=16"
|
redirect: "/skins/853c80ef3c3749fdaa49938b674adae6?size=16"
|
||||||
},
|
},
|
||||||
"skin with non-existent username defaulting to url": {
|
"skin with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/skins/0?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/skins/0?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"skin with existing uuid": {
|
"skin with existing uuid": {
|
||||||
url: "http://localhost:3000/skins/853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/skins/853c80ef3c3749fdaa49938b674adae6",
|
||||||
etag: '"a846b82963"',
|
crc32: [26500336]
|
||||||
crc32: 26500336
|
|
||||||
},
|
},
|
||||||
"skin with non-existent uuid": {
|
"skin with non-existent uuid": {
|
||||||
url: "http://localhost:3000/skins/00000000000000000000000000000000",
|
url: "http://localhost:3000/skins/00000000000000000000000000000000",
|
||||||
etag: '"mhf_steve"',
|
crc32: [981937087]
|
||||||
crc32: 981937087
|
|
||||||
},
|
},
|
||||||
"skin with non-existent uuid defaulting to alex": {
|
"skin with non-existent uuid defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/skins/00000000000000000000000000000000?default=mhf_alex",
|
url: "http://localhost:3000/skins/00000000000000000000000000000000?default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [2298915739]
|
||||||
crc32: 2298915739
|
|
||||||
},
|
},
|
||||||
"skin with non-existent uuid defaulting to username": {
|
"skin with non-existent uuid defaulting to username": {
|
||||||
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=jeb_",
|
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/skins/jeb_?size=16"
|
redirect: "/skins/jeb_?size=16"
|
||||||
},
|
},
|
||||||
"skin with non-existent uuid defaulting to uuid": {
|
"skin with non-existent uuid defaulting to uuid": {
|
||||||
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/skins/853c80ef3c3749fdaa49938b674adae6?size=16"
|
redirect: "/skins/853c80ef3c3749fdaa49938b674adae6?size=16"
|
||||||
},
|
},
|
||||||
"skin with non-existent uuid defaulting to url": {
|
"skin with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/skins/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/skins/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"head render with existing username": {
|
"head render with existing username": {
|
||||||
url: "http://localhost:3000/renders/head/jeb_?scale=2",
|
url: "http://localhost:3000/renders/head/jeb_?scale=2",
|
||||||
etag: '"a846b82963"',
|
crc32: [3487896679, 3001090792]
|
||||||
crc32: [1743362302, 208074514, 2506366593]
|
|
||||||
},
|
},
|
||||||
"head render with non-existent username": {
|
"head render with non-existent username": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2",
|
url: "http://localhost:3000/renders/head/0?scale=2",
|
||||||
etag: '"mhf_steve"',
|
crc32: [3257141069, 214248305]
|
||||||
crc32: [897270661, 1026982335, 1726107733]
|
|
||||||
},
|
},
|
||||||
"head render with non-existent username defaulting to alex": {
|
"head render with non-existent username defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2&default=mhf_alex",
|
url: "http://localhost:3000/renders/head/0?scale=2&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [263450586, 3116770561]
|
||||||
crc32: [2357619670, 3172866498, 2214491831]
|
|
||||||
},
|
},
|
||||||
"head render with non-existent username defaulting to username": {
|
"head render with non-existent username defaulting to username": {
|
||||||
url: "http://localhost:3000/avatars/0?scale=2&default=jeb_",
|
url: "http://localhost:3000/avatars/0?scale=2&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/jeb_?scale=2"
|
redirect: "/avatars/jeb_?scale=2"
|
||||||
},
|
},
|
||||||
"head render with non-existent username defaulting to uuid": {
|
"head render with non-existent username defaulting to uuid": {
|
||||||
url: "http://localhost:3000/avatars/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/avatars/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
||||||
},
|
},
|
||||||
"head render with non-existent username defaulting to url": {
|
"head render with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/head/0?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"overlay head render with existing username": {
|
"overlay head render with existing username": {
|
||||||
url: "http://localhost:3000/renders/head/jeb_?scale=2&overlay",
|
url: "http://localhost:3000/renders/head/jeb_?scale=2&overlay",
|
||||||
etag: '"a846b82963"',
|
crc32: [762377383, 1726474987]
|
||||||
crc32: [4178514320, 2340078566, 3980890516]
|
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent username": {
|
"overlay head render with non-existent username": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2&overlay",
|
url: "http://localhost:3000/renders/head/0?scale=2&overlay",
|
||||||
etag: '"mhf_steve"',
|
crc32: [3257141069, 214248305]
|
||||||
crc32: [507497693, 3868868707, 7372195]
|
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent username defaulting to alex": {
|
"overlay head render with non-existent username defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=mhf_alex",
|
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [263450586, 3116770561]
|
||||||
crc32: [891113664, 1785326216, 622500655]
|
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent username defaulting to username": {
|
"overlay head render with non-existent username defaulting to username": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=jeb_",
|
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/head/jeb_?scale=2&overlay="
|
redirect: "/renders/head/jeb_?scale=2&overlay="
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent username defaulting to uuid": {
|
"overlay head render with non-existent username defaulting to uuid": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay="
|
redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay="
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent username defaulting to url": {
|
"overlay head render with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"head render with existing uuid": {
|
"head render with existing uuid": {
|
||||||
url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2",
|
url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2",
|
||||||
etag: '"a846b82963"',
|
crc32: [3487896679, 3001090792]
|
||||||
crc32: [1743362302, 208074514, 2506366593]
|
|
||||||
},
|
},
|
||||||
"head render with non-existent uuid": {
|
"head render with non-existent uuid": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2",
|
||||||
etag: '"mhf_steve"',
|
crc32: [3257141069, 214248305]
|
||||||
crc32: [897270661, 1026982335, 1726107733]
|
|
||||||
},
|
},
|
||||||
"head render with non-existent uuid defaulting to alex": {
|
"head render with non-existent uuid defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=mhf_alex",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [263450586, 3116770561]
|
||||||
crc32: [2357619670, 3172866498, 2214491831]
|
|
||||||
},
|
},
|
||||||
"head render with non-existent uuid defaulting to username": {
|
"head render with non-existent uuid defaulting to username": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=jeb_",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/head/jeb_?scale=2"
|
redirect: "/renders/head/jeb_?scale=2"
|
||||||
},
|
},
|
||||||
"head render with non-existent uuid defaulting to uuid": {
|
"head render with non-existent uuid defaulting to uuid": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
||||||
},
|
},
|
||||||
"head render with non-existent uuid defaulting to url": {
|
"head render with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"overlay head render with existing uuid": {
|
"overlay head render with existing uuid": {
|
||||||
url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay",
|
url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay",
|
||||||
etag: '"a846b82963"',
|
crc32: [762377383, 1726474987]
|
||||||
crc32: [4178514320, 2340078566, 3980890516]
|
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent uuid": {
|
"overlay head render with non-existent uuid": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay",
|
||||||
etag: '"mhf_steve"',
|
crc32: [3257141069, 214248305]
|
||||||
crc32: [507497693, 3868868707, 7372195]
|
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent uuid defaulting to alex": {
|
"overlay head render with non-existent uuid defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [263450586, 3116770561]
|
||||||
crc32: [891113664, 1785326216, 622500655]
|
|
||||||
},
|
},
|
||||||
"overlay head with non-existent uuid defaulting to username": {
|
"overlay head with non-existent uuid defaulting to username": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=jeb_",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/head/jeb_?scale=2&overlay="
|
redirect: "/renders/head/jeb_?scale=2&overlay="
|
||||||
},
|
},
|
||||||
"overlay head with non-existent uuid defaulting to uuid": {
|
"overlay head with non-existent uuid defaulting to uuid": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay="
|
redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay="
|
||||||
},
|
},
|
||||||
"overlay head render with non-existent uuid defaulting to url": {
|
"overlay head render with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"body render with existing username": {
|
"body render with existing username": {
|
||||||
url: "http://localhost:3000/renders/body/jeb_?scale=2",
|
url: "http://localhost:3000/renders/body/jeb_?scale=2",
|
||||||
etag: '"a846b82963"',
|
crc32: [3127075871, 2595192206]
|
||||||
crc32: [1023392610, 4127764743, 3884408742]
|
|
||||||
},
|
},
|
||||||
"body render with non-existent username": {
|
"body render with non-existent username": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2",
|
url: "http://localhost:3000/renders/body/0?scale=2",
|
||||||
etag: '"mhf_steve"',
|
crc32: [1046655221, 1620063267]
|
||||||
crc32: [3559591930, 3663447404, 1521463481]
|
|
||||||
},
|
},
|
||||||
"body render with non-existent username defaulting to alex": {
|
"body render with non-existent username defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&default=mhf_alex",
|
url: "http://localhost:3000/renders/body/0?scale=2&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [549240598, 3952648540]
|
||||||
crc32: [470529151, 1823026927, 2079926997]
|
|
||||||
},
|
},
|
||||||
"body render with non-existent username defaulting to username": {
|
"body render with non-existent username defaulting to username": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&default=jeb_",
|
url: "http://localhost:3000/renders/body/0?scale=2&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/body/jeb_?scale=2"
|
redirect: "/renders/body/jeb_?scale=2"
|
||||||
},
|
},
|
||||||
"body render with non-existent username defaulting to uuid": {
|
"body render with non-existent username defaulting to uuid": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/renders/body/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
||||||
},
|
},
|
||||||
"body render with non-existent username defaulting to url": {
|
"body render with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/body/0?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"overlay body render with existing username": {
|
"overlay body render with existing username": {
|
||||||
url: "http://localhost:3000/renders/body/jeb_?scale=2&overlay",
|
url: "http://localhost:3000/renders/body/jeb_?scale=2&overlay",
|
||||||
etag: '"a846b82963"',
|
crc32: [699892097, 2732138694]
|
||||||
crc32: [3476579592, 97705180, 3086172613]
|
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent username": {
|
"overlay body render with non-existent username": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&overlay",
|
url: "http://localhost:3000/renders/body/0?scale=2&overlay",
|
||||||
etag: '"mhf_steve"',
|
crc32: [1046655221, 1620063267]
|
||||||
crc32: [3992841063, 1025743887, 1906839968]
|
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent username defaulting to alex": {
|
"overlay body render with non-existent username defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=mhf_alex",
|
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [549240598, 3952648540]
|
||||||
crc32: [3317518715, 3621585514, 294661951]
|
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent username defaulting to username": {
|
"overlay body render with non-existent username defaulting to username": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=jeb_",
|
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/body/jeb_?scale=2&overlay="
|
redirect: "/renders/body/jeb_?scale=2&overlay="
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent username defaulting to uuid": {
|
"overlay body render with non-existent username defaulting to uuid": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay="
|
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay="
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent username defaulting to url": {
|
"overlay body render with non-existent username defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"body render with existing uuid": {
|
"body render with existing uuid": {
|
||||||
url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
|
url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
|
||||||
etag: '"a846b82963"',
|
crc32: [3127075871, 2595192206]
|
||||||
crc32: [1023392610, 4127764743, 3884408742]
|
|
||||||
},
|
},
|
||||||
"body render with non-existent uuid": {
|
"body render with non-existent uuid": {
|
||||||
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2",
|
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2",
|
||||||
etag: '"mhf_steve"',
|
crc32: [1046655221, 1620063267]
|
||||||
crc32: [3559591930, 3663447404, 1521463481]
|
|
||||||
},
|
},
|
||||||
"body render with non-existent uuid defaulting to alex": {
|
"body render with non-existent uuid defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=mhf_alex",
|
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [549240598, 3952648540]
|
||||||
crc32: [470529151, 1823026927, 2079926997]
|
|
||||||
},
|
},
|
||||||
"body render with non-existent uuid defaulting to username": {
|
"body render with non-existent uuid defaulting to username": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&default=jeb_",
|
url: "http://localhost:3000/renders/body/0?scale=2&default=jeb_",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/body/jeb_?scale=2"
|
redirect: "/renders/body/jeb_?scale=2"
|
||||||
},
|
},
|
||||||
"body render with non-existent uuid defaulting to uuid": {
|
"body render with non-existent uuid defaulting to uuid": {
|
||||||
url: "http://localhost:3000/renders/body/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
url: "http://localhost:3000/renders/body/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2"
|
||||||
},
|
},
|
||||||
"body render with non-existent uuid defaulting to url": {
|
"body render with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
"overlay body render with existing uuid": {
|
"overlay body render with existing uuid": {
|
||||||
url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay",
|
url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay",
|
||||||
etag: '"a846b82963"',
|
crc32: [699892097, 2732138694]
|
||||||
crc32: [3476579592, 97705180, 3086172613]
|
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent uuid": {
|
"overlay body render with non-existent uuid": {
|
||||||
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay",
|
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay",
|
||||||
etag: '"mhf_steve"',
|
crc32: [1046655221, 1620063267]
|
||||||
crc32: [3992841063, 1025743887, 1906839968]
|
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent uuid defaulting to alex": {
|
"overlay body render with non-existent uuid defaulting to mhf_alex": {
|
||||||
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex",
|
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex",
|
||||||
etag: '"mhf_alex"',
|
crc32: [549240598, 3952648540]
|
||||||
crc32: [3317518715, 3621585514, 294661951]
|
|
||||||
},
|
},
|
||||||
"overlay body render with non-existent uuid defaulting to url": {
|
"overlay body render with non-existent uuid defaulting to url": {
|
||||||
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
|
||||||
crc32: 0,
|
crc32: [0],
|
||||||
redirect: "http://example.com/CaseSensitive"
|
redirect: "http://example.com/CaseSensitive"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -784,32 +742,30 @@ describe("Crafatar", function() {
|
|||||||
assert.ifError(error);
|
assert.ifError(error);
|
||||||
assert_headers(res);
|
assert_headers(res);
|
||||||
assert(res.headers["x-storage-type"]);
|
assert(res.headers["x-storage-type"]);
|
||||||
assert.strictEqual(res.headers.etag, location.etag);
|
var hash = crc(body);
|
||||||
var matches = false;
|
var matches = false;
|
||||||
if (location.crc32 instanceof Array) {
|
for (var c = 0; c < location.crc32.length; c++) {
|
||||||
for (var i = 0; i < location.crc32.length; i++) {
|
if (location.crc32[c] === hash) {
|
||||||
if (location.crc32[i] === crc(body)) {
|
|
||||||
matches = true;
|
matches = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
matches = location.crc32 === crc(body);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
assert.ok(matches);
|
assert(matches);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
throw new Error(crc(body) + " != " + location.crc32 + " | " + body.toString("base64"));
|
throw new Error(hash + " != " + location.crc32 + " | " + body.toString("base64"));
|
||||||
}
|
}
|
||||||
assert.strictEqual(res.headers.location, location.redirect);
|
assert.strictEqual(res.headers.location, location.redirect);
|
||||||
if (location.etag === undefined) {
|
if (location.crc32[0] === 0) {
|
||||||
assert.strictEqual(res.statusCode, location.redirect ? 307 : 404);
|
assert.strictEqual(res.statusCode, location.redirect ? 307 : 404);
|
||||||
|
assert.ifError(res.headers.etag); // etag must not be present on non-200
|
||||||
assert.strictEqual(res.headers["content-type"], "text/plain");
|
assert.strictEqual(res.headers["content-type"], "text/plain");
|
||||||
done();
|
done();
|
||||||
} else {
|
} else {
|
||||||
assert(res.headers.etag);
|
|
||||||
assert.strictEqual(res.headers["content-type"], "image/png");
|
assert.strictEqual(res.headers["content-type"], "image/png");
|
||||||
assert.strictEqual(res.statusCode, 200);
|
assert.strictEqual(res.statusCode, 200);
|
||||||
|
assert(res.headers.etag);
|
||||||
|
assert.strictEqual(res.headers.etag, '"' + hash + '"');
|
||||||
assert_cache(location.url, res.headers.etag, function() {
|
assert_cache(location.url, res.headers.etag, function() {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -819,6 +775,22 @@ describe("Crafatar", function() {
|
|||||||
}(loc));
|
}(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it("should update the username skin type on uuid request", function(done) {
|
||||||
|
/*eslint-disable handle-callback-err */
|
||||||
|
request.get("http://localhost:3000/renders/body/mhf_alex", function(error, res, body) {
|
||||||
|
cache.get_details("mhf_alex", function(err, details) {
|
||||||
|
assert.strictEqual(details.slim, false);
|
||||||
|
request.get("http://localhost:3000/renders/body/6ab4317889fd490597f60f67d9d76fd9", function(uerror, ures, ubody) {
|
||||||
|
cache.get_details("mhf_alex", function(cerr, cdetails) {
|
||||||
|
/*eslint-enable handle-callback-err */
|
||||||
|
assert.strictEqual(cdetails.slim, true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should return a 422 (invalid size)", function(done) {
|
it("should return a 422 (invalid size)", function(done) {
|
||||||
var size = config.avatars.max_size + 1;
|
var size = config.avatars.max_size + 1;
|
||||||
request.get("http://localhost:3000/avatars/Jake_0?size=" + size, function(error, res, body) {
|
request.get("http://localhost:3000/avatars/Jake_0?size=" + size, function(error, res, body) {
|
||||||
@ -878,13 +850,13 @@ describe("Crafatar", function() {
|
|||||||
// we have to make sure that we test both a 32x64 and 64x64 skin
|
// we have to make sure that we test both a 32x64 and 64x64 skin
|
||||||
describe("Networking: Render", function() {
|
describe("Networking: Render", function() {
|
||||||
it("should not fail (username, 32x64 skin)", function(done) {
|
it("should not fail (username, 32x64 skin)", function(done) {
|
||||||
helpers.get_render(rid, "md_5", 6, true, true, function(err, hash, img) {
|
helpers.get_render(rid(), "md_5", 6, true, true, function(err, hash, img) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("should not fail (username, 64x64 skin)", function(done) {
|
it("should not fail (username, 64x64 skin)", function(done) {
|
||||||
helpers.get_render(rid, "Jake_0", 6, true, true, function(err, hash, img) {
|
helpers.get_render(rid(), "Jake_0", 6, true, true, function(err, hash, img) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -893,7 +865,7 @@ describe("Crafatar", function() {
|
|||||||
|
|
||||||
describe("Networking: Cape", function() {
|
describe("Networking: Cape", function() {
|
||||||
it("should not fail (guaranteed cape)", function(done) {
|
it("should not fail (guaranteed cape)", function(done) {
|
||||||
helpers.get_cape(rid, "Dinnerbone", function(err, hash, status, img) {
|
helpers.get_cape(rid(), "Dinnerbone", function(err, hash, status, img) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -902,13 +874,13 @@ describe("Crafatar", function() {
|
|||||||
before(function() {
|
before(function() {
|
||||||
cache.get_redis().flushall();
|
cache.get_redis().flushall();
|
||||||
});
|
});
|
||||||
helpers.get_cape(rid, "Dinnerbone", function(err, hash, status, img) {
|
helpers.get_cape(rid(), "Dinnerbone", function(err, hash, status, img) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("should not be found", function(done) {
|
it("should not be found", function(done) {
|
||||||
helpers.get_cape(rid, "Jake_0", function(err, hash, status, img) {
|
helpers.get_cape(rid(), "Jake_0", function(err, hash, status, img) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(img, null);
|
assert.strictEqual(img, null);
|
||||||
done();
|
done();
|
||||||
@ -918,7 +890,7 @@ describe("Crafatar", function() {
|
|||||||
|
|
||||||
describe("Networking: Skin", function() {
|
describe("Networking: Skin", function() {
|
||||||
it("should not fail", function(done) {
|
it("should not fail", function(done) {
|
||||||
helpers.get_cape(rid, "Jake_0", function(err, hash, status, img) {
|
helpers.get_cape(rid(), "Jake_0", function(err, hash, status, img) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -927,7 +899,7 @@ describe("Crafatar", function() {
|
|||||||
before(function() {
|
before(function() {
|
||||||
cache.get_redis().flushall();
|
cache.get_redis().flushall();
|
||||||
});
|
});
|
||||||
helpers.get_cape(rid, "Jake_0", function(err, hash, status, img) {
|
helpers.get_cape(rid(), "Jake_0", function(err, hash, status, img) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -948,14 +920,14 @@ describe("Crafatar", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should be downloaded", function(done) {
|
it("should be downloaded", function(done) {
|
||||||
helpers.get_avatar(rid, id, false, 160, function(err, status, image) {
|
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(status, 2);
|
assert.strictEqual(status, 2);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("should be cached", function(done) {
|
it("should be cached", function(done) {
|
||||||
helpers.get_avatar(rid, id, false, 160, function(err, status, image) {
|
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(status === 0 || status === 1, true);
|
assert.strictEqual(status === 0 || status === 1, true);
|
||||||
done();
|
done();
|
||||||
@ -967,7 +939,7 @@ describe("Crafatar", function() {
|
|||||||
it("should be checked", function(done) {
|
it("should be checked", function(done) {
|
||||||
var original_cache_time = config.caching.local;
|
var original_cache_time = config.caching.local;
|
||||||
config.caching.local = 0;
|
config.caching.local = 0;
|
||||||
helpers.get_avatar(rid, id, false, 160, function(err, status, image) {
|
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(status, 3);
|
assert.strictEqual(status, 3);
|
||||||
config.caching.local = original_cache_time;
|
config.caching.local = original_cache_time;
|
||||||
@ -979,7 +951,7 @@ describe("Crafatar", function() {
|
|||||||
|
|
||||||
describe("Networking: Skin", function() {
|
describe("Networking: Skin", function() {
|
||||||
it("should not fail (uuid)", function(done) {
|
it("should not fail (uuid)", function(done) {
|
||||||
helpers.get_skin(rid, id, function(err, hash, status, img) {
|
helpers.get_skin(rid(), id, function(err, hash, status, img) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -988,13 +960,13 @@ describe("Crafatar", function() {
|
|||||||
|
|
||||||
describe("Networking: Render", function() {
|
describe("Networking: Render", function() {
|
||||||
it("should not fail (full body)", function(done) {
|
it("should not fail (full body)", function(done) {
|
||||||
helpers.get_render(rid, id, 6, true, true, function(err, hash, img) {
|
helpers.get_render(rid(), id, 6, true, true, function(err, hash, img) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("should not fail (only head)", function(done) {
|
it("should not fail (only head)", function(done) {
|
||||||
helpers.get_render(rid, id, 6, true, false, function(err, hash, img) {
|
helpers.get_render(rid(), id, 6, true, false, function(err, hash, img) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -1003,7 +975,7 @@ describe("Crafatar", function() {
|
|||||||
|
|
||||||
describe("Networking: Cape", function() {
|
describe("Networking: Cape", function() {
|
||||||
it("should not fail (possible cape)", function(done) {
|
it("should not fail (possible cape)", function(done) {
|
||||||
helpers.get_cape(rid, id, function(err, hash, status, img) {
|
helpers.get_cape(rid(), id, function(err, hash, status, img) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -1018,8 +990,8 @@ describe("Crafatar", function() {
|
|||||||
|
|
||||||
if (id_type === "uuid") {
|
if (id_type === "uuid") {
|
||||||
it("uuid should be rate limited", function(done) {
|
it("uuid should be rate limited", function(done) {
|
||||||
networking.get_profile(rid, id, function() {
|
networking.get_profile(rid(), id, function() {
|
||||||
networking.get_profile(rid, id, function(err, profile) {
|
networking.get_profile(rid(), id, function(err, profile) {
|
||||||
assert.strictEqual(err.toString(), "HTTP: 429");
|
assert.strictEqual(err.toString(), "HTTP: 429");
|
||||||
assert.strictEqual(profile, null);
|
assert.strictEqual(profile, null);
|
||||||
done();
|
done();
|
||||||
@ -1028,8 +1000,8 @@ describe("Crafatar", function() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
it("username should NOT be rate limited (username)", function(done) {
|
it("username should NOT be rate limited (username)", function(done) {
|
||||||
helpers.get_avatar(rid, id, false, 160, function() {
|
helpers.get_avatar(rid(), id, false, 160, function() {
|
||||||
helpers.get_avatar(rid, id, false, 160, function(err, status, image) {
|
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) {
|
||||||
assert.strictEqual(err, null);
|
assert.strictEqual(err, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user