mojang-auth
Version:
Mojang authentication client, re-implementing parts of `node-yggdrasil` in classes, and adding support for custom auth servers.
113 lines (107 loc) • 3.44 kB
text/typescript
import { Agent } from 'http'
import fetch from 'node-fetch'
//import { version } from './package.json';
const version = '1';
const headers = {
'User-Agent': `minecraft-auth/${version as string}`,
'Content-Type': 'application/json'
}
const utils = {
/**
* Generic POST request
*/
async call(host: string, path: string, data: any, agent: Agent | undefined) {
const resp = await fetch(`${host}/${path}`, { agent, body: JSON.stringify(data), headers, method: 'POST' });
let body: string | any = await resp.text()
if (body.length === 0) return ''
try {
body = JSON.parse(body)
} catch (e) {
if (e instanceof SyntaxError) {
if (resp.status === 403) {
if ((body as string).includes('Request blocked.')) {
throw new Error('Request blocked by CloudFlare')
}
if ((body as string).includes('cf-error-code">1009')) {
throw new Error('Your IP is banned by CloudFlare')
}
} else {
throw new Error(`Response is not JSON. Status code: ${resp.status ?? 'no status code'}`)
}
} else {
throw e
}
}
if (body?.error !== undefined) throw new Error(body?.errorMessage)
return body
},
/**
* Java's stupid hashing method
* @param {Buffer|String} hash The hash data to stupidify
* @param {String} encoding Optional, passed to Buffer() if hash is a string
* @return {String} Stupidified hash
*/
mcHexDigest(hash: Buffer | String, encoding?: String): string {
if (!(hash instanceof Buffer)) {
hash = (Buffer as any).from(hash, encoding)
}
// check for negative hashes
const negative = (hash as any).readInt8(0) < 0
if (negative) performTwosCompliment(hash)
return (negative ? '-' : '') + hash.toString('hex').replace(/^0+/g, '')
},
callbackify(f: (...args: any[]) => any, maxParams: number) {
return function (...args: any[]) {
let cb: Function | undefined
let i: number = args.length
while (cb === undefined && i > 0) {
if (typeof args[i - 1] === 'function') {
cb = args[i - 1]
args[i - 1] = undefined
args[maxParams] = cb
break
}
i--
}
return f.call(this, ...args).then(
(r: any) => {
if (r[0] !== undefined) {
cb?.(undefined, ...r)
return r[r.length - 1]
} else {
cb?.(undefined, r)
return r
}
},
(err: unknown) => {
if (typeof cb === 'function') cb(err)
else throw err
}
)
}
}
}
/**
* Java's annoying hashing method.
* All credit to andrewrk
* https://gist.github.com/andrewrk/4425843
*/
function performTwosCompliment(buffer: any): void {
let carry = true
let newByte: number, value: number;
for (let i = buffer.length - 1; i >= 0; --i) {
value = buffer.readUInt8(i)
newByte = ~value & 0xff
if (carry) {
carry = newByte === 0xff
buffer.writeUInt8(carry ? 0 : newByte + 1, i)
} else {
buffer.writeUInt8(newByte, i)
}
}
}
utils.call = utils.callbackify(utils.call, 4)
export const call = utils.call;
export const mcHexDigest = utils.mcHexDigest;
export const callbackify = utils.callbackify;
export default utils;