Added mojang functions, most of which are pending testing. Once testing is complete, the external 'mojang' module will be removed. The 'Mojang Status' are on the landing page is now displaying the actual statuses of mojang's services. This will be refreshed once every 5 minutes. Enhancements will be made to the UI of this down the line.

This commit is contained in:
Daniel Scalzi 2017-12-03 07:05:13 -05:00
parent a4012458be
commit 3c7d7d79af
3 changed files with 257 additions and 1 deletions

View File

@ -375,7 +375,7 @@ p {
#mojang_status_icon {
font-size: 30px;
color: #a5c325;
color: #848484;
margin-left: 15px;
}

View File

@ -4,7 +4,11 @@ const {AssetGuard} = require(path.join(__dirname, 'assets', 'js', 'assetguard.js
const ProcessBuilder = require(path.join(__dirname, 'assets', 'js', 'processbuilder.js'))
const ConfigManager = require(path.join(__dirname, 'assets', 'js', 'configmanager.js'))
const DiscordWrapper = require(path.join(__dirname, 'assets', 'js', 'discordwrapper.js'))
const mojang2 = require(path.join(__dirname, 'assets', 'js', 'mojang.js'))
let mojangStatusListener
// Synchronous Listener
document.addEventListener('readystatechange', function(){
if (document.readyState === 'interactive'){
@ -18,6 +22,39 @@ document.addEventListener('readystatechange', function(){
// Bind selected server
document.getElementById('server_selection').innerHTML = '\u2022 ' + AssetGuard.getServerById(ConfigManager.getGameDirectory(), ConfigManager.getSelectedServer()).name
// Update Mojang Status Color
const refreshMojangStatuses = async function(){
console.log('Refreshing Mojang Statuses..')
try {
let status = 'grey'
const statuses = await mojang2.status()
greenCount = 0
for(let i=0; i<statuses.length; i++){
if(statuses[i].status === 'yellow' && status !== 'red'){
status = 'yellow'
continue
} else if(statuses[i].status === 'red'){
status = 'red'
break
}
++greenCount
}
if(greenCount == statuses.length){
status = 'green'
}
document.getElementById('mojang_status_icon').style.color = mojang2.statusToHex(status)
} catch (err) {
console.error('Unable to refresh Mojang service status..', err)
}
}
refreshMojangStatuses()
// Set refresh rate to once every 5 minutes.
mojangStatusListener = setInterval(refreshMojangStatuses, 300000)
}
}, false)

219
app/assets/js/mojang.js Normal file
View File

@ -0,0 +1,219 @@
const request = require('request')
const minecraftAgent = {
name: 'Minecraft',
version: 1
}
const authpath = 'https://authserver.mojang.com'
const statuses = [
{
service: 'minecraft.net',
status: 'grey',
name: 'Minecraft.net'
},
{
service: 'api.mojang.com',
status: 'grey',
name: 'Public API'
},
{
service: 'textures.minecraft.net',
status: 'grey',
name: 'Minecraft Skins'
},
{
service: 'authserver.mojang.com',
status: 'grey',
name: 'Authentication Service'
},
{
service: 'sessionserver.mojang.com',
status: 'grey',
name: 'Multiplayer Session Service'
},
{
service: 'account.mojang.com',
status: 'grey',
name: 'Mojang accounts website'
}
]
/**
* Converts a Mojang status color to a hex value. Valid statuses
* are 'green', 'yellow', 'red', and 'grey'. Grey is a custom status
* to our project which represends an unknown status.
*
* @param {String} status - a valid status code.
* @returns {String} - the hex color of the status code.
*/
exports.statusToHex = function(status){
switch(status.toLowerCase()){
case 'green':
return '#a5c325'
case 'yellow':
return '#eac918'
case 'red':
return '#c32625'
case 'grey':
default:
return '#848484'
}
}
/**
* Retrieves the status of Mojang's services.
* The response is condensed into a single object. Each service is
* a key, where the value is an object containing a status and name
* property.
*
* @see http://wiki.vg/Mojang_API#API_Status
*/
exports.status = function(){
return new Promise(function(fulfill, reject) {
request.get('https://status.mojang.com/check',
{
json: true
},
function(error, response, body){
if(response.statusCode === 200){
for(let i=0; i<body.length; i++){
const key = Object.keys(body[i])[0]
inner:
for(let j=0; j<statuses.length; j++){
if(statuses[j].service === key) {
statuses[j].status = body[i][key]
break inner
}
}
}
fulfill(statuses)
} else {
reject()
}
})
})
}
/**
* Authenticate a user with their Mojang credentials.
*
* @param {String} username - user's username, this is often an email.
* @param {String} password - user's password.
* @param {String} clientToken - launcher's Client Token.
* @param {Boolean} requestUser - optional. Adds user object to the reponse.
* @param {Object} agent - optional. Provided by default. Adds user info to the response.
*
* @see http://wiki.vg/Authentication#Authenticate
*/
exports.authenticate = function(username, password, clientToken, requestUser = true, agent = minecraftAgent){
return new Promise(function(fulfill, reject){
request.post(authpath + '/authenticate',
{
json: true,
body: {
agent,
username,
password,
clientToken,
requestUser
}
},
function(error, response, body){
if(response.statusCode === 200){
fulfill(body)
} else {
reject()
}
})
})
}
/**
* Validate an access token. This should always be done before launching.
* The client token should match the one used to create the access token.
*
* @param {String} accessToken - the access token to validate.
* @param {String} clientToken - the launcher's client token.
*
* @see http://wiki.vg/Authentication#Validate
*/
exports.validate = function(accessToken, clientToken){
return new Promise(function(fulfill, reject){
request.post(authpath + '/validate',
{
json: true,
body: {
accessToken,
clientToken
}
},
function(error, response, body){
if(error && error.message === 'Invalid token'){
fulfill(false)
} else {
fulfill(true)
}
})
})
}
/**
* Invalidates an access token. The clientToken must match the
* token used to create the provided accessToken.
*
* @param {String} accessToken - the access token to invalidate.
* @param {String} clientToken - the launcher's client token.
*
* @see http://wiki.vg/Authentication#Invalidate
*/
exports.invalidate = function(accessToken, clientToken){
return new Promise(function(fulfill, reject){
request.post(authpath + '/invalidate',
{
json: true,
body: {
accessToken,
clientToken
}
},
function(error, response, body){
if(response.statusCode === 200){
fulfill()
} else {
reject()
}
})
})
}
/**
* Refresh a user's authentication. This should be used to keep a user logged
* in without asking them for their credentials again. A new access token will
* be generated using a recent invalid access token. See Wiki for more info.
*
* @param {String} accessToken - the old access token.
* @param {String} clientToken - the launcher's client token.
* @param {Boolean} requestUser - optional. Adds user object to the reponse.
*
* @see http://wiki.vg/Authentication#Refresh
*/
exports.refresh = function(accessToken, clientToken, requestUser = true){
return new Promise(function(fulfill, reject){
request.post(authpath + '/refresh',
{
json: true,
body: {
accessToken,
clientToken,
requestUser
}
},
function(error, response, body){
if(response.statusCode === 200){
fulfill(body)
} else {
reject()
}
})
})
}