UNPKG

@xmcl/user

Version:

Minecraft user related functions, including Yggdrasil authenticator, player skin fetcher, and Mojang security API

8 lines (7 loc) 46 kB
{ "version": 3, "sources": ["../offline.ts", "../../user-offline-uuid/index.ts", "../mojang.ts", "../yggdrasil.ts", "../microsoft.ts"], "sourcesContent": ["import { v4 } from 'uuid'\nimport { getOfflineUUID } from 'user-offline-uuid'\n\n/**\n * Random generate a new token by uuid v4. It can be client or auth token.\n * @returns a new token\n */\nexport function newToken() {\n return v4().replace(/-/g, '')\n}\n\nexport { getOfflineUUID }\n\n/**\n * Create an offline auth. It'll ensure the user game profile's `uuid` is the same for the same `username`.\n *\n * @param username The username you want to have in-game.\n */\nexport function offline(username: string, uuid?: string) {\n const id = (uuid || getOfflineUUID(username))\n const prof = {\n id,\n name: username,\n }\n return {\n accessToken: newToken(),\n clientToken: newToken(),\n selectedProfile: prof,\n availableProfiles: [prof],\n user: {\n id,\n username,\n },\n }\n}\n", "import { createHash } from 'crypto'\n\nexport function getOfflineUUID(username: string) {\n const md5Bytes = createHash('md5').update(`OfflinePlayer:${username}`).digest()\n md5Bytes[6] &= 0x0f /* clear version */\n md5Bytes[6] |= 0x30 /* set to version 3 */\n md5Bytes[8] &= 0x3f /* clear variant */\n md5Bytes[8] |= 0x80 /* set to IETF variant */\n return md5Bytes.toString('hex').replace(/(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})/, '$1-$2-$3-$4-$5')\n}\n", "/* eslint-disable @typescript-eslint/no-redeclare */\nimport { fetch, FormData } from 'undici'\n\n/**\n * Users defined question when they register this account\n *\n * The question id, content mapping is:\n *\n * 1. What is your favorite pet's name?\n * 2. What is your favorite movie?\n * 3. What is your favorite author's last name?\n * 4. What is your favorite artist's last name?\n * 5. What is your favorite actor's last name?\n * 6. What is your favorite activity?\n * 7. What is your favorite restaurant?\n * 8. What is the name of your favorite cartoon?\n * 9. What is the name of the first school you attended?\n * 10. What is the last name of your favorite teacher?\n * 11. What is your best friend's first name?\n * 12. What is your favorite cousin's name?\n * 13. What was the first name of your first girl/boyfriend?\n * 14. What was the name of your first stuffed animal?\n * 15. What is your mother's middle name?\n * 16. What is your father's middle name?\n * 17. What is your oldest sibling's middle name?\n * 18. In what city did your parents meet?\n * 19. In what hospital were you born?\n * 20. What is your favorite team?\n * 21. How old were you when you got your first computer?\n * 22. How old were you when you got your first gaming console?\n * 23. What was your first video game?\n * 24. What is your favorite card game?\n * 25. What is your favorite board game?\n * 26. What was your first gaming console?\n * 27. What was the first book you ever read?\n * 28. Where did you go on your first holiday?\n * 29. In what city does your grandmother live?\n * 30. In what city does your grandfather live?\n * 31. What is your grandmother's first name?\n * 32. What is your grandfather's first name?\n * 33. What is your least favorite food?\n * 34. What is your favorite ice cream flavor?\n * 35. What is your favorite ice cream flavor?\n * 36. What is your favorite place to visit?\n * 37. What is your dream job?\n * 38. What color was your first pet?\n * 39. What is your lucky number?s\n *\n */\nexport interface MojangChallenge {\n readonly answer: { id: number }\n readonly question: { id: number; question: string }\n}\n\nexport interface MojangChallengeResponse {\n id: number\n answer: string\n}\nexport interface MinecraftProfileResponse {\n id: string // the real uuid of the account, woo\n name: string // the mc user name of the account\n skins: [{\n id: string\n state: 'ACTIVE' | 'string'\n url: string\n variant: 'CLASSIC' | string\n alias: 'STEVE' | string\n }]\n capes: [{\n id: string\n state: 'ACTIVE' | string\n url: string\n }]\n}\n\nexport interface MinecraftOwnershipResponse {\n /**\n * If the account doesn't own the game, the items array will be empty.\n */\n items: Array<{\n name: 'product_minecraft' | 'game_minecraft'\n /**\n * jwt signature\n */\n signature: string\n }>\n /**\n * jwt signature\n */\n signature: string\n keyId: string\n}\n\nexport interface MinecraftProfileErrorResponse {\n path: '/minecraft/profile'\n errorType: 'NOT_FOUND' | string\n error: string | 'NOT_FOUND'\n errorMessage: string\n developerMessage: string\n}\nexport interface MojangSkin {\n id: string\n state: 'ACTIVE' | 'INACTIVE'\n url: string\n variant: 'SLIM' | 'CLASSIC'\n}\nexport interface MojangCape {\n id: string\n state: 'ACTIVE' | 'INACTIVE'\n url: string\n /**\n * Capes name\n */\n alias: string\n}\n\nexport interface MicrosoftMinecraftProfile {\n id: string\n name: string\n skins: MojangSkin[]\n capes: MojangCape[]\n}\n\nexport interface NameChangeInformation {\n changedAt: string\n createdAt: string\n nameChangeAllowed: boolean\n}\n\nexport enum NameAvailability {\n DUPLICATE = 'DUPLICATE',\n AVAILABLE = 'AVAILABLE',\n NOT_ALLOWED = 'NOT_ALLOWED',\n}\n\nexport class SetNameError extends Error {\n public path: string\n public errorType: string\n public error: string\n public details: object\n public errorMessage: string\n public developerMessage: string\n\n constructor(message: string, err: any) {\n super(message)\n this.name = 'SetNameError'\n this.path = err.path\n this.errorType = err.errorType\n this.error = err.error\n this.details = err.details\n this.errorMessage = err.errorMessage\n this.developerMessage = err.developerMessage\n }\n}\n\nexport class SetSkinError extends Error {\n public path: string\n public errorType: string\n public error: string\n public details: object\n public errorMessage: string\n public developerMessage: string\n\n constructor(message: string, err: any) {\n super(message)\n this.name = 'SetSkinError'\n this.path = err.path\n this.errorType = err.errorType\n this.error = err.error\n this.details = err.details\n this.errorMessage = err.errorMessage\n this.developerMessage = err.developerMessage\n }\n}\n\nexport class MojangError extends Error {\n public path: string\n public errorMessage: string\n public developerMessage: string\n\n constructor(err: any) {\n super(err.errorMessage)\n this.path = err.path\n this.errorMessage = err.errorMessage\n this.developerMessage = err.developerMessage\n Object.assign(this, err)\n }\n}\n\nexport class UnauthorizedError extends MojangError {\n name = 'UnauthorizedError'\n constructor(err: any) {\n super(err)\n }\n}\n\nexport class ProfileNotFoundError extends MojangError {\n name = 'ProfileNotFoundError'\n\n constructor(err: any) {\n super(err)\n }\n}\n\nexport interface MojangClientOptions {\n fetch?: typeof fetch\n}\n\n/**\n * The mojang api client. Please referece https://wiki.vg/Mojang_API.\n *\n * All the apis need user to authenticate the access token from microsoft.\n * @see {@link MicrosoftAuthenticator}\n */\nexport class MojangClient {\n private fetch: typeof fetch\n\n constructor(options?: MojangClientOptions) {\n this.fetch = options?.fetch || fetch\n }\n\n async setName(name: string, token: string, signal?: AbortSignal) {\n const resp = await this.fetch(`https://api.minecraftservices.com/minecraft/profile/name/${name}`, {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n signal,\n })\n switch (resp.status) {\n case 200: return await resp.json() as MicrosoftMinecraftProfile\n case 400: throw new SetNameError('Name is unavailable (Either taken or has not become available)', await resp.json())\n case 403: throw new SetNameError('Name is unavailable (Either taken or has not become available)', await resp.json())\n case 401: throw new SetNameError('Unauthorized (Bearer token expired or is not correct)', await resp.json())\n case 429: throw new SetNameError('Too many requests sent', await resp.json())\n case 500: throw new SetNameError('Timed out (API lagged out and could not respond)', await resp.json())\n }\n throw new SetNameError('Unknown error', await resp.json())\n }\n\n async getNameChangeInformation(token: string) {\n const resp = await this.fetch('https://api.minecraftservices.com/minecraft/profile/namechange', {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n return await resp.json() as NameChangeInformation\n }\n\n async checkNameAvailability(name: string, token: string, signal?: AbortSignal): Promise<NameAvailability> {\n const resp = await this.fetch(`https://api.minecraftservices.com/minecraft/profile/name/${name}/available`, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n signal,\n })\n const result = await resp.json() as any\n return result.status\n }\n\n async getProfile(token: string, signal?: AbortSignal): Promise<MicrosoftMinecraftProfile> {\n const resp = await this.fetch('https://api.minecraftservices.com/minecraft/profile', {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n signal,\n })\n if (resp.headers.get('content-type')?.toLocaleLowerCase() !== 'application/json') {\n throw new Error(await resp.text())\n }\n const json = await resp.json() as any\n if (resp.ok) {\n return json as MicrosoftMinecraftProfile\n } else if (json.error === 'NOT_FOUND') {\n throw new ProfileNotFoundError(json)\n } else if (resp.status === 401) {\n throw new UnauthorizedError(json)\n }\n throw Object.assign(new Error('Unknown Error'), json)\n }\n\n async setSkin(fileName: string, skin: string | Buffer, variant: 'slim' | 'classic', token: string, signal?: AbortSignal) {\n const body = typeof skin === 'string' ? JSON.stringify({ url: skin, variant }) : getSkinFormData(skin, fileName, variant)\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n }\n\n if (typeof body === 'string') {\n headers['Content-Type'] = 'application/json'\n }\n\n const resp = await this.fetch('https://api.minecraftservices.com/minecraft/profile/skins', {\n method: 'POST',\n headers,\n body,\n signal,\n })\n\n const profileResponse: MinecraftProfileResponse | MinecraftProfileErrorResponse = await resp.json() as any\n\n if (resp.status === 401) {\n throw new UnauthorizedError(await resp.json())\n }\n\n if ('error' in profileResponse || 'errorMessage' in profileResponse) {\n throw new SetSkinError(`Fail to set skin ${profileResponse.errorMessage}`, profileResponse)\n }\n\n return profileResponse\n }\n\n async resetSkin(token: string, signal?: AbortSignal) {\n const resp = await this.fetch('https://api.minecraftservices.com/minecraft/profile/skins/active', {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n signal,\n })\n if (resp.status === 401) {\n throw new UnauthorizedError(await resp.json())\n }\n }\n\n async hideCape(token: string, signal?: AbortSignal) {\n const resp = await this.fetch('https://api.minecraftservices.com/minecraft/profile/capes/active', {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n signal,\n })\n if (resp.status === 401) {\n throw new UnauthorizedError(await resp.json())\n }\n }\n\n async showCape(capeId: string, token: string, signal?: AbortSignal) {\n const resp = await this.fetch('https://api.minecraftservices.com/minecraft/profile/capes/active', {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ capeId }),\n signal,\n })\n if (resp.status === 401) {\n throw new UnauthorizedError(await resp.json())\n }\n if (resp.status === 400) {\n throw new Error()\n }\n const profile = await resp.json() as MicrosoftMinecraftProfile\n return profile\n }\n\n async verifySecurityLocation(token: string, signal?: AbortSignal) {\n const resp = await this.fetch('https://api.mojang.com/user/security/location', {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n signal,\n })\n\n if (resp.status === 204) {\n return true\n }\n return false\n }\n\n async getSecurityChallenges(token: string) {\n const resp = await this.fetch('https://api.mojang.com/user/security/challenges', {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n\n if (resp.status === 401) {\n throw new UnauthorizedError(await resp.json())\n }\n return await resp.json() as MojangChallenge[]\n }\n\n async submitSecurityChallenges(answers: MojangChallengeResponse[], token: string) {\n const resp = await this.fetch('https://api.mojang.com/user/security/location', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(answers),\n })\n\n if (resp.status === 204) {\n return\n }\n if (resp.status === 401) {\n throw new UnauthorizedError(await resp.json())\n }\n throw new Error()\n }\n\n /**\n * Return the owner ship list of the player with those token.\n */\n async checkGameOwnership(token: string, signal?: AbortSignal) {\n const mcResponse = await this.fetch('https://api.minecraftservices.com/entitlements/mcstore', {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n signal,\n })\n\n if (mcResponse.status === 401) {\n throw new UnauthorizedError(await mcResponse.text())\n }\n\n if (!mcResponse.ok || mcResponse.headers.get('content-type')?.toLocaleLowerCase() !== 'application/json') {\n throw new Error(await mcResponse.text())\n }\n\n const result = await mcResponse.json() as MinecraftOwnershipResponse\n\n return result\n }\n}\n\nfunction getSkinFormData(buf: Buffer, fileName: string, variant: 'slim' | 'classic') {\n const form = new FormData()\n form.append('variant', variant)\n const file = new File([buf], fileName, { type: 'image/png' })\n form.append('file', file)\n return form\n}\n", "/* eslint-disable n/no-unsupported-features/node-builtins */\nimport { GameProfile, GameProfileWithProperties } from './gameProfile'\n\n/**\n * The auth response format.\n *\n * Please refer https://wiki.vg/Authentication\n */\nexport interface YggrasilAuthentication {\n /**\n * hexadecimal or JSON-Web-Token (unconfirmed) [The normal accessToken can be found in the payload of the JWT (second by '.' separated part as Base64 encoded JSON object), in key \"yggt\"]\n */\n accessToken: string\n /**\n * identical to the one received\n */\n clientToken: string\n /**\n * only present if the agent field was received\n */\n availableProfiles: GameProfile[]\n /**\n * only present if the agent field was received\n */\n selectedProfile: GameProfile\n /**\n * only present if requestUser was true in the request payload\n */\n user?: {\n id: string\n username: string\n email?: string\n registerIp?: string\n migratedFrom?: string\n migratedAt?: number\n registeredAt?: number\n passwordChangedAt?: number\n dateOfBirth?: number\n suspended?: boolean\n blocked?: boolean\n secured?: boolean\n migrated?: boolean\n emailVerified?: boolean\n legacyUser?: boolean\n verifiedByParent?: boolean\n properties?: object[]\n }\n}\n\nexport interface YggdrasilClientOptions {\n headers?: Record<string, string>\n fetch?: typeof fetch\n FormData?: typeof FormData\n File?: typeof File\n}\n\nexport interface ProfileLookupException {\n /**\n * - statusCode=204 -> error=\"NoPlayerFound\"\n * - statusCode=400 -> error=\"IllegalArgumentException\" (parsed from body)\n * - statusCode=other -> error=statusCode.toString()\n */\n error: 'NoPlayerFoundException' | 'IllegalArgumentException' | 'GeneralException'\n errorMessage?: string | 'Invalid timestamp.'\n statusCode?: number\n statusMessage?: string\n}\n\nexport interface SetTextureOption {\n accessToken: string\n uuid: string\n type: 'skin' | 'cape' | 'elytra'\n texture?: {\n url: string\n metadata?: { model?: 'slim' | 'steve';[key: string]: any }\n } | {\n data: Uint8Array\n metadata?: { model?: 'slim' | 'steve';[key: string]: any }\n }\n}\n\nexport class YggdrasilError extends Error {\n error: string\n errorMessage: string\n cause?: string\n\n constructor(readonly statusCode: number, message: string, o?: any) {\n super(message)\n this.name = 'YggdrasilError'\n this.error = o?.error\n this.errorMessage = o?.errorMessage\n this.cause = o?.cause\n }\n}\n\nexport class YggdrasilClient {\n protected headers: Record<string, string>\n protected fetch: typeof fetch\n protected FormData: typeof FormData\n protected File: typeof File\n\n /**\n * Create client for official-like api endpoint\n * @param api The official-like api endpoint\n */\n constructor(public api: string, options?: YggdrasilClientOptions) {\n this.headers = options?.headers ?? {}\n this.fetch = options?.fetch || fetch\n this.FormData = options?.FormData || FormData\n this.File = options?.File || File\n }\n\n async validate(accessToken: string, clientToken: string, signal?: AbortSignal) {\n const response = await this.fetch(this.api + '/validate', {\n method: 'POST',\n body: JSON.stringify({ accessToken, clientToken }),\n headers: {\n ...this.headers,\n 'content-type': 'application/json; charset=utf-8',\n },\n signal,\n })\n return response.ok\n }\n\n async invalidate(accessToken: string, clientToken: string, signal?: AbortSignal) {\n return await this.fetch(this.api + '/invalidate', {\n method: 'POST',\n body: JSON.stringify({ accessToken, clientToken }),\n headers: {\n ...this.headers,\n 'content-type': 'application/json; charset=utf-8',\n },\n signal,\n }).then((s) => s.ok)\n }\n\n async login({ username, password, clientToken, requestUser }: { username: string; password: string; clientToken: string; requestUser?: boolean }, signal?: AbortSignal) {\n const response = await this.fetch(this.api + '/authenticate', {\n method: 'POST',\n body: JSON.stringify({\n agent: { name: 'Minecraft', version: 1 },\n requestUser: typeof requestUser === 'boolean' ? requestUser : false,\n username,\n password,\n clientToken,\n }),\n headers: {\n ...this.headers,\n 'content-type': 'application/json; charset=utf-8',\n },\n signal,\n })\n\n if (response.status >= 400) {\n const body = await response.text()\n throw new YggdrasilError(response.status, response.status + ':' + body, response.headers.get('content-type')?.startsWith('application/json') ? JSON.parse(body) : undefined)\n }\n\n const authentication: YggrasilAuthentication = await response.json() as YggrasilAuthentication\n return authentication\n }\n\n async refresh({ accessToken, requestUser, clientToken }: { accessToken: string; clientToken: string; requestUser?: boolean }, signal?: AbortSignal) {\n const response = await this.fetch(this.api + '/refresh', {\n method: 'POST',\n body: JSON.stringify({\n accessToken,\n clientToken,\n requestUser: typeof requestUser === 'boolean' ? requestUser : false,\n }),\n headers: {\n ...this.headers,\n 'content-type': 'application/json; charset=utf-8',\n },\n signal,\n })\n\n if (response.status >= 400) {\n const body = await response.text()\n throw new YggdrasilError(response.status, response.status + ':' + body, response.headers.get('content-type')?.startsWith('application/json') ? JSON.parse(body) : undefined)\n }\n\n const authentication = await response.json() as YggrasilAuthentication\n return authentication\n }\n}\n\n/**\n * The texture structure for yggdrasil API\n */\nexport interface YggdrasilTexturesInfo {\n /**\n * java time in ms\n */\n timestamp: number\n /**\n * player name\n */\n profileName: string\n /**\n * player id\n */\n profileId: string\n textures: {\n SKIN?: YggdrasilTexture\n CAPE?: YggdrasilTexture\n ELYTRA?: YggdrasilTexture\n }\n}\n\n/**\n * The data structure that hold the texture\n */\nexport interface YggdrasilTexture {\n url: string\n metadata?: { model?: 'slim' | 'steve';[key: string]: any }\n}\n\nexport function isTextureSlim(o: YggdrasilTexture) {\n return o.metadata ? o.metadata.model === 'slim' : false\n}\n\nexport function getTextureType(o: YggdrasilTexture) {\n return isTextureSlim(o) ? 'slim' : 'steve'\n}\n\nexport class YggdrasilThirdPartyClient extends YggdrasilClient {\n public profileApi: string\n public textureApi: string\n /**\n * Create thirdparty (authlib-injector) style client\n * @param api The api url following https://github.com/yushijinhun/authlib-injector/wiki/Yggdrasil-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%8A%80%E6%9C%AF%E8%A7%84%E8%8C%83\n * @param clientToken\n * @param dispatcher\n */\n constructor(\n api: string,\n options?: YggdrasilClientOptions,\n ) {\n super(api + '/authserver', options)\n // eslint-disable-next-line no-template-curly-in-string\n this.profileApi = api + '/sessionserver/session/minecraft/profile/${uuid}'\n // this.profileApi = api + '/yggdrasil/sessionserver/session/minecraft/profile/${uuid}'\n // eslint-disable-next-line no-template-curly-in-string\n this.textureApi = api + '/api/user/profile/${uuid}/${type}'\n }\n\n async lookup(uuid: string, unsigned = true, signal?: AbortSignal) {\n // eslint-disable-next-line no-template-curly-in-string\n const url = new URL(this.profileApi.replace('${uuid}', uuid))\n url.searchParams.append('unsigned', unsigned ? 'true' : 'false')\n const response = await this.fetch(url.toString(), {\n method: 'GET',\n headers: this.headers,\n signal,\n })\n if (response.status !== 200) {\n const body = await response.text()\n throw new YggdrasilError(response.status, response.status + ':' + body, response.headers.get('content-type')?.startsWith('application/json') ? JSON.parse(body) : undefined)\n }\n const o = await response.json() as any\n if (o.properties && o.properties instanceof Array) {\n const properties = o.properties as Array<{ name: string; value: string; signature: string }>\n const to: { [key: string]: string } = {}\n for (const prop of properties) {\n // if (prop.signature && api.publicKey && !await verify(prop.value, prop.signature, api.publicKey)) {\n // console.warn(`Discard corrupted prop ${prop.name}: ${prop.value} as the signature mismatched!`)\n // } else {\n to[prop.name] = prop.value\n // }\n }\n o.properties = to\n }\n return o as GameProfileWithProperties\n }\n\n async setTexture(options: SetTextureOption, signal?: AbortSignal) {\n // eslint-disable-next-line no-template-curly-in-string\n const url = new URL(this.textureApi.replace('${uuid}', options.uuid).replace('${type}', options.type))\n\n // eslint-disable-next-line no-undef\n const requestOptions: RequestInit = {\n headers: {\n ...this.headers,\n Authorization: `Bearer ${options.accessToken}`,\n },\n signal,\n }\n if (!options.texture) {\n // delete texture\n requestOptions.method = 'DELETE'\n } else if ('data' in options.texture) {\n requestOptions.method = 'PUT'\n // upload texture\n const form = new this.FormData()\n form.append('model', options.texture.metadata?.model || 'steve')\n form.append('file', new this.File([options.texture.data], 'Steve.png', { type: 'image/png' }))\n requestOptions.body = form\n } else if ('url' in options.texture) {\n // set texture\n requestOptions.method = 'POST'\n url.searchParams.append('model', options.texture.metadata?.model || '')\n url.searchParams.append('url', options.texture.url)\n } else {\n throw new TypeError('Illegal Option Format!')\n }\n\n const response = await this.fetch(url.toString(), requestOptions)\n if (response.status === 401) {\n if (response.headers.get('content-type') === 'application/json') {\n const body = await response.json() as any\n throw new YggdrasilError(response.status, response.status.toString(), {\n error: body.error ?? 'Unauthorized',\n errorMessage: body.errorMessage ?? 'Unauthorized',\n })\n } else {\n const body = await response.text()\n throw new YggdrasilError(response.status, response.status + ':' + body, {\n error: 'Unauthorized',\n errorMessage: 'Unauthorized: ' + body,\n })\n }\n }\n if (response.status >= 400) {\n const body = await response.text()\n throw new YggdrasilError(response.status, response.status + ':' + body, {\n error: 'SetSkinFailed',\n errorMessage: 'Fail to set skin ' + body,\n })\n }\n }\n}\n", "/* eslint-disable n/no-unsupported-features/node-builtins */\n/* eslint-disable camelcase */\nexport interface XBoxResponse {\n IssueInstant: string\n NotAfter: string\n Token: string\n DisplayClaims: {\n xui: [\n {\n /**\n * gamer tag\n */\n gtg: string\n /**\n * user id\n */\n xid: string\n uhs: string\n },\n ]\n }\n}\n\nexport interface XBoxGameProfileResponse {\n profileUsers: [{\n id: string\n hostId: string | null\n settings: [{\n 'id': 'Gamertag'\n 'value': string\n }, {\n 'id': 'PublicGamerpic'\n 'value': string\n }]\n isSponsoredUser: boolean\n }]\n}\n\nexport interface MinecraftAuthResponse {\n username: string // this is not the uuid of the account\n roles: []\n access_token: string // jwt, your good old minecraft access token\n token_type: 'Bearer'\n expires_in: number\n}\n\nexport interface MicrosoftAuthenticatorOptions {\n fetch?: typeof fetch\n}\n\n/**\n * The microsoft authenticator for Minecraft (Xbox) account.\n */\nexport class MicrosoftAuthenticator {\n fetch: typeof fetch\n\n constructor(options: MicrosoftAuthenticatorOptions) {\n this.fetch = options.fetch || fetch\n }\n\n /**\n * Authenticate with xbox live by ms oauth access token\n * @param oauthAccessToken The oauth access token\n */\n async authenticateXboxLive(oauthAccessToken: string, signal?: AbortSignal) {\n const xblResponse = await this.fetch('https://user.auth.xboxlive.com/user/authenticate', {\n method: 'POST',\n body: JSON.stringify({\n Properties: {\n AuthMethod: 'RPS',\n SiteName: 'user.auth.xboxlive.com',\n RpsTicket: `d=${oauthAccessToken}`,\n },\n RelyingParty: 'http://auth.xboxlive.com',\n TokenType: 'JWT',\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n signal,\n })\n\n if (xblResponse.status !== 200) {\n throw new Error(`Failed to authenticate with xbox live, status code: ${xblResponse.status}: ${await xblResponse.text()}}`)\n }\n\n const result = await xblResponse.json() as XBoxResponse\n\n return result\n }\n\n /**\n * Authorize the xbox live. It will get the xsts token in response.\n * @param xblResponseToken The {@link XBoxResponse.Token}\n */\n async authorizeXboxLive(xblResponseToken: string, relyingParty: 'rp://api.minecraftservices.com/' | 'http://xboxlive.com' = 'rp://api.minecraftservices.com/', signal?: AbortSignal) {\n const xstsResponse = await this.fetch('https://xsts.auth.xboxlive.com/xsts/authorize', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n Properties: {\n SandboxId: 'RETAIL',\n UserTokens: [xblResponseToken],\n },\n RelyingParty: relyingParty,\n TokenType: 'JWT',\n }),\n signal,\n })\n\n if (xstsResponse.status !== 200) {\n const errText = await xstsResponse.text()\n let errObj = {} as any\n try {\n errObj = JSON.parse(errText)\n } catch (e) {}\n throw Object.assign(new Error(`Failed to authorize with xbox live, status code: ${xstsResponse.status}: ${errText}}`), errObj)\n }\n\n const result = await xstsResponse.json() as XBoxResponse\n\n return result\n }\n\n /**\n * Get xbox user profile, including **username** and **avatar**.\n *\n * You can find the parameters from the {@link XBoxResponse}.\n *\n * @param xuid The `xuid` in a {@link XBoxResponse.DisplayClaims}\n * @param uhs The `uhs` in a {@link XBoxResponse.DisplayClaims}\n * @param xstsToken The {@link XBoxResponse.Token}\n * @returns The user game profile.\n */\n async getXboxGameProfile(xuid: string, uhs: string, xstsToken: string, signal?: AbortSignal) {\n const url = new URL(`https://profile.xboxlive.com/users/xuid(${xuid})/profile/settings`)\n url.searchParams.append('settings', ['PublicGamerpic', 'Gamertag'].join(','))\n const response = await this.fetch(url.toString(), {\n headers: {\n 'x-xbl-contract-version': '2',\n 'content-type': 'application/json',\n Authorization: `XBL3.0 x=${uhs};${xstsToken}`,\n },\n signal,\n })\n\n if (response.status !== 200) {\n throw new Error(`Failed to get xbox game profile, status code: ${response.status}: ${await response.text()}}`)\n }\n\n const result = await response.json() as XBoxGameProfileResponse\n return result\n }\n\n /**\n * Acquire both Minecraft and xbox token and xbox game profile.\n * You can use the xbox token to login Minecraft by {@link loginMinecraftWithXBox}.\n *\n * This method is the composition of calling\n * - {@link authenticateXboxLive}\n * - {@link authorizeXboxLive} to `rp://api.minecraftservices.com/`\n * - {@link authorizeXboxLive} to `http://xboxlive.com`\n * - {@link getXboxGameProfile}\n *\n * You can call them individually if you want a more detailed control.\n *\n * @param oauthAccessToken The microsoft access token\n * @param signal The abort signal\n * @returns The object contain xstsResponse (minecraft xbox token) and xbox game profile\n */\n async acquireXBoxToken(oauthAccessToken: string, signal?: AbortSignal) {\n const xblResponse: XBoxResponse = await this.authenticateXboxLive(oauthAccessToken, signal)\n const minecraftXstsResponse: XBoxResponse = await this.authorizeXboxLive(xblResponse.Token, 'rp://api.minecraftservices.com/', signal)\n const xstsResponse: XBoxResponse = await this.authorizeXboxLive(xblResponse.Token, 'http://xboxlive.com', signal)\n\n return { minecraftXstsResponse, liveXstsResponse: xstsResponse }\n }\n\n /**\n * This will return the response with Minecraft access token!\n *\n * This access token allows us to launch the game, but, we haven't actually checked if the account owns the game. Everything until here works with a normal Microsoft account!\n *\n * @param uhs uhs from {@link XBoxResponse} of {@link acquireXBoxToken}\n * @param xstsToken You need to get this token from {@link acquireXBoxToken}\n */\n async loginMinecraftWithXBox(uhs: string, xstsToken: string, signal?: AbortSignal) {\n const mcResponse = await this.fetch('https://api.minecraftservices.com/authentication/login_with_xbox', {\n method: 'POST',\n body: JSON.stringify({\n identityToken: `XBL3.0 x=${uhs};${xstsToken}`,\n }),\n headers: {\n 'content-type': 'application/json',\n },\n signal,\n })\n\n if (mcResponse.status !== 200) {\n throw new Error(`Failed to login minecraft with xbox, status code: ${mcResponse.status}: ${await mcResponse.text()}}`)\n }\n\n const result = await mcResponse.json() as MinecraftAuthResponse\n\n return result\n }\n}\n"], "mappings": ";AAAA,SAAS,UAAU;;;ACAnB,SAAS,kBAAkB;AAEpB,SAAS,eAAe,UAAkB;AAC/C,QAAM,WAAW,WAAW,KAAK,EAAE,OAAO,iBAAiB,UAAU,EAAE,OAAO;AAC9E,WAAS,CAAC,KAAK;AACf,WAAS,CAAC,KAAK;AACf,WAAS,CAAC,KAAK;AACf,WAAS,CAAC,KAAK;AACf,SAAO,SAAS,SAAS,KAAK,EAAE,QAAQ,wCAAwC,gBAAgB;AAClG;;;ADFO,SAAS,WAAW;AACzB,SAAO,GAAG,EAAE,QAAQ,MAAM,EAAE;AAC9B;AASO,SAAS,QAAQ,UAAkB,MAAe;AACvD,QAAM,KAAM,QAAQ,eAAe,QAAQ;AAC3C,QAAM,OAAO;AAAA,IACX;AAAA,IACA,MAAM;AAAA,EACR;AACA,SAAO;AAAA,IACL,aAAa,SAAS;AAAA,IACtB,aAAa,SAAS;AAAA,IACtB,iBAAiB;AAAA,IACjB,mBAAmB,CAAC,IAAI;AAAA,IACxB,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AEjCA,SAAS,SAAAA,QAAO,YAAAC,iBAAgB;AAgIzB,IAAK,mBAAL,kBAAKC,sBAAL;AACL,EAAAA,kBAAA,eAAY;AACZ,EAAAA,kBAAA,eAAY;AACZ,EAAAA,kBAAA,iBAAc;AAHJ,SAAAA;AAAA,GAAA;AAML,IAAM,eAAN,cAA2B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEP,YAAY,SAAiB,KAAU;AACrC,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO,IAAI;AAChB,SAAK,YAAY,IAAI;AACrB,SAAK,QAAQ,IAAI;AACjB,SAAK,UAAU,IAAI;AACnB,SAAK,eAAe,IAAI;AACxB,SAAK,mBAAmB,IAAI;AAAA,EAC9B;AACF;AAEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEP,YAAY,SAAiB,KAAU;AACrC,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO,IAAI;AAChB,SAAK,YAAY,IAAI;AACrB,SAAK,QAAQ,IAAI;AACjB,SAAK,UAAU,IAAI;AACnB,SAAK,eAAe,IAAI;AACxB,SAAK,mBAAmB,IAAI;AAAA,EAC9B;AACF;AAEO,IAAM,cAAN,cAA0B,MAAM;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EAEP,YAAY,KAAU;AACpB,UAAM,IAAI,YAAY;AACtB,SAAK,OAAO,IAAI;AAChB,SAAK,eAAe,IAAI;AACxB,SAAK,mBAAmB,IAAI;AAC5B,WAAO,OAAO,MAAM,GAAG;AAAA,EACzB;AACF;AAEO,IAAM,oBAAN,cAAgC,YAAY;AAAA,EACjD,OAAO;AAAA,EACP,YAAY,KAAU;AACpB,UAAM,GAAG;AAAA,EACX;AACF;AAEO,IAAM,uBAAN,cAAmC,YAAY;AAAA,EACpD,OAAO;AAAA,EAEP,YAAY,KAAU;AACpB,UAAM,GAAG;AAAA,EACX;AACF;AAYO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EAER,YAAY,SAA+B;AACzC,SAAK,SAAQ,mCAAS,UAASF;AAAA,EACjC;AAAA,EAEA,MAAM,QAAQ,MAAc,OAAe,QAAsB;AAC/D,UAAM,OAAO,MAAM,KAAK,MAAM,4DAA4D,QAAQ;AAAA,MAChG,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,CAAC;AACD,YAAQ,KAAK,QAAQ;AAAA,MACnB,KAAK;AAAK,eAAO,MAAM,KAAK,KAAK;AAAA,MACjC,KAAK;AAAK,cAAM,IAAI,aAAa,kEAAkE,MAAM,KAAK,KAAK,CAAC;AAAA,MACpH,KAAK;AAAK,cAAM,IAAI,aAAa,kEAAkE,MAAM,KAAK,KAAK,CAAC;AAAA,MACpH,KAAK;AAAK,cAAM,IAAI,aAAa,yDAAyD,MAAM,KAAK,KAAK,CAAC;AAAA,MAC3G,KAAK;AAAK,cAAM,IAAI,aAAa,0BAA0B,MAAM,KAAK,KAAK,CAAC;AAAA,MAC5E,KAAK;AAAK,cAAM,IAAI,aAAa,oDAAoD,MAAM,KAAK,KAAK,CAAC;AAAA,IACxG;AACA,UAAM,IAAI,aAAa,iBAAiB,MAAM,KAAK,KAAK,CAAC;AAAA,EAC3D;AAAA,EAEA,MAAM,yBAAyB,OAAe;AAC5C,UAAM,OAAO,MAAM,KAAK,MAAM,kEAAkE;AAAA,MAC9F,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,IACF,CAAC;AACD,WAAO,MAAM,KAAK,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,sBAAsB,MAAc,OAAe,QAAiD;AACxG,UAAM,OAAO,MAAM,KAAK,MAAM,4DAA4D,kBAAkB;AAAA,MAC1G,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAM,SAAS,MAAM,KAAK,KAAK;AAC/B,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAM,WAAW,OAAe,QAA0D;AAtQ5F;AAuQI,UAAM,OAAO,MAAM,KAAK,MAAM,uDAAuD;AAAA,MACnF,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAI,UAAK,QAAQ,IAAI,cAAc,MAA/B,mBAAkC,yBAAwB,oBAAoB;AAChF,YAAM,IAAI,MAAM,MAAM,KAAK,KAAK,CAAC;AAAA,IACnC;AACA,UAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,QAAI,KAAK,IAAI;AACX,aAAO;AAAA,IACT,WAAW,KAAK,UAAU,aAAa;AACrC,YAAM,IAAI,qBAAqB,IAAI;AAAA,IACrC,WAAW,KAAK,WAAW,KAAK;AAC9B,YAAM,IAAI,kBAAkB,IAAI;AAAA,IAClC;AACA,UAAM,OAAO,OAAO,IAAI,MAAM,eAAe,GAAG,IAAI;AAAA,EACtD;AAAA,EAEA,MAAM,QAAQ,UAAkB,MAAuB,SAA6B,OAAe,QAAsB;AACvH,UAAM,OAAO,OAAO,SAAS,WAAW,KAAK,UAAU,EAAE,KAAK,MAAM,QAAQ,CAAC,IAAI,gBAAgB,MAAM,UAAU,OAAO;AACxH,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU;AAAA,IAC3B;AAEA,QAAI,OAAO,SAAS,UAAU;AAC5B,cAAQ,cAAc,IAAI;AAAA,IAC5B;AAEA,UAAM,OAAO,MAAM,KAAK,MAAM,6DAA6D;AAAA,MACzF,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,kBAA4E,MAAM,KAAK,KAAK;AAElG,QAAI,KAAK,WAAW,KAAK;AACvB,YAAM,IAAI,kBAAkB,MAAM,KAAK,KAAK,CAAC;AAAA,IAC/C;AAEA,QAAI,WAAW,mBAAmB,kBAAkB,iBAAiB;AACnE,YAAM,IAAI,aAAa,oBAAoB,gBAAgB,gBAAgB,eAAe;AAAA,IAC5F;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,OAAe,QAAsB;AACnD,UAAM,OAAO,MAAM,KAAK,MAAM,oEAAoE;AAAA,MAChG,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,KAAK,WAAW,KAAK;AACvB,YAAM,IAAI,kBAAkB,MAAM,KAAK,KAAK,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,OAAe,QAAsB;AAClD,UAAM,OAAO,MAAM,KAAK,MAAM,oEAAoE;AAAA,MAChG,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,KAAK,WAAW,KAAK;AACvB,YAAM,IAAI,kBAAkB,MAAM,KAAK,KAAK,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,QAAgB,OAAe,QAAsB;AAClE,UAAM,OAAO,MAAM,KAAK,MAAM,oEAAoE;AAAA,MAChG,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,QACzB,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,OAAO,CAAC;AAAA,MAC/B;AAAA,IACF,CAAC;AACD,QAAI,KAAK,WAAW,KAAK;AACvB,YAAM,IAAI,kBAAkB,MAAM,KAAK,KAAK,CAAC;AAAA,IAC/C;AACA,QAAI,KAAK,WAAW,KAAK;AACvB,YAAM,IAAI,MAAM;AAAA,IAClB;AACA,UAAM,UAAU,MAAM,KAAK,KAAK;AAChC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,uBAAuB,OAAe,QAAsB;AAChE,UAAM,OAAO,MAAM,KAAK,MAAM,iDAAiD;AAAA,MAC7E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,KAAK,WAAW,KAAK;AACvB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,sBAAsB,OAAe;AACzC,UAAM,OAAO,MAAM,KAAK,MAAM,mDAAmD;AAAA,MAC/E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,IACF,CAAC;AAED,QAAI,KAAK,WAAW,KAAK;AACvB,YAAM,IAAI,kBAAkB,MAAM,KAAK,KAAK,CAAC;AAAA,IAC/C;AACA,WAAO,MAAM,KAAK,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,yBAAyB,SAAoC,OAAe;AAChF,UAAM,OAAO,MAAM,KAAK,MAAM,iDAAiD;AAAA,MAC7E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,QACzB,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B,CAAC;AAED,QAAI,KAAK,WAAW,KAAK;AACvB;AAAA,IACF;AACA,QAAI,KAAK,WAAW,KAAK;AACvB,YAAM,IAAI,kBAAkB,MAAM,KAAK,KAAK,CAAC;AAAA,IAC/C;AACA,UAAM,IAAI,MAAM;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,OAAe,QAAsB;AA3ZhE;AA4ZI,UAAM,aAAa,MAAM,KAAK,MAAM,0DAA0D;AAAA,MAC5F,SAAS;AAAA,QACP,eAAe,UAAU;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,WAAW,WAAW,KAAK;AAC7B,YAAM,IAAI,kBAAkB,MAAM,WAAW,KAAK,CAAC;AAAA,IACrD;AAEA,QAAI,CAAC,WAAW,QAAM,gBAAW,QAAQ,IAAI,cAAc,MAArC,mBAAwC,yBAAwB,oBAAoB;AACxG,YAAM,IAAI,MAAM,MAAM,WAAW,KAAK,CAAC;AAAA,IACzC;AAEA,UAAM,SAAS,MAAM,WAAW,KAAK;AAErC,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAAgB,KAAa,UAAkB,SAA6B;AACnF,QAAM,OAAO,IAAIC,UAAS;AAC1B,OAAK,OAAO,WAAW,OAAO;AAC9B,QAAM,OAAO,IAAI,KAAK,CAAC,GAAG,GAAG,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAK,OAAO,QAAQ,IAAI;AACxB,SAAO;AACT;;;ACtWO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAKxC,YAAqB,YAAoB,SAAiB,GAAS;AACjE,UAAM,OAAO;AADM;AAEnB,SAAK,OAAO;AACZ,SAAK,QAAQ,uBAAG;AAChB,SAAK,eAAe,uBAAG;AACvB,SAAK,QAAQ,uBAAG;AAAA,EAClB;AAAA,EAVA;AAAA,EACA;AAAA,EACA;AASF;AAEO,IAAM,kBAAN,MAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,EAU3B,YAAmB,KAAa,SAAkC;AAA/C;AACjB,SAAK,WAAU,mCAAS,YAAW,CAAC;AACpC,SAAK,SAAQ,mCAAS,UAAS;AAC/B,SAAK,YAAW,mCAAS,aAAY;AACrC,SAAK,QAAO,mCAAS,SAAQ;AAAA,EAC/B;AAAA,EAdU;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAaV,MAAM,SAAS,aAAqB,aAAqB,QAAsB;AAC7E,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,MAAM,aAAa;AAAA,MACxD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,aAAa,YAAY,CAAC;AAAA,MACjD,SAAS;AAAA,QACP,GAAG,KAAK;AAAA,QACR,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,MAAM,WAAW,aAAqB,aAAqB,QAAsB;AAC/E,WAAO,MAAM,KAAK,MAAM,KAAK,MAAM,eAAe;AAAA,MAChD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,aAAa,YAAY,CAAC;AAAA,MACjD,SAAS;AAAA,QACP,GAAG,KAAK;AAAA,QACR,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE;AAAA,EACrB;AAAA,EAEA,MAAM,MAAM,EAAE,UAAU,UAAU,aAAa,YAAY,GAAuF,QAAsB;AAzI1K;AA0II,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,MAAM,iBAAiB;AAAA,MAC5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,EAAE,MAAM,aAAa,SAAS,EAAE;AAAA,QACvC,aAAa,OAAO,gBAAgB,YAAY,cAAc;AAAA,QAC9D;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,MACD,SAAS;AAAA,QACP,GAAG,KAAK;AAAA,QACR,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,SAAS,UAAU,KAAK;AAC1B,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,IAAI,eAAe,SAAS,QAAQ,SAAS,SAAS,MAAM,QAAM,cAAS,QAAQ,IAAI,cAAc,MAAnC,mBAAsC,WAAW,uBAAsB,KAAK,MAAM,IAAI,IAAI,MAAS;AAAA,IAC7K;AAEA,UAAM,iBAAyC,MAAM,SAAS,KAAK;AACnE,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,EAAE,aAAa,aAAa,YAAY,GAAwE,QAAsB;AAnKtJ;AAoKI,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,MAAM,YAAY;AAAA,MACvD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA;AAAA,QACA,aAAa,OAAO,gBAAgB,YAAY,cAAc;AAAA,MAChE,CAAC;AAAA,MACD,SAAS;AAAA,QACP,GAAG,KAAK;AAAA,QACR,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,SAAS,UAAU,KAAK;AAC1B,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,IAAI,eAAe,SAAS,QAAQ,SAAS,SAAS,MAAM,QAAM,cAAS,QAAQ,IAAI,cAAc,MAAnC,mBAAsC,WAAW,uBAAsB,KAAK,MAAM,IAAI,IAAI,MAAS;AAAA,IAC7K;AAEA,UAAM,iBAAiB,MAAM,SAAS,KAAK;AAC3C,WAAO;AAAA,EACT;AACF;AAiCO,SAAS,cAAc,GAAqB;AACjD,SAAO,EAAE,WAAW,EAAE,SAAS,UAAU,SAAS;AACpD;AAEO,SAAS,eAAe,GAAqB;AAClD,SAAO,cAAc,CAAC,IAAI,SAAS;AACrC;AAEO,IAAM,4BAAN,cAAwC,gBAAgB;AAAA,EACtD;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOP,YACE,KACA,SACA;AACA,UAAM,MAAM,eAAe,OAAO;AAElC,SAAK,aAAa,MAAM;AAGxB,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEA,MAAM,OAAO,MAAc,WAAW,MAAM,QAAsB;AAxPpE;AA0PI,UAAM,MAAM,IAAI,IAAI,KAAK,WAAW,QAAQ,WAAW,IAAI,CAAC;AAC5D,QAAI,aAAa,OAAO,YAAY,WAAW,SAAS,OAAO;AAC/D,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,SAAS,GAAG;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS,KAAK;AAAA,MACd;AAAA,IACF,CAAC;AACD,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,IAAI,eAAe,SAAS,QAAQ,SAAS,SAAS,MAAM,QAAM,cAAS,QAAQ,IAAI,cAAc,MAAnC,mBAAsC,WAAW,uBAAsB,KAAK,MAAM,IAAI,IAAI,MAAS;AAAA,IAC7K;AACA,UAAM,IAAI,MAAM,SAAS,KAAK;AAC9B,QAAI,EAAE,cAAc,EAAE,sBAAsB,OAAO;AACjD,YAAM,aAAa,EAAE;AACrB,YAAM,KAAgC,CAAC;AACvC,iBAAW,QAAQ,YAAY;AAI7B,WAAG,KAAK,IAAI,IAAI,KAAK;AAAA,MAEvB;AACA,QAAE,aAAa;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,SAA2B,QAAsB;AArRpE;AAuRI,UAAM,MAAM,IAAI,IAAI,KAAK,WAAW,QAAQ,WAAW,QAAQ,IAAI,EAAE,QAAQ,WAAW,QAAQ,IAAI,CAAC;AAGrG,UAAM,iBAA8B;AAAA,MAClC,SAAS;AAAA,QACP,GAAG,KAAK;AAAA,QACR,eAAe,UAAU,QAAQ;AAAA,MACnC;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,SAAS;AAEpB,qBAAe,SAAS;AAAA,IAC1B,WAAW,UAAU,QAAQ,SAAS;AACpC,qBAAe,SAAS;AAExB,YAAM,OAAO,IAAI,KAAK,SAAS;AAC/B,WAAK,OAAO,WAAS,aAAQ,QAAQ,aAAhB,mBAA0B,UAAS,OAAO;AAC/D,WAAK,OAAO,QAAQ,IAAI,KAAK,KAAK,CAAC,QAAQ,QAAQ,IAAI,GAAG,aAAa,EAAE,MAAM,YAAY,CAAC,CAAC;AAC7F,qBAAe,OAAO;AAAA,IACxB,WAAW,SAAS,QAAQ,SAAS;AAEnC,qBAAe,SAAS;AACxB,UAAI,aAAa,OAAO,WAAS,aAAQ,QAAQ,aAAhB,mBAA0B,UAAS,EAAE;AACtE,UAAI,aAAa,OAAO,OAAO,QAAQ,QAAQ,GAAG;AAAA,IACpD,OAAO;AACL,YAAM,IAAI,UAAU,wBAAwB;AAAA,IAC9C;AAEA,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,SAAS,GAAG,cAAc;AAChE,QAAI,SAAS,WAAW,KAAK;AAC3B,UAAI,SAAS,QAAQ,IAAI,cAAc,MAAM,oBAAoB;AAC/D,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,cAAM,IAAI,eAAe,SAAS,QAAQ,SAAS,OAAO,SAAS,GAAG;AAAA,UACpE,OAAO,KAAK,SAAS;AAAA,UACrB,cAAc,KAAK,gBAAgB;AAAA,QACrC,CAAC;AAAA,MACH,OAAO;AACL,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,cAAM,IAAI,eAAe,SAAS,QAAQ,SAAS,SAAS,MAAM,MAAM;AAAA,UACtE,OAAO;AAAA,UACP,cAAc,mBAAmB;AAAA,QACnC,CAAC;AAAA,MACH;AAAA,IACF;AACA,QAAI,SAAS,UAAU,KAAK;AAC1B,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,IAAI,eAAe,SAAS,QAAQ,SAAS,SAAS,MAAM,MAAM;AAAA,QACtE,OAAO;AAAA,QACP,cAAc,sBAAsB;AAAA,MACtC,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACvRO,IAAM,yBAAN,MAA6B;AAAA,EAClC;AAAA,EAEA,YAAY,SAAwC;AAClD,SAAK,QAAQ,QAAQ,SAAS;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,qBAAqB,kBAA0B,QAAsB;AACzE,UAAM,cAAc,MAAM,KAAK,MAAM,oDAAoD;AAAA,MACvF,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,YAAY;AAAA,UACV,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,WAAW,KAAK;AAAA,QAClB;AAAA,QACA,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,MACD,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,YAAY,WAAW,KAAK;AAC9B,YAAM,IAAI,MAAM,uDAAuD,YAAY,WAAW,MAAM,YAAY,KAAK,IAAI;AAAA,IAC3H;AAEA,UAAM,SAAS,MAAM,YAAY,KAAK;AAEtC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAAkB,kBAA0B,eAA0E,mCAAmC,QAAsB;AACnL,UAAM,eAAe,MAAM,KAAK,MAAM,iDAAiD;AAAA,MACrF,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,YAAY;AAAA,UACV,WAAW;AAAA,UACX,YAAY,CAAC,gBAAgB;AAAA,QAC/B;AAAA,QACA,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,MACD;AAAA,IACF,CAAC;AAED,QAAI,aAAa,WAAW,KAAK;AAC/B,YAAM,UAAU,MAAM,aAAa,KAAK;AACxC,UAAI,SAAS,CAAC;AACd,UAAI;AACF,iBAAS,KAAK,MAAM,OAAO;AAAA,MAC7B,SAAS,GAAP;AAAA,MAAW;AACb,YAAM,OAAO,OAAO,IAAI,MAAM,oDAAoD,aAAa,WAAW,UAAU,GAAG,MAAM;AAAA,IAC/H;AAEA,UAAM,SAAS,MAAM,aAAa,KAAK;AAEvC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,mBAAmB,MAAc,KAAa,WAAmB,QAAsB;AAC3F,UAAM,MAAM,IAAI,IAAI,2CAA2C,wBAAwB;AACvF,QAAI,aAAa,OAAO,YAAY,CAAC,kBAAkB,UAAU,EAAE,KAAK,GAAG,CAAC;AAC5E,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,SAAS,GAAG;AAAA,MAChD,SAAS;AAAA,QACP,0BAA0B;AAAA,QAC1B,gBAAgB;AAAA,QAChB,eAAe,YAAY,OAAO;AAAA,MACpC;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,iDAAiD,SAAS,WAAW,MAAM,SAAS,KAAK,IAAI;AAAA,IAC/G;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,iBAAiB,kBAA0B,QAAsB;AACrE,UAAM,cAA4B,MAAM,KAAK,qBAAqB,kBAAkB,MAAM;AAC1F,UAAM,wBAAsC,MAAM,KAAK,kBAAkB,YAAY,OAAO,mCAAmC,MAAM;AACrI,UAAM,eAA6B,MAAM,KAAK,kBAAkB,YAAY,OAAO,uBAAuB,MAAM;AAEhH,WAAO,EAAE,uBAAuB,kBAAkB,aAAa;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,uBAAuB,KAAa,WAAmB,QAAsB;AACjF,UAAM,aAAa,MAAM,KAAK,MAAM,oEAAoE;AAAA,MACtG,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,eAAe,YAAY,OAAO;AAAA,MACpC,CAAC;AAAA,MACD,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,WAAW,WAAW,KAAK;AAC7B,YAAM,IAAI,MAAM,qDAAqD,WAAW,WAAW,MAAM,WAAW,KAAK,IAAI;AAAA,IACvH;AAEA,UAAM,SAAS,MAAM,WAAW,KAAK;AAErC,WAAO;AAAA,EACT;AACF;", "names": ["fetch", "FormData", "NameAvailability"] }