| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 | var logging = require("./logging");var request = require("request");var config = require("./config");var skins = require("./skins");var fs = require("fs");var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";var skins_url = "https://skins.minecraft.net/MinecraftSkins/";// exracts the skin url of a +profile+ object// returns null when no url found (user has no skin)function extract_skin_url(profile) {  var url = null;  if (profile && profile.properties) {    profile.properties.forEach(function(prop) {      if (prop.name == "textures") {        var json = Buffer(prop.value, "base64").toString();        var props = JSON.parse(json);        url = props && props.textures && props.textures.SKIN && props.textures.SKIN.url || null;      }    });  }  return url;}// make a request to skins.miencraft.net// the skin url is taken from the HTTP redirectvar get_username_url = function(name, callback) {  request.get({    url: skins_url + name + ".png",    headers: {      "User-Agent": "https://crafatar.com"    },    timeout: config.http_timeout,    followRedirect: false  }, function(error, response, body) {    if (!error && response.statusCode == 301) {      // skin_url received successfully      logging.log(name + " skin url received");      callback(null, response.headers.location);    } else if (error) {      callback(error, null);    } else if (response.statusCode == 404) {      // skin (or user) doesn't exist      logging.log(name + " has no skin");      callback(null, null);    } else if (response.statusCode == 429) {      // Too Many Requests      // Never got this, seems like skins aren't limited      logging.warn(body || "Too many requests");      callback(null, null);    } else {      logging.error(name + " Unknown error:");      logging.error(response);      callback(body || "Unknown error", null);    }  });};// make a request to sessionserver// the skin_url is taken from the profilevar get_uuid_url = function(uuid, callback) {  request.get({    url: session_url + uuid,    headers: {      "User-Agent": "https://crafatar.com"    },    timeout: config.http_timeout // ms  }, function (error, response, body) {    if (!error && response.statusCode == 200) {      // profile downloaded successfully      logging.log(uuid + " profile downloaded");      callback(null, extract_skin_url(JSON.parse(body)));    } else if (error) {      callback(error, null);    } else if (response.statusCode == 204 || response.statusCode == 404) {      // we get 204 No Content when UUID doesn't exist (including 404 in case they change that)      logging.log(uuid + " uuid does not exist");      callback(null, null);    } else if (response.statusCode == 429) {      // Too Many Requests      callback(body || "Too many requests", null);    } else {      logging.error(uuid + " Unknown error:");      logging.error(response);      callback(body || "Unknown error", null);    }  });};var exp = {};// download skin_url for +uuid+ (name or uuid)// callback contains error, skin_urlexp.get_skin_url = function(uuid, callback) {  if (uuid.length <= 16) {    get_username_url(uuid, function(err, url) {      callback(err, url);    });  } else {    get_uuid_url(uuid, function(err, url) {      callback(err, url);    });  }};// downloads skin file from +url+// callback contains error, imageexp.get_skin = function(url, callback) {  request.get({    url: url,    headers: {      "User-Agent": "https://crafatar.com"    },    encoding: null, // encoding must be null so we get a buffer    timeout: config.http_timeout // ms  }, function (error, response, body) {    if (!error && response.statusCode == 200) {      // skin downloaded successfully      logging.log("downloaded skin");      logging.debug(url);      callback(null, body);    } else {      if (error) {        logging.error("Error downloading '" + url + "': " + error);      } else if (response.statusCode == 404) {        logging.warn("texture not found (404): " + url);      } else if (response.statusCode == 429) {        // Too Many Requests        // Never got this, seems like textures aren't limited        logging.warn("too many requests for " + url);        logging.warn(body);      } else {        logging.error("unknown error for " + url);        logging.error(response);        logging.error(body);        error = "unknown error"; // Error needs to be set, otherwise null in callback      }      callback(error, null);    }  });};exp.save_skin = function(uuid, hash, outpath, callback) {  if (hash) {    var skinurl = "http://textures.minecraft.net/texture/" + hash;    exp.get_skin(skinurl, function(err, img) {      if (err) {        logging.error("error while downloading skin");        callback(err, null);      } else {        fs.writeFile(outpath, img, "binary", function(err){          if (err) {            logging.log(err);          }          callback(null, img);        });      }    });  } else {    callback(null, null);  }};module.exports = exp;
 |