diff --git a/lib/cache.js b/lib/cache.js index 2b8c8cf..cda3848 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -64,7 +64,7 @@ exp.get_redis = function() { // updates the redis instance's server_info object -// callback contains error, info object +// callback: error, info object exp.info = function(callback) { redis.info(function (err, res) { @@ -95,7 +95,7 @@ exp.info = function(callback) { // sets the timestamp for +userId+ and its face file's (+hash+) date to the current time // 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 -// +callback+ contains error +// callback: error exp.update_timestamp = function(rid, userId, hash, temp, callback) { logging.log(rid + "cache: updating timestamp"); sub = temp ? (config.local_cache_time - 60) : 0; @@ -143,7 +143,7 @@ exp.remove_hash = function(rid, userId) { // get a details object for +userId+ // {skin: "0123456789abcdef", cape: "gs1gds1g5d1g5ds1", time: 1414881524512} -// +callback+ contains error, details +// callback: error, details // details is null when userId not cached exp.get_details = function(userId, callback) { // get userId in lower case if not null diff --git a/lib/cleaner.js b/lib/cleaner.js index f014591..f8e190e 100644 --- a/lib/cleaner.js +++ b/lib/cleaner.js @@ -8,7 +8,7 @@ var redis = cache.get_redis(); var exp = {}; // compares redis' used_memory with cleaning_redis_limit -// callback contains error, true|false +// callback: error, true|false function should_clean_redis(callback) { cache.info(function(err, info) { if (err) { @@ -28,7 +28,7 @@ function should_clean_redis(callback) { } // uses `df` to get the available fisk space -// callback contains error, true|false +// callback: error, true|false function should_clean_disk(callback) { df({ file: __dirname + "/../" + config.faces_dir, diff --git a/lib/helpers.js b/lib/helpers.js index e0aaa42..67f3ed5 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -15,11 +15,15 @@ function get_hash(url) { return hash_pattern.exec(url)[0].toLowerCase(); } -function store_skin(rid, userId, profile, details, callback) { +// 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 +// face and face+helm images are extracted and stored to files +// callback: error, skin hash +function store_skin(rid, userId, profile, cache_details, callback) { networking.get_skin_url(rid, userId, profile, function(err, url) { if (!err && url) { var skin_hash = get_hash(url); - if (details && details.skin === skin_hash) { + if (cache_details && cache_details.skin === skin_hash) { cache.update_timestamp(rid, userId, skin_hash, false, function(err) { callback(err, skin_hash); }); @@ -60,11 +64,15 @@ function store_skin(rid, userId, profile, details, callback) { }); } -function store_cape(rid, userId, profile, details, callback) { +// gets the cape for +userId+ with +profile+ +// uses +cache_details+ to determine if the cape needs to be downloaded or can be taken from cache +// the cape - if downloaded - is stored to file +// callback: error, cape hash +function store_cape(rid, userId, profile, cache_details, callback) { networking.get_cape_url(rid, userId, profile, function(err, url) { if (!err && url) { var cape_hash = get_hash(url); - if (details && details.cape === cape_hash) { + if (cache_details && cache_details.cape === cape_hash) { cache.update_timestamp(rid, userId, cape_hash, false, function(err) { callback(err, cape_hash); }); @@ -120,7 +128,10 @@ function callback_for(userId, type, err, hash) { } } -// returns true if any object in +arr+ has +value+ as +property+ +// returns true if any object in +arr+ has a +property+ that matches +value+ +// +// deep_property_check([{foo: "bar"}, {foo: "baz"}], "foo", "baz"); +// function deep_property_check(arr, property, value) { for (var i = 0; i < arr.length; i++) { if (arr[i][property] === value) { @@ -131,10 +142,10 @@ function deep_property_check(arr, property, value) { } // downloads the images for +userId+ while checking the cache -// status based on +details+. +type+ specifies which +// status based on +cache_details+. +type+ specifies which // image type should be called back on -// +callback+ contains error, image hash -function store_images(rid, userId, details, type, callback) { +// callback: error, image hash +function store_images(rid, userId, cache_details, type, callback) { var is_uuid = userId.length > 16; var new_hash = { rid: rid, @@ -160,7 +171,7 @@ function store_images(rid, userId, details, type, callback) { } } else { // no error and we have a profile (if it's a uuid) - store_skin(rid, userId, profile, details, function(err, skin_hash) { + store_skin(rid, userId, profile, cache_details, function(err, skin_hash) { if (err && !skin_hash) { // an error occured, not caching. we can try in 60 seconds callback_for(userId, "skin", err, null); @@ -170,7 +181,7 @@ function store_images(rid, userId, details, type, callback) { }); } }); - store_cape(rid, userId, profile, details, function(err, cape_hash) { + store_cape(rid, userId, profile, cache_details, function(err, cape_hash) { if (err && !cape_hash) { // an error occured, not caching. we can try in 60 seconds callback_for(userId, "cape", (err || cache_err), cape_hash); @@ -197,7 +208,7 @@ exp.id_valid = function(userId) { }; // decides whether to get a +type+ image for +userId+ from disk or to download it -// callback contains error, status, hash +// callback: error, status, hash // the status gives information about how the image was received // -1: "error" // 0: "none" - cached as null @@ -205,32 +216,32 @@ exp.id_valid = function(userId) { // 2: "downloaded" - profile downloaded, skin downloaded from mojang servers // 3: "checked" - profile re-downloaded (was too old), but it has either not changed or has no skin exp.get_image_hash = function(rid, userId, type, callback) { - cache.get_details(userId, function(err, details) { - var cached_hash = (details !== null) ? (type === "skin" ? details.skin : details.cape) : null; + cache.get_details(userId, function(err, cache_details) { + var cached_hash = (cache_details !== null) ? (type === "skin" ? cache_details.skin : cache_details.cape) : null; if (err) { callback(err, -1, null); } else { - if (details && details[type] !== undefined && details.time + config.local_cache_time * 1000 >= new Date().getTime()) { + if (cache_details && cache_details[type] !== undefined && cache_details.time + config.local_cache_time * 1000 >= new Date().getTime()) { // use cached image logging.log(rid + "userId cached & recently updated"); callback(null, (cached_hash ? 1 : 0), cached_hash); } else { // download image - if (details) { + if (cache_details) { logging.log(rid + "userId cached, but too old"); } else { logging.log(rid + "userId not cached"); } - store_images(rid, userId, details, type, function(err, new_hash) { + store_images(rid, userId, cache_details, type, function(err, new_hash) { if (err) { // we might have a cached hash although an error occured // (e.g. Mojang servers not reachable, using outdated hash) cache.update_timestamp(rid, userId, cached_hash, true, function(err2) { - callback(err2 || err, -1, details && cached_hash); + callback(err2 || err, -1, cache_details && cached_hash); }); } else { - var status = details && (cached_hash === new_hash) ? 3 : 2; - logging.debug(rid + "cached hash: " + (details && cached_hash)); + var status = cache_details && (cached_hash === new_hash) ? 3 : 2; + logging.debug(rid + "cached hash: " + (cache_details && cached_hash)); logging.log(rid + "new hash: " + new_hash); callback(null, status, new_hash); } @@ -242,7 +253,7 @@ exp.get_image_hash = function(rid, userId, type, callback) { // handles requests for +userId+ avatars with +size+ -// callback contains error, status, image buffer, skin hash +// callback: error, status, image buffer, skin hash // image is the user's face+helm when helm is true, or the face otherwise // for status, see get_image_hash exp.get_avatar = function(rid, userId, helm, size, callback) { @@ -271,7 +282,7 @@ exp.get_avatar = function(rid, userId, helm, size, callback) { }; // handles requests for +userId+ skins -// callback contains error, skin hash, image buffer +// callback: error, skin hash, image buffer exp.get_skin = function(rid, userId, callback) { exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash) { var skinpath = __dirname + "/../" + config.skins_dir + skin_hash + ".png"; @@ -290,13 +301,16 @@ exp.get_skin = function(rid, userId, callback) { }); }; +// helper method used for file names +// possible returned names based on +helm+ and +body+ are: +// body, bodyhelm, head, headhelm function get_type(helm, body) { var text = body ? "body" : "head"; return helm ? text + "helm" : text; } // handles creations of 3D renders -// callback contains error, skin hash, image buffer +// callback: error, skin hash, image buffer exp.get_render = function(rid, userId, scale, helm, body, callback) { exp.get_skin(rid, userId, function(err, skin_hash, img) { if (!skin_hash) { @@ -335,7 +349,7 @@ exp.get_render = function(rid, userId, scale, helm, body, callback) { }; // handles requests for +userId+ capes -// callback contains error, cape hash, image buffer +// callback: error, cape hash, image buffer exp.get_cape = function(rid, userId, callback) { exp.get_image_hash(rid, userId, "cape", function(err, status, cape_hash) { if (!cape_hash) { diff --git a/lib/logging.js b/lib/logging.js index 8b4f031..f49fc9b 100644 --- a/lib/logging.js +++ b/lib/logging.js @@ -3,23 +3,23 @@ var config = require("./config"); var exp = {}; -function split_args(args) { - var text = ""; +// returns all values in the +args+ object separated by " " +function join_args(args) { + var values = []; for (var i = 0, l = args.length; i < l; i++) { - if (i > 0) { - text += " " + args[i]; - } else { - text += args[i]; - } + values.push(args[i]); } - return text; + return values.join(" "); } +// prints +args+ to +logger+ (defaults to `console.log`) +// the +level+ and a timestamp is prepended to each line of log +// the timestamp can be disabled in the config function log(level, args, logger) { logger = logger || console.log; var time = config.log_time ? new Date().toISOString() + " " : ""; var clid = (cluster.worker && cluster.worker.id || "M"); - var lines = split_args(args).split("\n"); + var lines = join_args(args).split("\n"); for (var i = 0, l = lines.length; i < l; i++) { logger(time + clid + " " + level + ": " + lines[i]); } @@ -42,4 +42,4 @@ if (config.debug_enabled || process.env.DEBUG === "true") { exp.debug = function(){}; } -module.exports = exp; +module.exports = exp; \ No newline at end of file diff --git a/lib/networking.js b/lib/networking.js index 24992f5..9aacb9b 100644 --- a/lib/networking.js +++ b/lib/networking.js @@ -12,36 +12,39 @@ var mojang_urls = [skins_url, capes_url]; var exp = {}; -function extract_url(profile, property) { +// extracts the +type+ [SKIN|CAPE] URL +// 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[property] && props.textures[property].url || null; + url = props && props.textures && props.textures[type] && props.textures[type].url || null; } }); } return url; } -// exracts the skin url of a +profile+ object -// returns null when no url found (user has no skin) +// 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) +// 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'); }; -// makes a GET request to the +url+ -// +options+ hash includes these options: +// performs a GET request to the +url+ +// +options+ object includes these options: // encoding (string), default is to return a buffer -// +callback+ contains the body, response, +// callback: the body, response, // and error buffer. get_from helper method is available exp.get_from_options = function(rid, url, options, callback) { request.get({ @@ -55,7 +58,9 @@ exp.get_from_options = function(rid, url, options, callback) { }, function(error, response, body) { // log url + code + description var code = response && response.statusCode; - if (!error) { + if (error) { + logging.error(url, error); + } else { var logfunc = code && code < 405 ? logging.log : logging.warn; logfunc(rid + url + " " + code + " " + http_code[code]); } @@ -65,7 +70,6 @@ exp.get_from_options = function(rid, url, options, callback) { // response received successfully callback(body, response, null); } else if (error) { - logging.error(error); callback(body || null, response, error); } else if (code === 404 || code === 204) { // page does not exist @@ -115,7 +119,7 @@ exp.get_uuid_url = function(profile, type, callback) { }; // make a request to sessionserver for +uuid+ -// +callback+ contains error, profile +// callback: error, profile exp.get_profile = function(rid, uuid, callback) { if (!uuid) { callback(null, null); @@ -142,6 +146,8 @@ exp.get_cape_url = function(rid, userId, profile, callback) { }); }; +// 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 function get_url(rid, userId, profile, type, callback) { if (userId.length <= 16) { //username @@ -155,6 +161,9 @@ function get_url(rid, userId, profile, type, callback) { } } +// download the +tex_hash+ image from the texture server +// and save it in the +outpath+ file +// callback: error, response, image buffer exp.save_texture = function(rid, tex_hash, outpath, callback) { if (tex_hash) { var textureurl = textures_url + tex_hash; diff --git a/lib/renders.js b/lib/renders.js index 2febfaa..d518110 100644 --- a/lib/renders.js +++ b/lib/renders.js @@ -128,7 +128,7 @@ exp.draw_body = function(rid, skin_canvas, model_ctx, scale) { // sets up the necessary components to draw the skin model // uses the +img+ skin with options of drawing // the +helm+ and the +body+ -// callback contains error, image buffer +// callback: error, image buffer exp.draw_model = function(rid, img, scale, helm, body, callback) { var image = new Image(); @@ -169,7 +169,7 @@ exp.draw_model = function(rid, img, scale, helm, body, callback) { }; // helper method to open a render from +renderpath+ -// callback contains error, image buffer +// callback: error, image buffer exp.open_render = function(rid, renderpath, callback) { fs.readFile(renderpath, function (err, buf) { if (err) { diff --git a/lib/skins.js b/lib/skins.js index ebf4a7f..da9a85d 100644 --- a/lib/skins.js +++ b/lib/skins.js @@ -6,7 +6,7 @@ var exp = {}; // extracts the face from an image +buffer+ // result is saved to a file called +outname+ -// +callback+ contains error +// callback: error exp.extract_face = function(buffer, outname, callback) { lwip.open(buffer, "png", function(err, image) { if (err) { @@ -28,7 +28,7 @@ exp.extract_face = function(buffer, outname, callback) { // extracts the helm from an image +buffer+ and lays it over a +facefile+ // +facefile+ is the filename of an image produced by extract_face // result is saved to a file called +outname+ -// +callback+ contains error +// callback: error exp.extract_helm = function(rid, facefile, buffer, outname, callback) { lwip.open(buffer, "png", function(err, skin_img) { if (err) { @@ -69,7 +69,7 @@ exp.extract_helm = function(rid, facefile, buffer, outname, callback) { }; // resizes the image file +inname+ to +size+ by +size+ pixels -// +callback+ contains error, image buffer +// callback: error, image buffer exp.resize_img = function(inname, size, callback) { lwip.open(inname, function(err, image) { if (err) { @@ -105,7 +105,7 @@ exp.default_skin = function(uuid) { }; // helper method for opening a skin file from +skinpath+ -// callback contains error, image buffer +// callback: error, image buffer exp.open_skin = function(rid, skinpath, callback) { fs.readFile(skinpath, function(err, buf) { if (err) { @@ -117,6 +117,8 @@ exp.open_skin = function(rid, skinpath, callback) { }); }; +// write the image +buffer+ to the +outpath+ file +// callback: error exp.save_image = function(buffer, outpath, callback) { lwip.open(buffer, "png", function(err, image) { if (err) {