import bent , { RequestFunction } from 'bent' ; import sharp from "sharp" ; import { Responses , Skin , Texture } from './types' ; import * as Endpoints from "./endpoints" ; /**
 * This class represents a player in Minecraft. It interacts with the
 * Mojang API (credit to wiki.vg for mapping out all the endpoints) to get
 * all the attributes in all the accessor methods.
 */ export class Player { private name : string | null ; private uuid : string | null ; public constructor ( name ? , uuid ? ) { this . name = name || null ; this . uuid = uuid || null ; } param { Texture } texture returns { Skin } public static parseTexture ( texture ) { let decoded = Buffer . from ( texture . value , 'base64' ) . toString ( 'utf-8' ) ; return JSON . parse ( decoded ) ; } link returns { Promise < string > } public async getUUID ( ) { if ( this . uuid != null ) return this . uuid ; else { const name = await this . getName ( ) ; const getJSON = bent ( 'json' ) as RequestFunction < Responses . UUID > ; const target = Endpoints . get . uuid . replace ( /({playername})/g , name ) ; const res = await getJSON ( target ) ; this . uuid = res . id ; return res . id ; } } returns { Promise < string > } public async getName ( ) { if ( this . name != null ) return this . name ; else { const profile = await this . getProfile ( ) ; this . name = profile . name ; return profile . name ; } } link returns { Promise < NameHistory > } public async getNameHistory ( ) { const getJSON = bent ( 'json' ) as RequestFunction < Responses . NameHistory > ; const uuid = await this . getUUID ( ) ; const target = Endpoints . get . nameHistory . replace ( /({uuid})/g , uuid ) ; return getJSON ( target ) ; } link returns { Promise < Profile > } public async getProfile ( ) { const getJSON = bent ( 'json' ) as RequestFunction < Responses . Profile > ; const uuid = await this . getUUID ( ) ; const name = await this . getName ( ) ; const target = Endpoints . get . profile . replace ( /({uuid})/g , uuid ) ; try { return await getJSON ( target ) ; } catch ( err ) { const texture = { 'timestamp' : 0 , 'profileId' : uuid , 'profileName' : name , 'signatureRequired' : false , 'textures' : { "SKIN" : { "url" : "http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b" } } } ; return { 'id' : uuid , 'name' : name , 'properties' : [ { "name" : "textures" , "value" : new Buffer ( JSON . stringify ( texture ) ) . toString ( 'base64' ) } ] } ; } } returns { Promise < Buffer > } throws public async getSkin ( ) { let profile = await this . getProfile ( ) ; if ( profile . properties . length >= 1 ) { let texture = profile . properties [ 0 ] ; let parsed = Player . parseTexture ( texture ) ; if ( parsed . textures . SKIN ) { const getBuffer = bent ( 'buffer' ) ; const target = new URL ( parsed . textures . SKIN . url ) ; target . protocol = 'https' ; return await getBuffer ( target . toString ( ) ) as Buffer ; } else { throw new Error ( 'No custom skin' ) ; } } else { throw new Error ( 'No custom skin' ) ; } } returns { Promise < Buffer > } public async getHead ( ) { const skin = await this . getSkin ( ) ; let image = sharp ( skin ) ; let head = image . extract ( { top : 8 , left : 8 , width : 8 , height : 8 , } ) . resize ( 200 , 200 , { kernel : sharp . kernel . nearest , } ) ; return new Promise ( ( resolve , reject ) => { head . toBuffer ( ( ( err , buffer ) => { if ( err ) reject ( err ) ; else { resolve ( buffer ) ; } } ) ) ; } ) ; } returns { Promise < string > } throws public async getSkinURL ( ) { let profile = await this . getProfile ( ) ; if ( profile . properties . length >= 1 ) { let texture = profile . properties [ 0 ] ; let parsed = Player . parseTexture ( texture ) ; if ( parsed . textures . SKIN ) { return parsed . textures . SKIN . url ; } else { throw new Error ( 'No custom skin' ) ; } } else { throw new Error ( 'No custom skin' ) ; } } }