diff options
-rw-r--r-- | build/hypixelCached.js | 3 | ||||
-rw-r--r-- | build/mojang.js | 53 | ||||
-rw-r--r-- | build/util.js | 7 | ||||
-rw-r--r-- | src/hypixelCached.ts | 5 | ||||
-rw-r--r-- | src/mojang.ts | 84 | ||||
-rw-r--r-- | src/util.ts | 5 |
6 files changed, 107 insertions, 50 deletions
diff --git a/build/hypixelCached.js b/build/hypixelCached.js index 88397bf..82e8c93 100644 --- a/build/hypixelCached.js +++ b/build/hypixelCached.js @@ -32,6 +32,7 @@ const hypixel = __importStar(require("./hypixel")); const util_1 = require("./util"); const _1 = require("."); // cache usernames for 4 hours +/** uuid: username */ const usernameCache = new node_cache_1.default({ stdTTL: 60 * 60 * 4, checkperiod: 60, @@ -85,7 +86,7 @@ function waitForCacheSet(cache, key, value) { */ async function uuidFromUser(user) { // if the user is 32 characters long, it has to be a uuid - if (util_1.undashUuid(user).length === 32) + if (util_1.isUuid(user)) return util_1.undashUuid(user); if (usernameCache.has(util_1.undashUuid(user))) { // check if the uuid is a key diff --git a/build/mojang.js b/build/mojang.js index b8bfa44..052f813 100644 --- a/build/mojang.js +++ b/build/mojang.js @@ -6,39 +6,68 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.usernameFromUser = exports.uuidFromUser = exports.mojangDataFromUser = void 0; +exports.usernameFromUser = exports.mojangDataFromUser = exports.uuidFromUser = exports.usernameFromUuid = exports.uuidFromUsername = exports.mojangDataFromUuid = void 0; const node_fetch_1 = __importDefault(require("node-fetch")); const https_1 = require("https"); +const util_1 = require("./util"); // We need to create an agent to prevent memory leaks const httpsAgent = new https_1.Agent({ keepAlive: true }); /** - * Get mojang api data from ashcon.app + * Get mojang api data from the session server */ -async function mojangDataFromUser(user) { +async function mojangDataFromUuid(uuid) { + console.log('mojangDataFromUuid', uuid); const fetchResponse = await node_fetch_1.default( - // we use v1 rather than v2 since its more stable - `https://api.ashcon.app/mojang/v1/user/${user}`, { agent: () => httpsAgent }); - return await fetchResponse.json(); + // using mojang directly is faster than ashcon lol, also mojang removed the ratelimits from here + `https://sessionserver.mojang.com/session/minecraft/profile/${util_1.undashUuid(uuid)}`, { agent: () => httpsAgent }); + const data = await fetchResponse.json(); + return { + uuid: data.id, + username: data.name + }; } -exports.mojangDataFromUser = mojangDataFromUser; +exports.mojangDataFromUuid = mojangDataFromUuid; +async function uuidFromUsername(username) { + console.log('uuidFromUsername', username); + // since we don't care about anything other than the uuid, we can use /uuid/ instead of /user/ + const fetchResponse = await node_fetch_1.default(`https://api.ashcon.app/mojang/v2/uuid/${username}`, { agent: () => httpsAgent }); + const userUuid = await fetchResponse.text(); + return userUuid.replace(/-/g, ''); +} +exports.uuidFromUsername = uuidFromUsername; +async function usernameFromUuid(uuid) { + const userJson = await mojangDataFromUuid(uuid); + return userJson.username; +} +exports.usernameFromUuid = usernameFromUuid; /** * Fetch the uuid from a user * @param user A user can be either a uuid or a username */ async function uuidFromUser(user) { - const fetchJSON = await mojangDataFromUser(user); - return fetchJSON.uuid.replace(/-/g, ''); + if (util_1.isUuid(user)) + // already a uuid, just return it undashed + return util_1.undashUuid(user); + else + return await uuidFromUsername(user); } exports.uuidFromUser = uuidFromUser; +async function mojangDataFromUser(user) { + if (!util_1.isUuid(user)) + return await mojangDataFromUuid(await uuidFromUsername(user)); + else + return await mojangDataFromUuid(user); +} +exports.mojangDataFromUser = mojangDataFromUser; /** * Fetch the username from a user * @param user A user can be either a uuid or a username */ async function usernameFromUser(user) { - // get a minecraft uuid from a username, using ashcon.app's mojang api - const fetchJSON = await mojangDataFromUser(user); - return fetchJSON.username; + // we do this to fix the capitalization + const data = await mojangDataFromUser(user); + return data.username; } exports.usernameFromUser = usernameFromUser; diff --git a/build/util.js b/build/util.js index df88635..e7ec9a6 100644 --- a/build/util.js +++ b/build/util.js @@ -3,7 +3,7 @@ * Random utility functions that are not related to Hypixel */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.sleep = exports.colorCodeFromName = exports.minecraftColorCodes = exports.shuffle = exports.jsonToQuery = exports.queryToJson = exports.undashUuid = void 0; +exports.isUuid = exports.sleep = exports.colorCodeFromName = exports.minecraftColorCodes = exports.shuffle = exports.jsonToQuery = exports.queryToJson = exports.undashUuid = void 0; function undashUuid(uuid) { return uuid.replace(/-/g, '').toLowerCase(); } @@ -82,3 +82,8 @@ async function sleep(ms) { await new Promise(resolve => setTimeout(resolve, ms)); } exports.sleep = sleep; +/** Returns whether a string is a UUID4 (Minecraft uuid) */ +function isUuid(string) { + return undashUuid(string).length === 32; +} +exports.isUuid = isUuid; diff --git a/src/hypixelCached.ts b/src/hypixelCached.ts index 4e3316e..82f3eaa 100644 --- a/src/hypixelCached.ts +++ b/src/hypixelCached.ts @@ -6,11 +6,12 @@ import NodeCache from 'node-cache' import * as mojang from './mojang' import * as hypixel from './hypixel' import { CleanPlayer } from './cleaners/player' -import { undashUuid } from './util' +import { isUuid, undashUuid } from './util' import { CleanProfile, CleanFullProfile, CleanBasicProfile } from './cleaners/skyblock/profile' import { debug } from '.' // cache usernames for 4 hours +/** uuid: username */ const usernameCache = new NodeCache({ stdTTL: 60 * 60 * 4, checkperiod: 60, @@ -77,7 +78,7 @@ function waitForCacheSet(cache: NodeCache, key?: string, value?: string): Promis */ export async function uuidFromUser(user: string): Promise<string> { // if the user is 32 characters long, it has to be a uuid - if (undashUuid(user).length === 32) + if (isUuid(user)) return undashUuid(user) if (usernameCache.has(undashUuid(user))) { diff --git a/src/mojang.ts b/src/mojang.ts index a340ae0..7efc4ae 100644 --- a/src/mojang.ts +++ b/src/mojang.ts @@ -4,59 +4,75 @@ import fetch from 'node-fetch' import { Agent } from 'https' +import { isUuid, undashUuid } from './util' // We need to create an agent to prevent memory leaks const httpsAgent = new Agent({ keepAlive: true }) -interface AshconHistoryItem { - username: string - changed_at?: string -} - -interface AshconTextures { - custom: boolean - slim: boolean - skin: { url: string, data: string } - raw: { value: string, signature: string } -} - -interface AshconV2Response { +interface MojangApiResponse { + /** These uuids are already undashed */ uuid: string - username: string - username_history: AshconHistoryItem[] - textures: AshconTextures - created_at?: string -} -interface AshconV1Response { - uuid: string username: string - username_history: AshconHistoryItem[] - textures: AshconTextures - cached_at?: string } /** - * Get mojang api data from ashcon.app + * Get mojang api data from the session server */ -export async function mojangDataFromUser(user: string): Promise<AshconV1Response> { - const fetchResponse = await fetch( - // we use v1 rather than v2 since its more stable - `https://api.ashcon.app/mojang/v1/user/${user}`, +export async function mojangDataFromUuid(uuid: string): Promise<MojangApiResponse> { + console.log('mojangDataFromUuid', uuid) + const fetchResponse = await fetch( + // using mojang directly is faster than ashcon lol, also mojang removed the ratelimits from here + `https://sessionserver.mojang.com/session/minecraft/profile/${undashUuid(uuid)}`, { agent: () => httpsAgent } ) - return await fetchResponse.json() + const data = await fetchResponse.json() + return { + uuid: data.id, + username: data.name + } } + +export async function uuidFromUsername(username: string): Promise<string> { + console.log('uuidFromUsername', username) + // since we don't care about anything other than the uuid, we can use /uuid/ instead of /user/ + const fetchResponse = await fetch( + `https://api.ashcon.app/mojang/v2/uuid/${username}`, + { agent: () => httpsAgent } + ) + const userUuid = await fetchResponse.text() + return userUuid.replace(/-/g, '') +} + +export async function usernameFromUuid(uuid: string): Promise<string> { + const userJson = await mojangDataFromUuid(uuid) + return userJson.username +} + + + + /** * Fetch the uuid from a user * @param user A user can be either a uuid or a username */ export async function uuidFromUser(user: string): Promise<string> { - const fetchJSON = await mojangDataFromUser(user) - return fetchJSON.uuid.replace(/-/g, '') + if (isUuid(user)) + // already a uuid, just return it undashed + return undashUuid(user) + else + return await uuidFromUsername(user) +} + + +export async function mojangDataFromUser(user: string): Promise<MojangApiResponse> { + if (!isUuid(user)) + return await mojangDataFromUuid(await uuidFromUsername(user)) + else + return await mojangDataFromUuid(user) } /** @@ -64,8 +80,8 @@ export async function uuidFromUser(user: string): Promise<string> { * @param user A user can be either a uuid or a username */ export async function usernameFromUser(user: string): Promise<string> { - // get a minecraft uuid from a username, using ashcon.app's mojang api - const fetchJSON = await mojangDataFromUser(user) - return fetchJSON.username + // we do this to fix the capitalization + const data = await mojangDataFromUser(user) + return data.username } diff --git a/src/util.ts b/src/util.ts index cc9cffb..facc425 100644 --- a/src/util.ts +++ b/src/util.ts @@ -82,4 +82,9 @@ export function colorCodeFromName(colorName: string): string { export async function sleep(ms: number): Promise<void> { await new Promise(resolve => setTimeout(resolve, ms)) +} + +/** Returns whether a string is a UUID4 (Minecraft uuid) */ +export function isUuid(string: string) { + return undashUuid(string).length === 32 }
\ No newline at end of file |