aboutsummaryrefslogtreecommitdiff
path: root/src/hypixelCached.ts
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2021-02-28 01:23:18 -0600
committermat <27899617+mat-1@users.noreply.github.com>2021-02-28 01:23:18 -0600
commit6dadf95683a8b8574976c9d024b0b148521012f7 (patch)
treeedd88502959e8b74c76d47a82a5b98a646b26eb4 /src/hypixelCached.ts
parent78198ac4812f6f33f412bdc62216567aa08d8199 (diff)
downloadskyblock-api-6dadf95683a8b8574976c9d024b0b148521012f7.tar.gz
skyblock-api-6dadf95683a8b8574976c9d024b0b148521012f7.tar.bz2
skyblock-api-6dadf95683a8b8574976c9d024b0b148521012f7.zip
Add leaderboards
Diffstat (limited to 'src/hypixelCached.ts')
-rw-r--r--src/hypixelCached.ts71
1 files changed, 45 insertions, 26 deletions
diff --git a/src/hypixelCached.ts b/src/hypixelCached.ts
index 1b8b617..83360a9 100644
--- a/src/hypixelCached.ts
+++ b/src/hypixelCached.ts
@@ -2,7 +2,7 @@
* Fetch the clean and cached Hypixel API
*/
-import NodeCache from 'node-cache'
+import NodeCache, { EventEmitter, Key } from 'node-cache'
import * as mojang from './mojang'
import * as hypixel from './hypixel'
import { CleanPlayer } from './cleaners/player'
@@ -10,8 +10,6 @@ import { undashUuid } from './util'
import { CleanProfile, CleanFullProfile, CleanBasicProfile } from './cleaners/skyblock/profile'
import { debug } from '.'
-
-
// cache usernames for 4 hours
const usernameCache = new NodeCache({
stdTTL: 60 * 60 * 4,
@@ -49,28 +47,54 @@ const profileNameCache = new NodeCache({
useClones: false,
})
+function waitForSet(cache: NodeCache, key?: string, value?: string): Promise<any> {
+ return new Promise((resolve, reject) => {
+ const listener = (setKey, setValue) => {
+ if (setKey === key || (value && setValue === value)) {
+ cache.removeListener('set', listener)
+ return resolve({ key, value })
+ }
+ }
+ cache.on('set', listener)
+ })
+}
+
/**
* 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> {
- if (usernameCache.has(undashUuid(user)))
+ if (usernameCache.has(undashUuid(user))) {
// check if the uuid is a key
- return undashUuid(user)
+ const username: any = usernameCache.get(undashUuid(user))
+ // if it has .then, then that means its a waitForSet promise. This is done to prevent requests made while it is already requesting
+ if (username.then) {
+ return (await username()).key
+ } else
+ return undashUuid(user)
+ }
// check if the username is a value
const uuidToUsername: {[ key: string ]: string} = usernameCache.mget(usernameCache.keys())
for (const [ uuid, username ] of Object.entries(uuidToUsername)) {
- if (user.toLowerCase() === username.toLowerCase())
+ if (username.toLowerCase && user.toLowerCase() === username.toLowerCase())
return uuid
}
+ if (debug) console.log('Cache miss: uuidFromUser', user)
+
+ // set it as waitForSet (a promise) in case uuidFromUser gets called while its fetching mojang
+ usernameCache.set(undashUuid(user), waitForSet(usernameCache, user, user))
+
// not cached, actually fetch mojang api now
let { uuid, username } = await mojang.mojangDataFromUser(user)
if (!uuid) return
// remove dashes from the uuid so its more normal
uuid = undashUuid(uuid)
+
+ if (user !== uuid) usernameCache.del(user)
+
usernameCache.set(uuid, username)
return uuid
}
@@ -85,6 +109,8 @@ export async function usernameFromUser(user: string): Promise<string> {
return usernameCache.get(undashUuid(user))
}
+ if (debug) console.log('Cache miss: usernameFromUser', user)
+
let { uuid, username } = await mojang.mojangDataFromUser(user)
uuid = undashUuid(uuid)
usernameCache.set(uuid, username)
@@ -96,7 +122,6 @@ export async function fetchPlayer(user: string): Promise<CleanPlayer> {
const playerUuid = await uuidFromUser(user)
if (playerCache.has(playerUuid)) {
- if (debug) console.log('Cache hit! fetchPlayer', playerUuid)
return playerCache.get(playerUuid)
}
@@ -120,17 +145,9 @@ export async function fetchSkyblockProfiles(playerUuid: string): Promise<CleanPr
return profilesCache.get(playerUuid)
}
- const profiles: CleanFullProfile[] = await hypixel.sendCleanApiRequest({
- path: 'skyblock/profiles',
- args: {
- uuid: playerUuid
- }},
- null,
- {
- // only the inventories for the main player are generated, this is for optimization purposes
- mainMemberUuid: playerUuid
- }
- )
+ if (debug) console.log('Cache miss: fetchSkyblockProfiles', playerUuid)
+
+ const profiles: CleanProfile[] = await hypixel.fetchMemberProfilesUncached(playerUuid)
const basicProfiles: CleanProfile[] = []
@@ -165,6 +182,9 @@ async function fetchBasicProfiles(user: string): Promise<CleanBasicProfile[]> {
if (debug) console.log('Cache hit! fetchBasicProfiles', playerUuid)
return basicProfilesCache.get(playerUuid)
}
+
+ if (debug) console.log('Cache miss: fetchBasicProfiles', user)
+
const player = await fetchPlayer(playerUuid)
const profiles = player.profiles
basicProfilesCache.set(playerUuid, profiles)
@@ -188,6 +208,8 @@ export async function fetchProfileUuid(user: string, profile: string) {
return null
}
+ if (debug) console.log('Cache miss: fetchProfileUuid', user)
+
const profiles = await fetchBasicProfiles(user)
const profileUuid = undashUuid(profile)
@@ -215,16 +237,11 @@ export async function fetchProfile(user: string, profile: string): Promise<Clean
return profileCache.get(profileUuid)
}
+ if (debug) console.log('Cache miss: fetchProfile', user, profile)
+
const profileName = await fetchProfileName(user, profile)
- const cleanProfile: CleanFullProfile = await hypixel.sendCleanApiRequest(
- {
- path: 'skyblock/profile',
- args: { profile: profileUuid }
- },
- null,
- { mainMemberUuid: playerUuid }
- )
+ const cleanProfile: CleanFullProfile = await hypixel.fetchMemberProfileUncached(playerUuid, profileUuid)
// we know the name from fetchProfileName, so set it here
cleanProfile.name = profileName
@@ -250,6 +267,8 @@ export async function fetchProfileName(user: string, profile: string): Promise<s
return profileNameCache.get(`${playerUuid}.${profileUuid}`)
}
+ if (debug) console.log('Cache miss: fetchProfileName', user, profile)
+
const basicProfiles = await fetchBasicProfiles(playerUuid)
let profileName
for (const basicProfile of basicProfiles)