Clean up structure of Mojang API/Util files.
This commit is contained in:
parent
571b788e25
commit
c7b95f3719
@ -1,6 +0,0 @@
|
|||||||
export interface Agent {
|
|
||||||
|
|
||||||
name: 'Minecraft'
|
|
||||||
version: number
|
|
||||||
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
import { Agent } from './Agent'
|
|
||||||
|
|
||||||
export interface AuthPayload {
|
|
||||||
|
|
||||||
agent: Agent
|
|
||||||
username: string
|
|
||||||
password: string
|
|
||||||
clientToken?: string
|
|
||||||
requestUser?: boolean
|
|
||||||
|
|
||||||
}
|
|
157
src/common/mojang/net/Protocol.ts
Normal file
157
src/common/mojang/net/Protocol.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* Utility Class to construct a packet conforming to Minecraft's
|
||||||
|
* protocol. All data types are BE except VarInt and VarLong.
|
||||||
|
*
|
||||||
|
* @see https://wiki.vg/Protocol
|
||||||
|
*/
|
||||||
|
export class ServerBoundPacket {
|
||||||
|
|
||||||
|
private buffer: number[]
|
||||||
|
|
||||||
|
protected constructor() {
|
||||||
|
this.buffer = []
|
||||||
|
}
|
||||||
|
|
||||||
|
public static build(): ServerBoundPacket {
|
||||||
|
return new ServerBoundPacket()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet is prefixed with its data length as a VarInt.
|
||||||
|
*
|
||||||
|
* @see https://wiki.vg/Protocol#Packet_format
|
||||||
|
*/
|
||||||
|
public toBuffer(): Buffer {
|
||||||
|
const finalizedPacket = new ServerBoundPacket()
|
||||||
|
finalizedPacket.writeVarInt(this.buffer.length)
|
||||||
|
finalizedPacket.writeBytes(...this.buffer)
|
||||||
|
|
||||||
|
return Buffer.from(finalizedPacket.buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeBytes(...bytes: number[]): ServerBoundPacket {
|
||||||
|
this.buffer.push(...bytes)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://wiki.vg/Protocol#VarInt_and_VarLong
|
||||||
|
*/
|
||||||
|
public writeVarInt(value: number): ServerBoundPacket {
|
||||||
|
do {
|
||||||
|
let temp = value & 0b01111111
|
||||||
|
|
||||||
|
value >>>= 7
|
||||||
|
|
||||||
|
if (value != 0) {
|
||||||
|
temp |= 0b10000000
|
||||||
|
}
|
||||||
|
|
||||||
|
this.writeBytes(temp)
|
||||||
|
} while (value != 0)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strings are prefixed with their length as a VarInt.
|
||||||
|
*
|
||||||
|
* @see https://wiki.vg/Protocol#Data_types
|
||||||
|
*/
|
||||||
|
public writeString(string: string): ServerBoundPacket {
|
||||||
|
this.writeVarInt(string.length)
|
||||||
|
for (let i=0; i<string.length; i++) {
|
||||||
|
this.writeBytes(string.codePointAt(i)!)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeUnsignedShort(short: number): ServerBoundPacket {
|
||||||
|
const buf = Buffer.alloc(2)
|
||||||
|
buf.writeUInt16BE(short, 0)
|
||||||
|
this.writeBytes(...buf)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility Class to read a client-bound packet conforming to
|
||||||
|
* Minecraft's protocol. All data types are BE except VarInt
|
||||||
|
* and VarLong.
|
||||||
|
*
|
||||||
|
* @see https://wiki.vg/Protocol
|
||||||
|
*/
|
||||||
|
export class ClientBoundPacket {
|
||||||
|
|
||||||
|
private buffer: number[]
|
||||||
|
|
||||||
|
constructor(buffer: Buffer) {
|
||||||
|
this.buffer = [...buffer]
|
||||||
|
}
|
||||||
|
|
||||||
|
public append(buffer: Buffer): void {
|
||||||
|
this.buffer.push(...buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
public readByte(): number {
|
||||||
|
return this.buffer.shift()!
|
||||||
|
}
|
||||||
|
|
||||||
|
public readBytes(length: number): number[] {
|
||||||
|
const value = this.buffer.slice(0, length)
|
||||||
|
this.buffer.splice(0, length)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
public readVarInt(): number {
|
||||||
|
|
||||||
|
let numRead = 0
|
||||||
|
let result = 0
|
||||||
|
let read
|
||||||
|
|
||||||
|
do {
|
||||||
|
read = this.readByte()
|
||||||
|
const value = (read & 0b01111111)
|
||||||
|
result |= (value << (7 * numRead))
|
||||||
|
|
||||||
|
numRead++
|
||||||
|
if (numRead > 5) {
|
||||||
|
throw new Error('VarInt is too big')
|
||||||
|
}
|
||||||
|
} while ((read & 0b10000000) != 0)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public readString(): string {
|
||||||
|
const length = this.readVarInt()
|
||||||
|
const data = this.readBytes(length)
|
||||||
|
|
||||||
|
let value = ''
|
||||||
|
|
||||||
|
for (let i=0; i<data.length; i++) {
|
||||||
|
value += String.fromCharCode(data[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ProtocolUtils {
|
||||||
|
|
||||||
|
public static getVarIntSize(value: number): number {
|
||||||
|
let size = 0
|
||||||
|
|
||||||
|
do {
|
||||||
|
value >>>= 7
|
||||||
|
size++
|
||||||
|
} while (value != 0)
|
||||||
|
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable no-control-regex */
|
/* eslint-disable no-control-regex */
|
||||||
import { connect } from 'net'
|
import { connect } from 'net'
|
||||||
import { LoggerUtil } from 'common/logging/loggerutil'
|
import { LoggerUtil } from 'common/logging/loggerutil'
|
||||||
|
import { ServerBoundPacket, ClientBoundPacket, ProtocolUtils } from './Protocol'
|
||||||
|
|
||||||
const logger = LoggerUtil.getLogger('ServerStatusUtil')
|
const logger = LoggerUtil.getLogger('ServerStatusUtil')
|
||||||
|
|
||||||
@ -30,161 +31,6 @@ export interface ServerStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility Class to construct a packet conforming to Minecraft's
|
|
||||||
* protocol. All data types are BE except VarInt and VarLong.
|
|
||||||
*
|
|
||||||
* @see https://wiki.vg/Protocol
|
|
||||||
*/
|
|
||||||
class ServerBoundPacket {
|
|
||||||
|
|
||||||
private buffer: number[]
|
|
||||||
|
|
||||||
protected constructor() {
|
|
||||||
this.buffer = []
|
|
||||||
}
|
|
||||||
|
|
||||||
public static build(): ServerBoundPacket {
|
|
||||||
return new ServerBoundPacket()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet is prefixed with its data length as a VarInt.
|
|
||||||
*
|
|
||||||
* @see https://wiki.vg/Protocol#Packet_format
|
|
||||||
*/
|
|
||||||
public toBuffer(): Buffer {
|
|
||||||
const finalizedPacket = new ServerBoundPacket()
|
|
||||||
finalizedPacket.writeVarInt(this.buffer.length)
|
|
||||||
finalizedPacket.writeBytes(...this.buffer)
|
|
||||||
|
|
||||||
return Buffer.from(finalizedPacket.buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
public writeBytes(...bytes: number[]): ServerBoundPacket {
|
|
||||||
this.buffer.push(...bytes)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://wiki.vg/Protocol#VarInt_and_VarLong
|
|
||||||
*/
|
|
||||||
public writeVarInt(value: number): ServerBoundPacket {
|
|
||||||
do {
|
|
||||||
let temp = value & 0b01111111
|
|
||||||
|
|
||||||
value >>>= 7
|
|
||||||
|
|
||||||
if (value != 0) {
|
|
||||||
temp |= 0b10000000
|
|
||||||
}
|
|
||||||
|
|
||||||
this.writeBytes(temp)
|
|
||||||
} while (value != 0)
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strings are prefixed with their length as a VarInt.
|
|
||||||
*
|
|
||||||
* @see https://wiki.vg/Protocol#Data_types
|
|
||||||
*/
|
|
||||||
public writeString(string: string): ServerBoundPacket {
|
|
||||||
this.writeVarInt(string.length)
|
|
||||||
for (let i=0; i<string.length; i++) {
|
|
||||||
this.writeBytes(string.codePointAt(i)!)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public writeUnsignedShort(short: number): ServerBoundPacket {
|
|
||||||
const buf = Buffer.alloc(2)
|
|
||||||
buf.writeUInt16BE(short, 0)
|
|
||||||
this.writeBytes(...buf)
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility Class to read a client-bound packet conforming to
|
|
||||||
* Minecraft's protocol. All data types are BE except VarInt
|
|
||||||
* and VarLong.
|
|
||||||
*
|
|
||||||
* @see https://wiki.vg/Protocol
|
|
||||||
*/
|
|
||||||
class ClientBoundPacket {
|
|
||||||
|
|
||||||
private buffer: number[]
|
|
||||||
|
|
||||||
constructor(buffer: Buffer) {
|
|
||||||
this.buffer = [...buffer]
|
|
||||||
}
|
|
||||||
|
|
||||||
public append(buffer: Buffer): void {
|
|
||||||
this.buffer.push(...buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
public readByte(): number {
|
|
||||||
return this.buffer.shift()!
|
|
||||||
}
|
|
||||||
|
|
||||||
public readBytes(length: number): number[] {
|
|
||||||
const value = this.buffer.slice(0, length)
|
|
||||||
this.buffer.splice(0, length)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
public readVarInt(): number {
|
|
||||||
|
|
||||||
let numRead = 0
|
|
||||||
let result = 0
|
|
||||||
let read
|
|
||||||
|
|
||||||
do {
|
|
||||||
read = this.readByte()
|
|
||||||
const value = (read & 0b01111111)
|
|
||||||
result |= (value << (7 * numRead))
|
|
||||||
|
|
||||||
numRead++
|
|
||||||
if (numRead > 5) {
|
|
||||||
throw new Error('VarInt is too big')
|
|
||||||
}
|
|
||||||
} while ((read & 0b10000000) != 0)
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
public readString(): string {
|
|
||||||
const length = this.readVarInt()
|
|
||||||
const data = this.readBytes(length)
|
|
||||||
|
|
||||||
let value = ''
|
|
||||||
|
|
||||||
for (let i=0; i<data.length; i++) {
|
|
||||||
value += String.fromCharCode(data[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getVarIntSize(value: number): number {
|
|
||||||
let size = 0
|
|
||||||
|
|
||||||
do {
|
|
||||||
value >>>= 7
|
|
||||||
|
|
||||||
size++
|
|
||||||
} while (value != 0)
|
|
||||||
|
|
||||||
return size
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the handshake packet.
|
* Get the handshake packet.
|
||||||
*
|
*
|
||||||
@ -217,7 +63,15 @@ function getRequestPacket(): Buffer {
|
|||||||
.toBuffer()
|
.toBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some servers do not return the same status object. Unify
|
||||||
|
* the response so that the caller need only worry about
|
||||||
|
* handling a single format.
|
||||||
|
*
|
||||||
|
* @param resp The servevr status response.
|
||||||
|
*/
|
||||||
function unifyStatusResponse(resp: ServerStatus): ServerStatus {
|
function unifyStatusResponse(resp: ServerStatus): ServerStatus {
|
||||||
|
// Some servers don't wrap their description in a text object.
|
||||||
if(typeof resp.description === 'string') {
|
if(typeof resp.description === 'string') {
|
||||||
resp.description = {
|
resp.description = {
|
||||||
text: resp.description
|
text: resp.description
|
||||||
@ -261,7 +115,7 @@ export function getServerStatus(protocol: number, address: string, port = 25565)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Size of packetLength VarInt is not included in the packetLength.
|
// Size of packetLength VarInt is not included in the packetLength.
|
||||||
bytesLeft = packetLength + getVarIntSize(packetLength)
|
bytesLeft = packetLength + ProtocolUtils.getVarIntSize(packetLength)
|
||||||
|
|
||||||
// Listener to keep reading until we have read all the bytes into the buffer.
|
// Listener to keep reading until we have read all the bytes into the buffer.
|
||||||
const packetReadListener = (nextData: Buffer, doAppend: boolean) => {
|
const packetReadListener = (nextData: Buffer, doAppend: boolean) => {
|
@ -1,3 +1,20 @@
|
|||||||
|
export interface Agent {
|
||||||
|
|
||||||
|
name: 'Minecraft'
|
||||||
|
version: number
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuthPayload {
|
||||||
|
|
||||||
|
agent: Agent
|
||||||
|
username: string
|
||||||
|
password: string
|
||||||
|
clientToken?: string
|
||||||
|
requestUser?: boolean
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export interface Session {
|
export interface Session {
|
||||||
|
|
||||||
accessToken: string
|
accessToken: string
|
@ -1,13 +1,11 @@
|
|||||||
import { LoggerUtil } from '../logging/loggerutil'
|
import { LoggerUtil } from '../../logging/loggerutil'
|
||||||
import { Agent } from './model/auth/Agent'
|
import { MojangStatus, MojangStatusColor } from './internal/MojangStatus'
|
||||||
import { Status, StatusColor } from './model/internal/Status'
|
|
||||||
import got, { RequestError, HTTPError } from 'got'
|
import got, { RequestError, HTTPError } from 'got'
|
||||||
import { Session } from './model/auth/Session'
|
import { MojangResponse, MojangErrorCode, decipherErrorCode, isInternalError, MojangErrorBody } from './internal/MojangResponse'
|
||||||
import { AuthPayload } from './model/auth/AuthPayload'
|
|
||||||
import { MojangResponse, MojangErrorCode, decipherErrorCode, isInternalError, MojangErrorBody } from './model/internal/MojangResponse'
|
|
||||||
import { RestResponseStatus, handleGotError } from 'common/got/RestResponse'
|
import { RestResponseStatus, handleGotError } from 'common/got/RestResponse'
|
||||||
|
import { Agent, AuthPayload, Session } from './Auth'
|
||||||
|
|
||||||
export class Mojang {
|
export class MojangRestAPI {
|
||||||
|
|
||||||
private static readonly logger = LoggerUtil.getLogger('Mojang')
|
private static readonly logger = LoggerUtil.getLogger('Mojang')
|
||||||
|
|
||||||
@ -17,12 +15,12 @@ export class Mojang {
|
|||||||
public static readonly STATUS_ENDPOINT = 'https://status.mojang.com'
|
public static readonly STATUS_ENDPOINT = 'https://status.mojang.com'
|
||||||
|
|
||||||
private static authClient = got.extend({
|
private static authClient = got.extend({
|
||||||
prefixUrl: Mojang.AUTH_ENDPOINT,
|
prefixUrl: MojangRestAPI.AUTH_ENDPOINT,
|
||||||
responseType: 'json',
|
responseType: 'json',
|
||||||
retry: 0
|
retry: 0
|
||||||
})
|
})
|
||||||
private static statusClient = got.extend({
|
private static statusClient = got.extend({
|
||||||
prefixUrl: Mojang.STATUS_ENDPOINT,
|
prefixUrl: MojangRestAPI.STATUS_ENDPOINT,
|
||||||
responseType: 'json',
|
responseType: 'json',
|
||||||
retry: 0
|
retry: 0
|
||||||
})
|
})
|
||||||
@ -32,40 +30,40 @@ export class Mojang {
|
|||||||
version: 1
|
version: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static statuses: Status[] = [
|
protected static statuses: MojangStatus[] = [
|
||||||
{
|
{
|
||||||
service: 'sessionserver.mojang.com',
|
service: 'sessionserver.mojang.com',
|
||||||
status: StatusColor.GREY,
|
status: MojangStatusColor.GREY,
|
||||||
name: 'Multiplayer Session Service',
|
name: 'Multiplayer Session Service',
|
||||||
essential: true
|
essential: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'authserver.mojang.com',
|
service: 'authserver.mojang.com',
|
||||||
status: StatusColor.GREY,
|
status: MojangStatusColor.GREY,
|
||||||
name: 'Authentication Service',
|
name: 'Authentication Service',
|
||||||
essential: true
|
essential: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'textures.minecraft.net',
|
service: 'textures.minecraft.net',
|
||||||
status: StatusColor.GREY,
|
status: MojangStatusColor.GREY,
|
||||||
name: 'Minecraft Skins',
|
name: 'Minecraft Skins',
|
||||||
essential: false
|
essential: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'api.mojang.com',
|
service: 'api.mojang.com',
|
||||||
status: StatusColor.GREY,
|
status: MojangStatusColor.GREY,
|
||||||
name: 'Public API',
|
name: 'Public API',
|
||||||
essential: false
|
essential: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'minecraft.net',
|
service: 'minecraft.net',
|
||||||
status: StatusColor.GREY,
|
status: MojangStatusColor.GREY,
|
||||||
name: 'Minecraft.net',
|
name: 'Minecraft.net',
|
||||||
essential: false
|
essential: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'account.mojang.com',
|
service: 'account.mojang.com',
|
||||||
status: StatusColor.GREY,
|
status: MojangStatusColor.GREY,
|
||||||
name: 'Mojang Accounts Website',
|
name: 'Mojang Accounts Website',
|
||||||
essential: false
|
essential: false
|
||||||
}
|
}
|
||||||
@ -78,13 +76,13 @@ export class Mojang {
|
|||||||
*/
|
*/
|
||||||
public static statusToHex(status: string): string {
|
public static statusToHex(status: string): string {
|
||||||
switch(status.toLowerCase()){
|
switch(status.toLowerCase()){
|
||||||
case StatusColor.GREEN:
|
case MojangStatusColor.GREEN:
|
||||||
return '#a5c325'
|
return '#a5c325'
|
||||||
case StatusColor.YELLOW:
|
case MojangStatusColor.YELLOW:
|
||||||
return '#eac918'
|
return '#eac918'
|
||||||
case StatusColor.RED:
|
case MojangStatusColor.RED:
|
||||||
return '#c32625'
|
return '#c32625'
|
||||||
case StatusColor.GREY:
|
case MojangStatusColor.GREY:
|
||||||
default:
|
default:
|
||||||
return '#848484'
|
return '#848484'
|
||||||
}
|
}
|
||||||
@ -92,7 +90,7 @@ export class Mojang {
|
|||||||
|
|
||||||
private static handleGotError<T>(operation: string, error: RequestError, dataProvider: () => T): MojangResponse<T> {
|
private static handleGotError<T>(operation: string, error: RequestError, dataProvider: () => T): MojangResponse<T> {
|
||||||
|
|
||||||
const response: MojangResponse<T> = handleGotError(operation, error, Mojang.logger, dataProvider)
|
const response: MojangResponse<T> = handleGotError(operation, error, MojangRestAPI.logger, dataProvider)
|
||||||
|
|
||||||
if(error instanceof HTTPError) {
|
if(error instanceof HTTPError) {
|
||||||
response.mojangErrorCode = decipherErrorCode(error.response.body as MojangErrorBody)
|
response.mojangErrorCode = decipherErrorCode(error.response.body as MojangErrorBody)
|
||||||
@ -106,7 +104,7 @@ export class Mojang {
|
|||||||
|
|
||||||
private static expectSpecificSuccess(operation: string, expected: number, actual: number) {
|
private static expectSpecificSuccess(operation: string, expected: number, actual: number) {
|
||||||
if(actual !== expected) {
|
if(actual !== expected) {
|
||||||
Mojang.logger.warn(`${operation} expected ${expected} response, recieved ${actual}.`)
|
MojangRestAPI.logger.warn(`${operation} expected ${expected} response, recieved ${actual}.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,35 +116,35 @@ export class Mojang {
|
|||||||
*
|
*
|
||||||
* @see http://wiki.vg/Mojang_API#API_Status
|
* @see http://wiki.vg/Mojang_API#API_Status
|
||||||
*/
|
*/
|
||||||
public static async status(): Promise<MojangResponse<Status[]>>{
|
public static async status(): Promise<MojangResponse<MojangStatus[]>>{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const res = await Mojang.statusClient.get<{[service: string]: StatusColor}[]>('check')
|
const res = await MojangRestAPI.statusClient.get<{[service: string]: MojangStatusColor}[]>('check')
|
||||||
|
|
||||||
Mojang.expectSpecificSuccess('Mojang Status', 200, res.statusCode)
|
MojangRestAPI.expectSpecificSuccess('Mojang Status', 200, res.statusCode)
|
||||||
|
|
||||||
res.body.forEach(status => {
|
res.body.forEach(status => {
|
||||||
const entry = Object.entries(status)[0]
|
const entry = Object.entries(status)[0]
|
||||||
for(let i=0; i<Mojang.statuses.length; i++) {
|
for(let i=0; i<MojangRestAPI.statuses.length; i++) {
|
||||||
if(Mojang.statuses[i].service === entry[0]) {
|
if(MojangRestAPI.statuses[i].service === entry[0]) {
|
||||||
Mojang.statuses[i].status = entry[1]
|
MojangRestAPI.statuses[i].status = entry[1]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: Mojang.statuses,
|
data: MojangRestAPI.statuses,
|
||||||
responseStatus: RestResponseStatus.SUCCESS
|
responseStatus: RestResponseStatus.SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
|
|
||||||
return Mojang.handleGotError('Mojang Status', error, () => {
|
return MojangRestAPI.handleGotError('Mojang Status', error, () => {
|
||||||
for(let i=0; i<Mojang.statuses.length; i++){
|
for(let i=0; i<MojangRestAPI.statuses.length; i++){
|
||||||
Mojang.statuses[i].status = StatusColor.GREY
|
MojangRestAPI.statuses[i].status = MojangStatusColor.GREY
|
||||||
}
|
}
|
||||||
return Mojang.statuses
|
return MojangRestAPI.statuses
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +166,7 @@ export class Mojang {
|
|||||||
password: string,
|
password: string,
|
||||||
clientToken: string | null,
|
clientToken: string | null,
|
||||||
requestUser = true,
|
requestUser = true,
|
||||||
agent: Agent = Mojang.MINECRAFT_AGENT
|
agent: Agent = MojangRestAPI.MINECRAFT_AGENT
|
||||||
): Promise<MojangResponse<Session | null>> {
|
): Promise<MojangResponse<Session | null>> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -183,15 +181,15 @@ export class Mojang {
|
|||||||
json.clientToken = clientToken
|
json.clientToken = clientToken
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await Mojang.authClient.post<Session>('authenticate', { json, responseType: 'json' })
|
const res = await MojangRestAPI.authClient.post<Session>('authenticate', { json, responseType: 'json' })
|
||||||
Mojang.expectSpecificSuccess('Mojang Authenticate', 200, res.statusCode)
|
MojangRestAPI.expectSpecificSuccess('Mojang Authenticate', 200, res.statusCode)
|
||||||
return {
|
return {
|
||||||
data: res.body,
|
data: res.body,
|
||||||
responseStatus: RestResponseStatus.SUCCESS
|
responseStatus: RestResponseStatus.SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
return Mojang.handleGotError('Mojang Authenticate', err, () => null)
|
return MojangRestAPI.handleGotError('Mojang Authenticate', err, () => null)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -214,8 +212,8 @@ export class Mojang {
|
|||||||
clientToken
|
clientToken
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await Mojang.authClient.post('validate', { json })
|
const res = await MojangRestAPI.authClient.post('validate', { json })
|
||||||
Mojang.expectSpecificSuccess('Mojang Validate', 204, res.statusCode)
|
MojangRestAPI.expectSpecificSuccess('Mojang Validate', 204, res.statusCode)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: res.statusCode === 204,
|
data: res.statusCode === 204,
|
||||||
@ -229,7 +227,7 @@ export class Mojang {
|
|||||||
responseStatus: RestResponseStatus.SUCCESS
|
responseStatus: RestResponseStatus.SUCCESS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Mojang.handleGotError('Mojang Validate', err, () => false)
|
return MojangRestAPI.handleGotError('Mojang Validate', err, () => false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -252,8 +250,8 @@ export class Mojang {
|
|||||||
clientToken
|
clientToken
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await Mojang.authClient.post('invalidate', { json })
|
const res = await MojangRestAPI.authClient.post('invalidate', { json })
|
||||||
Mojang.expectSpecificSuccess('Mojang Invalidate', 204, res.statusCode)
|
MojangRestAPI.expectSpecificSuccess('Mojang Invalidate', 204, res.statusCode)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: undefined,
|
data: undefined,
|
||||||
@ -261,7 +259,7 @@ export class Mojang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
return Mojang.handleGotError('Mojang Invalidate', err, () => undefined)
|
return MojangRestAPI.handleGotError('Mojang Invalidate', err, () => undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -287,8 +285,8 @@ export class Mojang {
|
|||||||
requestUser
|
requestUser
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await Mojang.authClient.post<Session>('refresh', { json, responseType: 'json' })
|
const res = await MojangRestAPI.authClient.post<Session>('refresh', { json, responseType: 'json' })
|
||||||
Mojang.expectSpecificSuccess('Mojang Refresh', 200, res.statusCode)
|
MojangRestAPI.expectSpecificSuccess('Mojang Refresh', 200, res.statusCode)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: res.body,
|
data: res.body,
|
||||||
@ -296,7 +294,7 @@ export class Mojang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
return Mojang.handleGotError('Mojang Refresh', err, () => null)
|
return MojangRestAPI.handleGotError('Mojang Refresh', err, () => null)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
export enum StatusColor {
|
export enum MojangStatusColor {
|
||||||
RED = 'red',
|
RED = 'red',
|
||||||
YELLOW = 'yellow',
|
YELLOW = 'yellow',
|
||||||
GREEN = 'green',
|
GREEN = 'green',
|
||||||
GREY = 'grey'
|
GREY = 'grey'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Status {
|
export interface MojangStatus {
|
||||||
|
|
||||||
service: string
|
service: string
|
||||||
status: StatusColor
|
status: MojangStatusColor
|
||||||
name: string
|
name: string
|
||||||
essential: boolean
|
essential: boolean
|
||||||
|
|
@ -18,7 +18,7 @@ import Overlay from './overlay/Overlay'
|
|||||||
import { OverlayPushAction, OverlayActionDispatch } from '../redux/actions/overlayActions'
|
import { OverlayPushAction, OverlayActionDispatch } from '../redux/actions/overlayActions'
|
||||||
|
|
||||||
import { DistributionAPI } from 'common/distribution/distribution'
|
import { DistributionAPI } from 'common/distribution/distribution'
|
||||||
import { getServerStatus } from 'common/util/ServerStatusUtil'
|
import { getServerStatus } from 'common/mojang/net/ServerStatusAPI'
|
||||||
|
|
||||||
import './Application.css'
|
import './Application.css'
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ class Application extends React.Component<ApplicationProps & typeof mapDispatch,
|
|||||||
const distro = new DistributionAPI('C:\\Users\\user\\AppData\\Roaming\\Helios Launcher')
|
const distro = new DistributionAPI('C:\\Users\\user\\AppData\\Roaming\\Helios Launcher')
|
||||||
const x = await distro.testLoad()
|
const x = await distro.testLoad()
|
||||||
console.log(x)
|
console.log(x)
|
||||||
const serverStatus = await getServerStatus(47, 'mc.westeroscraft.com', 25565)
|
const serverStatus = await getServerStatus(47, 'play.hypixel.net', 25565)
|
||||||
console.log(serverStatus)
|
console.log(serverStatus)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
|
||||||
import { Status, StatusColor } from 'common/mojang/model/internal/Status'
|
import { MojangStatus, MojangStatusColor } from 'common/mojang/rest/internal/MojangStatus'
|
||||||
import { MojangResponse } from 'common/mojang/model/internal/MojangResponse'
|
import { MojangResponse } from 'common/mojang/rest/internal/MojangResponse'
|
||||||
import { Mojang } from 'common/mojang/mojang'
|
import { MojangRestAPI } from 'common/mojang/rest/MojangRestAPI'
|
||||||
import { RestResponseStatus } from 'common/got/RestResponse'
|
import { RestResponseStatus } from 'common/got/RestResponse'
|
||||||
import { LoggerUtil } from 'common/logging/loggerutil'
|
import { LoggerUtil } from 'common/logging/loggerutil'
|
||||||
|
|
||||||
import './Landing.css'
|
import './Landing.css'
|
||||||
|
|
||||||
interface LandingState {
|
interface LandingState {
|
||||||
mojangStatuses: Status[]
|
mojangStatuses: MojangStatus[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Landing extends React.Component<unknown, LandingState> {
|
export default class Landing extends React.Component<unknown, LandingState> {
|
||||||
@ -45,7 +45,7 @@ export default class Landing extends React.Component<unknown, LandingState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private loadMojangStatuses = async (): Promise<void> => {
|
private loadMojangStatuses = async (): Promise<void> => {
|
||||||
const response: MojangResponse<Status[]> = await Mojang.status()
|
const response: MojangResponse<MojangStatus[]> = await MojangRestAPI.status()
|
||||||
|
|
||||||
if(response.responseStatus !== RestResponseStatus.SUCCESS) {
|
if(response.responseStatus !== RestResponseStatus.SUCCESS) {
|
||||||
Landing.logger.warn('Failed to retrieve Mojang Statuses.')
|
Landing.logger.warn('Failed to retrieve Mojang Statuses.')
|
||||||
@ -56,7 +56,7 @@ export default class Landing extends React.Component<unknown, LandingState> {
|
|||||||
const statuses = response.data
|
const statuses = response.data
|
||||||
for(const status of statuses) {
|
for(const status of statuses) {
|
||||||
if(status.service === 'sessionserver.mojang.com' || status.service === 'minecraft.net') {
|
if(status.service === 'sessionserver.mojang.com' || status.service === 'minecraft.net') {
|
||||||
status.status = StatusColor.GREEN
|
status.status = MojangStatusColor.GREEN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,27 +71,27 @@ export default class Landing extends React.Component<unknown, LandingState> {
|
|||||||
const essential = this.state.mojangStatuses.filter(s => s.essential)
|
const essential = this.state.mojangStatuses.filter(s => s.essential)
|
||||||
|
|
||||||
if(this.state.mojangStatuses.length === 0) {
|
if(this.state.mojangStatuses.length === 0) {
|
||||||
return Mojang.statusToHex(StatusColor.GREY)
|
return MojangRestAPI.statusToHex(MojangStatusColor.GREY)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any essential are red, it's red.
|
// If any essential are red, it's red.
|
||||||
if(essential.filter(s => s.status === StatusColor.RED).length > 0) {
|
if(essential.filter(s => s.status === MojangStatusColor.RED).length > 0) {
|
||||||
return Mojang.statusToHex(StatusColor.RED)
|
return MojangRestAPI.statusToHex(MojangStatusColor.RED)
|
||||||
}
|
}
|
||||||
// If any essential are yellow, it's yellow.
|
// If any essential are yellow, it's yellow.
|
||||||
if(essential.filter(s => s.status === StatusColor.YELLOW).length > 0) {
|
if(essential.filter(s => s.status === MojangStatusColor.YELLOW).length > 0) {
|
||||||
return Mojang.statusToHex(StatusColor.YELLOW)
|
return MojangRestAPI.statusToHex(MojangStatusColor.YELLOW)
|
||||||
}
|
}
|
||||||
// If any non-essential are not green, return yellow.
|
// If any non-essential are not green, return yellow.
|
||||||
if(this.state.mojangStatuses.filter(s => s.status !== StatusColor.GREEN && s.status !== StatusColor.GREY).length > 0) {
|
if(this.state.mojangStatuses.filter(s => s.status !== MojangStatusColor.GREEN && s.status !== MojangStatusColor.GREY).length > 0) {
|
||||||
return Mojang.statusToHex(StatusColor.YELLOW)
|
return MojangRestAPI.statusToHex(MojangStatusColor.YELLOW)
|
||||||
}
|
}
|
||||||
// if all are grey, return grey.
|
// if all are grey, return grey.
|
||||||
if(this.state.mojangStatuses.filter(s => s.status === StatusColor.GREY).length === this.state.mojangStatuses.length) {
|
if(this.state.mojangStatuses.filter(s => s.status === MojangStatusColor.GREY).length === this.state.mojangStatuses.length) {
|
||||||
return Mojang.statusToHex(StatusColor.GREY)
|
return MojangRestAPI.statusToHex(MojangStatusColor.GREY)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Mojang.statusToHex(StatusColor.GREEN)
|
return MojangRestAPI.statusToHex(MojangStatusColor.GREEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMojangStatusesAsJSX = (essential: boolean): JSX.Element[] => {
|
private getMojangStatusesAsJSX = (essential: boolean): JSX.Element[] => {
|
||||||
@ -101,7 +101,7 @@ export default class Landing extends React.Component<unknown, LandingState> {
|
|||||||
statuses.push(
|
statuses.push(
|
||||||
<>
|
<>
|
||||||
<div className="mojangStatusContainer">
|
<div className="mojangStatusContainer">
|
||||||
<span className="mojangStatusIcon" style={{color: Mojang.statusToHex(status.status)}}>•</span>
|
<span className="mojangStatusIcon" style={{color: MojangRestAPI.statusToHex(status.status)}}>•</span>
|
||||||
<span className="mojangStatusName">{status.name}</span>
|
<span className="mojangStatusName">{status.name}</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { Mojang } from 'common/mojang/mojang'
|
import { MojangRestAPI } from 'common/mojang/rest/MojangRestAPI'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import nock from 'nock'
|
import nock from 'nock'
|
||||||
import { Session } from 'common/mojang/model/auth/Session'
|
import { Session } from 'common/mojang/rest/Auth'
|
||||||
import { MojangErrorCode, MojangResponse } from 'common/mojang/model/internal/MojangResponse'
|
import { MojangErrorCode, MojangResponse } from 'common/mojang/rest/internal/MojangResponse'
|
||||||
import { RestResponseStatus, RestResponse } from 'common/got/RestResponse'
|
import { RestResponseStatus, RestResponse } from 'common/got/RestResponse'
|
||||||
|
|
||||||
function assertResponse(res: RestResponse<unknown>) {
|
function assertResponse(res: RestResponse<unknown>) {
|
||||||
@ -39,13 +39,13 @@ describe('Mojang Errors', () => {
|
|||||||
|
|
||||||
it('Status (Offline)', async () => {
|
it('Status (Offline)', async () => {
|
||||||
|
|
||||||
const defStatusHack = Mojang['statuses']
|
const defStatusHack = MojangRestAPI['statuses']
|
||||||
|
|
||||||
nock(Mojang.STATUS_ENDPOINT)
|
nock(MojangRestAPI.STATUS_ENDPOINT)
|
||||||
.get('/check')
|
.get('/check')
|
||||||
.reply(500, 'Service temprarily offline.')
|
.reply(500, 'Service temprarily offline.')
|
||||||
|
|
||||||
const res = await Mojang.status()
|
const res = await MojangRestAPI.status()
|
||||||
expectFailure(res)
|
expectFailure(res)
|
||||||
expect(res.data).to.be.an('array')
|
expect(res.data).to.be.an('array')
|
||||||
expect(res.data).to.deep.equal(defStatusHack)
|
expect(res.data).to.deep.equal(defStatusHack)
|
||||||
@ -54,7 +54,7 @@ describe('Mojang Errors', () => {
|
|||||||
|
|
||||||
it('Authenticate (Invalid Credentials)', async () => {
|
it('Authenticate (Invalid Credentials)', async () => {
|
||||||
|
|
||||||
nock(Mojang.AUTH_ENDPOINT)
|
nock(MojangRestAPI.AUTH_ENDPOINT)
|
||||||
.post('/authenticate')
|
.post('/authenticate')
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
.reply(403, (uri, requestBody: unknown): { error: string, errorMessage: string } => {
|
.reply(403, (uri, requestBody: unknown): { error: string, errorMessage: string } => {
|
||||||
@ -64,7 +64,7 @@ describe('Mojang Errors', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await Mojang.authenticate('user', 'pass', 'xxx', true)
|
const res = await MojangRestAPI.authenticate('user', 'pass', 'xxx', true)
|
||||||
expectMojangResponse(res, MojangErrorCode.ERROR_INVALID_CREDENTIALS)
|
expectMojangResponse(res, MojangErrorCode.ERROR_INVALID_CREDENTIALS)
|
||||||
expect(res.data).to.be.a('null')
|
expect(res.data).to.be.a('null')
|
||||||
expect(res.error).to.not.be.a('null')
|
expect(res.error).to.not.be.a('null')
|
||||||
@ -76,13 +76,13 @@ describe('Mojang Status', () => {
|
|||||||
|
|
||||||
it('Status (Online)', async () => {
|
it('Status (Online)', async () => {
|
||||||
|
|
||||||
const defStatusHack = Mojang['statuses']
|
const defStatusHack = MojangRestAPI['statuses']
|
||||||
|
|
||||||
nock(Mojang.STATUS_ENDPOINT)
|
nock(MojangRestAPI.STATUS_ENDPOINT)
|
||||||
.get('/check')
|
.get('/check')
|
||||||
.reply(200, defStatusHack)
|
.reply(200, defStatusHack)
|
||||||
|
|
||||||
const res = await Mojang.status()
|
const res = await MojangRestAPI.status()
|
||||||
expectSuccess(res)
|
expectSuccess(res)
|
||||||
expect(res.data).to.be.an('array')
|
expect(res.data).to.be.an('array')
|
||||||
expect(res.data).to.deep.equal(defStatusHack)
|
expect(res.data).to.deep.equal(defStatusHack)
|
||||||
@ -95,7 +95,7 @@ describe('Mojang Auth', () => {
|
|||||||
|
|
||||||
it('Authenticate', async () => {
|
it('Authenticate', async () => {
|
||||||
|
|
||||||
nock(Mojang.AUTH_ENDPOINT)
|
nock(MojangRestAPI.AUTH_ENDPOINT)
|
||||||
.post('/authenticate')
|
.post('/authenticate')
|
||||||
.reply(200, (uri, requestBody: any): Session => {
|
.reply(200, (uri, requestBody: any): Session => {
|
||||||
const mockResponse: Session = {
|
const mockResponse: Session = {
|
||||||
@ -117,7 +117,7 @@ describe('Mojang Auth', () => {
|
|||||||
return mockResponse
|
return mockResponse
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await Mojang.authenticate('user', 'pass', 'xxx', true)
|
const res = await MojangRestAPI.authenticate('user', 'pass', 'xxx', true)
|
||||||
expectSuccess(res)
|
expectSuccess(res)
|
||||||
expect(res.data!.clientToken).to.equal('xxx')
|
expect(res.data!.clientToken).to.equal('xxx')
|
||||||
expect(res.data).to.have.property('user')
|
expect(res.data).to.have.property('user')
|
||||||
@ -126,7 +126,7 @@ describe('Mojang Auth', () => {
|
|||||||
|
|
||||||
it('Validate', async () => {
|
it('Validate', async () => {
|
||||||
|
|
||||||
nock(Mojang.AUTH_ENDPOINT)
|
nock(MojangRestAPI.AUTH_ENDPOINT)
|
||||||
.post('/validate')
|
.post('/validate')
|
||||||
.times(2)
|
.times(2)
|
||||||
.reply((uri, requestBody: any) => {
|
.reply((uri, requestBody: any) => {
|
||||||
@ -135,13 +135,13 @@ describe('Mojang Auth', () => {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await Mojang.validate('abc', 'def')
|
const res = await MojangRestAPI.validate('abc', 'def')
|
||||||
|
|
||||||
expectSuccess(res)
|
expectSuccess(res)
|
||||||
expect(res.data).to.be.a('boolean')
|
expect(res.data).to.be.a('boolean')
|
||||||
expect(res.data).to.equal(true)
|
expect(res.data).to.equal(true)
|
||||||
|
|
||||||
const res2 = await Mojang.validate('def', 'def')
|
const res2 = await MojangRestAPI.validate('def', 'def')
|
||||||
|
|
||||||
expectSuccess(res2)
|
expectSuccess(res2)
|
||||||
expect(res2.data).to.be.a('boolean')
|
expect(res2.data).to.be.a('boolean')
|
||||||
@ -151,11 +151,11 @@ describe('Mojang Auth', () => {
|
|||||||
|
|
||||||
it('Invalidate', async () => {
|
it('Invalidate', async () => {
|
||||||
|
|
||||||
nock(Mojang.AUTH_ENDPOINT)
|
nock(MojangRestAPI.AUTH_ENDPOINT)
|
||||||
.post('/invalidate')
|
.post('/invalidate')
|
||||||
.reply(204)
|
.reply(204)
|
||||||
|
|
||||||
const res = await Mojang.invalidate('adc', 'def')
|
const res = await MojangRestAPI.invalidate('adc', 'def')
|
||||||
|
|
||||||
expectSuccess(res)
|
expectSuccess(res)
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ describe('Mojang Auth', () => {
|
|||||||
|
|
||||||
it('Refresh', async () => {
|
it('Refresh', async () => {
|
||||||
|
|
||||||
nock(Mojang.AUTH_ENDPOINT)
|
nock(MojangRestAPI.AUTH_ENDPOINT)
|
||||||
.post('/refresh')
|
.post('/refresh')
|
||||||
.reply(200, (uri, requestBody: any): Session => {
|
.reply(200, (uri, requestBody: any): Session => {
|
||||||
const mockResponse: Session = {
|
const mockResponse: Session = {
|
||||||
@ -185,7 +185,7 @@ describe('Mojang Auth', () => {
|
|||||||
return mockResponse
|
return mockResponse
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await Mojang.refresh('gfd', 'xxx', true)
|
const res = await MojangRestAPI.refresh('gfd', 'xxx', true)
|
||||||
expectSuccess(res)
|
expectSuccess(res)
|
||||||
expect(res.data!.clientToken).to.equal('xxx')
|
expect(res.data!.clientToken).to.equal('xxx')
|
||||||
expect(res.data).to.have.property('user')
|
expect(res.data).to.have.property('user')
|
||||||
|
Loading…
Reference in New Issue
Block a user