mojang.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. const request = require('request')
  2. const minecraftAgent = {
  3. name: 'Minecraft',
  4. version: 1
  5. }
  6. const authpath = 'https://authserver.mojang.com'
  7. const statuses = [
  8. {
  9. service: 'minecraft.net',
  10. status: 'grey',
  11. name: 'Minecraft.net'
  12. },
  13. {
  14. service: 'api.mojang.com',
  15. status: 'grey',
  16. name: 'Public API'
  17. },
  18. {
  19. service: 'textures.minecraft.net',
  20. status: 'grey',
  21. name: 'Minecraft Skins'
  22. },
  23. {
  24. service: 'authserver.mojang.com',
  25. status: 'grey',
  26. name: 'Authentication Service'
  27. },
  28. {
  29. service: 'sessionserver.mojang.com',
  30. status: 'grey',
  31. name: 'Multiplayer Session Service'
  32. },
  33. {
  34. service: 'account.mojang.com',
  35. status: 'grey',
  36. name: 'Mojang accounts website'
  37. }
  38. ]
  39. /**
  40. * Converts a Mojang status color to a hex value. Valid statuses
  41. * are 'green', 'yellow', 'red', and 'grey'. Grey is a custom status
  42. * to our project which represents an unknown status.
  43. *
  44. * @param {string} status A valid status code.
  45. * @returns {string} The hex color of the status code.
  46. */
  47. exports.statusToHex = function(status){
  48. switch(status.toLowerCase()){
  49. case 'green':
  50. return '#a5c325'
  51. case 'yellow':
  52. return '#eac918'
  53. case 'red':
  54. return '#c32625'
  55. case 'grey':
  56. default:
  57. return '#848484'
  58. }
  59. }
  60. /**
  61. * Retrieves the status of Mojang's services.
  62. * The response is condensed into a single object. Each service is
  63. * a key, where the value is an object containing a status and name
  64. * property.
  65. *
  66. * @see http://wiki.vg/Mojang_API#API_Status
  67. */
  68. exports.status = function(){
  69. return new Promise(function(fulfill, reject) {
  70. request.get('https://status.mojang.com/check',
  71. {
  72. json: true
  73. },
  74. function(error, response, body){
  75. if(response.statusCode === 200){
  76. for(let i=0; i<body.length; i++){
  77. const key = Object.keys(body[i])[0]
  78. inner:
  79. for(let j=0; j<statuses.length; j++){
  80. if(statuses[j].service === key) {
  81. statuses[j].status = body[i][key]
  82. break inner
  83. }
  84. }
  85. }
  86. fulfill(statuses)
  87. } else {
  88. reject()
  89. }
  90. })
  91. })
  92. }
  93. /**
  94. * Authenticate a user with their Mojang credentials.
  95. *
  96. * @param {string} username The user's username, this is often an email.
  97. * @param {string} password The user's password.
  98. * @param {string} clientToken The launcher's Client Token.
  99. * @param {boolean} requestUser Optional. Adds user object to the reponse.
  100. * @param {Object} agent Optional. Provided by default. Adds user info to the response.
  101. *
  102. * @see http://wiki.vg/Authentication#Authenticate
  103. */
  104. exports.authenticate = function(username, password, clientToken, requestUser = true, agent = minecraftAgent){
  105. return new Promise(function(fulfill, reject){
  106. request.post(authpath + '/authenticate',
  107. {
  108. json: true,
  109. body: {
  110. agent,
  111. username,
  112. password,
  113. clientToken,
  114. requestUser
  115. }
  116. },
  117. function(error, response, body){
  118. if(response.statusCode === 200){
  119. fulfill(body)
  120. } else {
  121. reject(body)
  122. }
  123. })
  124. })
  125. }
  126. /**
  127. * Validate an access token. This should always be done before launching.
  128. * The client token should match the one used to create the access token.
  129. *
  130. * @param {string} accessToken The access token to validate.
  131. * @param {string} clientToken The launcher's client token.
  132. *
  133. * @see http://wiki.vg/Authentication#Validate
  134. */
  135. exports.validate = function(accessToken, clientToken){
  136. return new Promise(function(fulfill, reject){
  137. request.post(authpath + '/validate',
  138. {
  139. json: true,
  140. body: {
  141. accessToken,
  142. clientToken
  143. }
  144. },
  145. function(error, response, body){
  146. if(response.statusCode === 403){
  147. fulfill(false)
  148. } else {
  149. // 204 if valid
  150. fulfill(true)
  151. }
  152. })
  153. })
  154. }
  155. /**
  156. * Invalidates an access token. The clientToken must match the
  157. * token used to create the provided accessToken.
  158. *
  159. * @param {string} accessToken The access token to invalidate.
  160. * @param {string} clientToken The launcher's client token.
  161. *
  162. * @see http://wiki.vg/Authentication#Invalidate
  163. */
  164. exports.invalidate = function(accessToken, clientToken){
  165. return new Promise(function(fulfill, reject){
  166. request.post(authpath + '/invalidate',
  167. {
  168. json: true,
  169. body: {
  170. accessToken,
  171. clientToken
  172. }
  173. },
  174. function(error, response, body){
  175. if(response.statusCode === 200){
  176. fulfill()
  177. } else {
  178. reject()
  179. }
  180. })
  181. })
  182. }
  183. /**
  184. * Refresh a user's authentication. This should be used to keep a user logged
  185. * in without asking them for their credentials again. A new access token will
  186. * be generated using a recent invalid access token. See Wiki for more info.
  187. *
  188. * @param {string} accessToken The old access token.
  189. * @param {string} clientToken The launcher's client token.
  190. * @param {boolean} requestUser Optional. Adds user object to the reponse.
  191. *
  192. * @see http://wiki.vg/Authentication#Refresh
  193. */
  194. exports.refresh = function(accessToken, clientToken, requestUser = true){
  195. return new Promise(function(fulfill, reject){
  196. request.post(authpath + '/refresh',
  197. {
  198. json: true,
  199. body: {
  200. accessToken,
  201. clientToken,
  202. requestUser
  203. }
  204. },
  205. function(error, response, body){
  206. if(response.statusCode === 200){
  207. fulfill(body)
  208. } else {
  209. reject(response.body)
  210. }
  211. })
  212. })
  213. }