networking.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. var request = require('request');
  2. var config = require('./config');
  3. var skins = require('./skins');
  4. var fs = require("fs");
  5. var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";
  6. var skins_url = "https://skins.minecraft.net/MinecraftSkins/";
  7. // exracts the skin url of a +profile+ object
  8. // returns null when no url found (user has no skin)
  9. function extract_skin_url(profile) {
  10. var url = null;
  11. if (profile && profile.properties) {
  12. profile.properties.forEach(function(prop) {
  13. if (prop.name == 'textures') {
  14. var json = Buffer(prop.value, 'base64').toString();
  15. var props = JSON.parse(json);
  16. url = props && props.textures && props.textures.SKIN && props.textures.SKIN.url || null;
  17. }
  18. });
  19. }
  20. return url;
  21. }
  22. // make a request to skins.miencraft.net
  23. // the skin url is taken from the HTTP redirect
  24. var get_username_url = function(name, callback) {
  25. request.get({
  26. url: skins_url + name + ".png",
  27. timeout: config.http_timeout,
  28. followRedirect: false
  29. }, function(error, response, body) {
  30. if (!error && response.statusCode == 301) {
  31. // skin_url received successfully
  32. console.log(name + " skin url received");
  33. callback(null, response.headers.location);
  34. } else if (error) {
  35. callback(error, null);
  36. } else if (response.statusCode == 404) {
  37. // skin doesn't exist
  38. console.log(name + " has no skin");
  39. callback(0, null);
  40. } else if (response.statusCode == 429) {
  41. // Too Many Requests
  42. // Never got this, seems like skins aren't limited
  43. console.warn(name + " Too many requests");
  44. console.warn(body);
  45. callback(null, null);
  46. } else {
  47. console.error(name + " Unknown error:");
  48. console.error(response);
  49. console.error(body);
  50. callback(null, null);
  51. }
  52. });
  53. };
  54. // make a request to sessionserver
  55. // the skin_url is taken from the profile
  56. var get_uuid_url = function(uuid, callback) {
  57. request.get({
  58. url: session_url + uuid,
  59. timeout: config.http_timeout // ms
  60. }, function (error, response, body) {
  61. if (!error && response.statusCode == 200) {
  62. // profile downloaded successfully
  63. console.log(uuid + " profile downloaded");
  64. callback(null, extract_skin_url(JSON.parse(body)));
  65. } else if (error) {
  66. callback(error, null);
  67. } else if (response.statusCode == 204 || response.statusCode == 404) {
  68. // we get 204 No Content when UUID doesn't exist (including 404 in case they change that)
  69. console.log(uuid + " uuid does not exist");
  70. callback(0, null);
  71. } else if (response.statusCode == 429) {
  72. // Too Many Requests
  73. console.warn(uuid + " Too many requests");
  74. console.warn(body);
  75. callback(null, null);
  76. } else {
  77. console.error(uuid + " Unknown error:");
  78. console.error(response);
  79. console.error(body);
  80. callback(null, null);
  81. }
  82. });
  83. };
  84. var exp = {};
  85. // download skin_url for +uuid+ (name or uuid)
  86. // callback contains error, skin_url
  87. exp.get_skin_url = function(uuid, callback) {
  88. if (uuid.length <= 16) {
  89. get_username_url(uuid, function(err, url) {
  90. callback(err, url);
  91. });
  92. } else {
  93. get_uuid_url(uuid, function(err, url) {
  94. callback(err, url);
  95. });
  96. }
  97. };
  98. // downloads skin file from +url+
  99. // stores face image as +facename+
  100. // stores helm image as +helmname+
  101. // callback contains error
  102. exp.skin_file = function(url, facename, helmname, callback) {
  103. if (fs.existsSync(facename) && fs.existsSync(facename)) {
  104. console.log("Images already exist, not downloading.");
  105. callback(null);
  106. return;
  107. }
  108. request.get({
  109. url: url,
  110. encoding: null, // encoding must be null so we get a buffer
  111. timeout: config.http_timeout // ms
  112. }, function (error, response, body) {
  113. if (!error && response.statusCode == 200) {
  114. // skin downloaded successfully
  115. console.log(url + " skin downloaded");
  116. skins.extract_face(body, facename, function(err) {
  117. if (err) {
  118. callback(err);
  119. } else {
  120. console.log(facename + " face extracted");
  121. skins.extract_helm(facename, body, helmname, function(err) {
  122. console.log(helmname + " helm extracted.");
  123. callback(err);
  124. });
  125. }
  126. });
  127. } else {
  128. if (error) {
  129. console.error("Error downloading '" + url + "': " + error);
  130. } else if (response.statusCode == 404) {
  131. console.warn("texture not found (404): " + url);
  132. } else if (response.statusCode == 429) {
  133. // Too Many Requests
  134. // Never got this, seems like textures aren't limited
  135. console.warn("too many requests for " + url);
  136. console.warn(body);
  137. } else {
  138. console.error("unknown error for " + url);
  139. console.error(response);
  140. console.error(body);
  141. error = "unknown error"; // Error needs to be set, otherwise null in callback
  142. }
  143. callback(error);
  144. }
  145. });
  146. };
  147. module.exports = exp;