123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- var http_code = require("http").STATUS_CODES;
- var logging = require("./logging");
- var request = require("request");
- var config = require("../config");
- var skins = require("./skins");
- require("./object-patch");
- var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";
- var textures_url = "http://textures.minecraft.net/texture/";
- var exp = {};
- // performs a GET request to the +url+
- // +options+ object includes these options:
- // encoding (string), default is to return a buffer
- // callback: the body, response,
- // and error buffer. get_from helper method is available
- exp.get_from_options = function(rid, url, options, callback) {
- request.get({
- url: url,
- headers: {
- "User-Agent": "Crafatar (+https://crafatar.com)"
- },
- timeout: config.server.http_timeout,
- followRedirect: false,
- encoding: options.encoding || null,
- }, function(error, response, body) {
- // log url + code + description
- var code = response && response.statusCode;
- var logfunc = code && code < 405 ? logging.debug : logging.warn;
- logfunc(rid, url, code || error && error.code, http_code[code]);
- // not necessarily used
- var e = new Error(code);
- e.name = "HTTP";
- e.code = "HTTPERROR";
- switch (code) {
- case 200:
- case 301:
- case 302: // never seen, but mojang might use it in future
- case 307: // never seen, but mojang might use it in future
- case 308: // never seen, but mojang might use it in future
- // these are okay
- break;
- case 204: // no content, used like 404 by mojang. making sure it really has no content
- case 404:
- // can be cached as null
- body = null;
- break;
- case 429: // this shouldn't usually happen, but occasionally does
- case 500:
- case 502: // CloudFront can't reach mojang origin
- case 503:
- case 504:
- // we don't want to cache this
- error = error || e;
- body = null;
- break;
- default:
- if (!error) {
- // Probably 500 or the likes
- logging.error(rid, "Unexpected response:", code, body);
- }
- error = error || e;
- body = null;
- break;
- }
- if (body && !body.length) {
- // empty response
- body = null;
- }
- callback(body, response, error);
- });
- };
- // helper method for get_from_options, no options required
- exp.get_from = function(rid, url, callback) {
- exp.get_from_options(rid, url, {}, function(body, response, err) {
- callback(body, response, err);
- });
- };
- // gets the URL for a skin/cape from the profile
- // +type+ "SKIN" or "CAPE", specifies which to retrieve
- // callback: url, slim
- exp.get_uuid_info = function(profile, type, callback) {
- var properties = Object.get(profile, "properties") || [];
- properties.forEach(function(prop) {
- if (prop.name === "textures") {
- var json = new Buffer.from(prop.value, "base64").toString();
- profile = JSON.parse(json);
- }
- });
- var url = Object.get(profile, "textures." + type + ".url");
- var slim;
- if (type === "SKIN") {
- slim = Object.get(profile, "textures.SKIN.metadata.model") === "slim";
- }
- callback(null, url || null, !!slim);
- };
- // make a request to sessionserver for +uuid+
- // callback: error, profile
- exp.get_profile = function(rid, uuid, callback) {
- exp.get_from_options(rid, session_url + uuid, { encoding: "utf8" }, function(body, response, err) {
- try {
- body = body ? JSON.parse(body) : null;
- callback(err || null, body);
- } catch(e) {
- if (e instanceof SyntaxError) {
- logging.warn(rid, "Failed to parse JSON", e);
- logging.debug(rid, body);
- callback(err || null, null);
- } else {
- throw e;
- }
- }
- });
- };
- // get the skin URL and type for +userId+
- // +profile+ is used if +userId+ is a uuid
- // callback: error, url, slim
- exp.get_skin_info = function(rid, userId, profile, callback) {
- exp.get_uuid_info(profile, "SKIN", callback);
- };
- // get the cape URL for +userId+
- // +profile+ is used if +userId+ is a uuid
- exp.get_cape_url = function(rid, userId, profile, callback) {
- exp.get_uuid_info(profile, "CAPE", 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;
- exp.get_from(rid, textureurl, function(img, response, err) {
- if (err) {
- callback(err, response, null);
- } else {
- skins.save_image(img, outpath, function(img_err) {
- callback(img_err, response, img);
- });
- }
- });
- } else {
- callback(null, null, null);
- }
- };
- module.exports = exp;
|