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 redirect
- var 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(name + body || "Too many requests");
- callback(null, null);
- } else {
- logging.error(name + " Unknown error:");
- logging.error(name + " " + response);
- callback(body || "Unknown error", null);
- }
- });
- };
- // make a request to sessionserver
- // the skin_url is taken from the profile
- var 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(uuid + " " + response);
- callback(body || "Unknown error", null);
- }
- });
- };
- var exp = {};
- // download skin_url for +uuid+ (name or uuid)
- // callback contains error, skin_url
- exp.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, image
- exp.get_skin = function(url, uuid, 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(uuid + " downloaded skin");
- logging.debug(uuid + " " + url);
- callback(null, body);
- } else {
- if (error) {
- logging.error(uuid + " error downloading '" + url + "': " + error);
- } else if (response.statusCode == 404) {
- logging.warn(uuid + " texture not found (404): " + url);
- } else if (response.statusCode == 429) {
- // Too Many Requests
- // Never got this, seems like textures aren't limited
- logging.warn(uuid + " too many requests for " + url);
- logging.warn(uuid + " " + body);
- } else {
- logging.error(uuid + " unknown error for " + url);
- logging.error(uuid + " " + response);
- logging.error(uuid + " " + 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, uuid, function(err, img) {
- if (err) {
- logging.error(uuid + " error while downloading skin");
- callback(err, null);
- } else {
- fs.writeFile(outpath, img, "binary", function(err){
- if (err) {
- logging.log(uuid + " error: " + err);
- }
- callback(null, img);
- });
- }
- });
- } else {
- callback(null, null);
- }
- };
- module.exports = exp;
|