diff options
author | mat <27899617+mat-1@users.noreply.github.com> | 2021-02-13 14:13:42 -0600 |
---|---|---|
committer | mat <27899617+mat-1@users.noreply.github.com> | 2021-02-13 14:13:42 -0600 |
commit | 52e38809212133ef673d11bfa96ba3bb43c3644c (patch) | |
tree | f54408afd41cc64b64d5e82a3ad814b1bb55d4a7 /hypixel.ts | |
parent | a23103ec24128f2e24b93ad101ade6dfdd4758c3 (diff) | |
download | skyblock-api-52e38809212133ef673d11bfa96ba3bb43c3644c.tar.gz skyblock-api-52e38809212133ef673d11bfa96ba3bb43c3644c.tar.bz2 skyblock-api-52e38809212133ef673d11bfa96ba3bb43c3644c.zip |
move stuff into src folder
Diffstat (limited to 'hypixel.ts')
-rw-r--r-- | hypixel.ts | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/hypixel.ts b/hypixel.ts deleted file mode 100644 index f17dc9e..0000000 --- a/hypixel.ts +++ /dev/null @@ -1,284 +0,0 @@ -import { CleanMinion, cleanMinions, combineMinionArrays } from './cleaners/skyblock/minions' -import { CleanProfileStats, cleanProfileStats } from './cleaners/skyblock/stats' -import { CleanPlayer, cleanPlayerResponse } from './cleaners/player' -import { chooseApiKey, HypixelPlayerStatsSkyBlockProfiles, HypixelResponse, sendApiRequest } from './hypixelApi' -import * as cached from './hypixelCached' - -export type Included = 'profiles' | 'player' | 'stats' - -// the interval at which the "last_save" parameter updates in the hypixel api, this is 3 minutes -export const saveInterval = 60 * 3 * 1000 - -// the highest level a minion can be -export const maxMinion = 11 - -/** - * Send a request to api.hypixel.net using a random key, clean it up to be more useable, and return it - */ -export async function sendCleanApiRequest({ path, args }, included?: Included[], cleaned=true) { - const key = await chooseApiKey() - const rawResponse = await sendApiRequest({ path, key, args }) - if (rawResponse.throttled) { - // if it's throttled, wait a second and try again - console.log('throttled :/') - await new Promise(resolve => setTimeout(resolve, 1000)) - return await sendCleanApiRequest({ path, args }, included, cleaned) - } - if (cleaned) { - // if it needs to clean the response, call cleanResponse - return await cleanResponse({ path, data: rawResponse }, included=included) - } else { - // this is provided in case the caller wants to do the cleaning itself - // used in skyblock/profile, as cleaning the entire profile would use too much cpu - return rawResponse - } -} - -export interface CleanBasicMember { - uuid: string - username: string - last_save: number - first_join: number -} - -interface CleanMember extends CleanBasicMember { - stats?: CleanProfileStats - minions?: CleanMinion[] -} - -async function cleanSkyBlockProfileMemberResponse(member, included: Included[] = null): Promise<CleanMember> { - // Cleans up a member (from skyblock/profile) - // profiles.members[] - const statsIncluded = included == null || included.includes('stats') - return { - uuid: member.uuid, - username: await cached.usernameFromUser(member.uuid), - last_save: member.last_save, - first_join: member.first_join, - // last_death: ??? idk how this is formatted, - stats: statsIncluded ? cleanProfileStats(member.stats) : undefined, - minions: statsIncluded ? cleanMinions(member.crafted_generators) : undefined, - } -} - - -export interface CleanMemberProfilePlayer extends CleanPlayer { - // The profile name may be different for each player, so we put it here - profileName: string - first_join: number - last_save: number - bank?: { - balance: number - history: any[] - } -} - -export interface CleanMemberProfile { - member: CleanMemberProfilePlayer - profile: { - - } -} - -export interface CleanProfile extends CleanBasicProfile { - members?: CleanBasicMember[] -} - -export interface CleanFullProfile extends CleanProfile { - members: CleanMember[] - bank?: { - balance: number - history: any[] - } - minions: CleanMinion[] -} - -/** Return a `CleanProfile` instead of a `CleanFullProfile`, useful when we need to get members but don't want to waste much ram */ -async function cleanSkyblockProfileResponseLighter(data): Promise<CleanProfile> { - // We use Promise.all so it can fetch all the usernames at once instead of waiting for the previous promise to complete - const promises: Promise<CleanMember>[] = [] - - for (const memberUUID in data.members) { - const memberRaw = data.members[memberUUID] - memberRaw.uuid = memberUUID - // we pass an empty array to make it not check stats - promises.push(cleanSkyBlockProfileMemberResponse(memberRaw, [])) - } - - const cleanedMembers: CleanMember[] = await Promise.all(promises) - - return { - uuid: data.profile_id, - name: data.cute_name, - members: cleanedMembers, - } -} - -/** This function is very costly and shouldn't be called often. Use cleanSkyblockProfileResponseLighter if you don't need all the data */ -async function cleanSkyblockProfileResponse(data: any): Promise<CleanFullProfile> { - const cleanedMembers: CleanMember[] = [] - - for (const memberUUID in data.members) { - const memberRaw = data.members[memberUUID] - memberRaw.uuid = memberUUID - const member: CleanMember = await cleanSkyBlockProfileMemberResponse(memberRaw, ['stats']) - cleanedMembers.push(member) - } - - const memberMinions: CleanMinion[][] = [] - - for (const member of cleanedMembers) { - memberMinions.push(member.minions) - } - const minions: CleanMinion[] = combineMinionArrays(memberMinions) - - // return more detailed info - return { - uuid: data.profile_id, - name: data.cute_name, - members: cleanedMembers, - bank: { - balance: data?.banking?.balance ?? 0, - - // TODO: make transactions good - history: data?.banking?.transactions ?? [] - }, - minions - } -} - -/** A basic profile that only includes the profile uuid and name */ -export interface CleanBasicProfile { - uuid: string - - // the name depends on the user, so its sometimes not included - name?: string -} - -export function cleanPlayerSkyblockProfiles(rawProfiles: HypixelPlayerStatsSkyBlockProfiles): CleanBasicProfile[] { - let profiles: CleanBasicProfile[] = [] - for (const profile of Object.values(rawProfiles)) { - profiles.push({ - uuid: profile.profile_id, - name: profile.cute_name - }) - } - console.log('cleanPlayerSkyblockProfiles', profiles) - return profiles -} - -/** Convert an array of raw profiles into clean profiles */ -async function cleanSkyblockProfilesResponse(data: any[]): Promise<CleanProfile[]> { - const cleanedProfiles: CleanProfile[] = [] - for (const profile of data) { - let cleanedProfile = await cleanSkyblockProfileResponseLighter(profile) - cleanedProfiles.push(cleanedProfile) - } - return cleanedProfiles -} - -async function cleanResponse({ path, data }: { path: string, data: HypixelResponse }, included?: Included[]) { - // Cleans up an api response - switch (path) { - case 'player': return await cleanPlayerResponse(data.player) - case 'skyblock/profile': return await cleanSkyblockProfileResponse(data.profile) - case 'skyblock/profiles': return await cleanSkyblockProfilesResponse(data.profiles) - } -} - -/* ----------------------------- */ - -export interface UserAny { - user?: string - uuid?: string - username?: string -} - -export interface CleanUser { - player: any - profiles?: any - activeProfile?: string - online?: boolean -} - - -/** - * Higher level function that requests the api for a user, and returns the cleaned response - * This is safe to fetch many times because the results are cached! - * @param included lets you choose what is returned, so there's less processing required on the backend - * used inclusions: player, profiles - */ -export async function fetchUser({ user, uuid, username }: UserAny, included: Included[]=['player']): Promise<CleanUser> { - if (!uuid) { - // If the uuid isn't provided, get it - uuid = await cached.uuidFromUser(user || username) - } - - const includePlayers = included.includes('player') - const includeProfiles = included.includes('profiles') - - let profilesData: CleanProfile[] - let basicProfilesData: CleanBasicProfile[] - let playerData: CleanPlayer - - if (includePlayers) { - playerData = await cached.fetchPlayer(uuid) - // if not including profiles, include lightweight profiles just in case - if (!includeProfiles) - basicProfilesData = playerData.profiles - playerData.profiles = undefined - } - if (includeProfiles) { - profilesData = await cached.fetchSkyblockProfiles(uuid) - } - - let activeProfile: CleanProfile = null - let lastOnline: number = 0 - - if (includeProfiles) { - for (const profile of profilesData) { - const member = profile.members.find(member => member.uuid === uuid) - if (member.last_save > lastOnline) { - lastOnline = member.last_save - activeProfile = profile - } - } - } - return { - player: playerData ?? null, - profiles: profilesData ?? basicProfilesData, - activeProfile: includeProfiles ? activeProfile?.uuid : undefined, - online: includeProfiles ? lastOnline > (Date.now() - saveInterval): undefined - } -} - -/** - * Fetch a CleanMemberProfile from a user and string - * This is safe to use many times as the results are cached! - * @param user A username or uuid - * @param profile A profile name or profile uuid - */ -export async function fetchMemberProfile(user: string, profile: string): Promise<CleanMemberProfile> { - const playerUuid = await cached.uuidFromUser(user) - const profileUuid = await cached.fetchProfileUuid(user, profile) - - const player = await cached.fetchPlayer(playerUuid) - - const cleanProfile = await cached.fetchProfile(playerUuid, profileUuid) - - const member = cleanProfile.members.find(m => m.uuid === playerUuid) - - return { - member: { - profileName: cleanProfile.name, - first_join: member.first_join, - last_save: member.last_save, - - // add all other data relating to the hypixel player, such as username, rank, etc - ...player - }, - profile: { - minions: cleanProfile.minions - } - } -} |