From 541731a63c5e05baa58dd6fcb598c14dd4ce9d88 Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Thu, 8 Apr 2021 14:17:40 -0500 Subject: add member leaderboard spots api --- src/database.ts | 40 +++++++++++++++++++++++++++++++++++++--- src/index.ts | 10 ++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/database.ts b/src/database.ts index 66d4142..6e5a41b 100644 --- a/src/database.ts +++ b/src/database.ts @@ -23,6 +23,7 @@ const recentlyUpdated = new NodeCache({ interface DatabaseLeaderboardItem { uuid: string + profile: string stats: any last_updated: Date } @@ -178,7 +179,12 @@ async function fetchMemberLeaderboardRaw(name: string): Promise } } +/** Get the leaderboard positions a member is on. This may take a while depending on whether stuff is cached */ +export async function fetchMemberLeaderboardSpots(player: string, profile: string) { + const fullProfile = await cached.fetchProfile(player, profile) + const fullMember = fullProfile.members.find(m => m.username.toLowerCase() === player.toLowerCase() || m.uuid === player) + + // update the leaderboard positions for the member + await updateDatabaseMember(fullMember, fullProfile) + + const applicableAttributes = await getApplicableAttributes(fullMember) + + const memberLeaderboardSpots = [] + + for (const leaderboardName in applicableAttributes) { + const leaderboard = await fetchMemberLeaderboardRaw(leaderboardName) + const leaderboardPositionIndex = leaderboard.findIndex(i => i.uuid === fullMember.uuid && i.profile === fullProfile.uuid) + memberLeaderboardSpots.push({ + name: leaderboardName, + positionIndex: leaderboardPositionIndex, + value: applicableAttributes[leaderboardName], + + }) + } + + return memberLeaderboardSpots +} + async function getMemberLeaderboardRequirement(name: string): Promise { const leaderboard = await fetchMemberLeaderboardRaw(name) // if there's more than 100 items, return the 100th. if there's less, return null @@ -219,7 +251,7 @@ async function getMemberLeaderboardRequirement(name: string): Promise { } /** Get the attributes for the member, but only ones that would put them on the top 100 for leaderboards */ -async function getApplicableAttributes(member): Promise { +async function getApplicableAttributes(member: CleanMember): Promise { const leaderboardAttributes = getMemberLeaderboardAttributes(member) const applicableAttributes = {} for (const [ leaderboard, attributeValue ] of Object.entries(leaderboardAttributes)) { @@ -277,7 +309,8 @@ export async function updateDatabaseMember(member: CleanMember, profile: CleanFu .concat([{ last_updated: new Date(), stats: leaderboardAttributes, - uuid: member.uuid + uuid: member.uuid, + profile: profile.uuid }]) .sort((a, b) => leaderboardReverse ? a.stats[attributeName] - b.stats[attributeName] : b.stats[attributeName] - a.stats[attributeName]) .slice(0, 100) @@ -329,6 +362,7 @@ async function removeBadMemberLeaderboardAttributes(): Promise { /** Fetch all the leaderboards, used for caching. Don't call this often! */ async function fetchAllLeaderboards(fast?: boolean): Promise { const leaderboards = await fetchAllMemberLeaderboardAttributes() + // shuffle so if the application is restarting many times itll still be useful if (debug) console.log('Caching leaderboards!') for (const leaderboard of shuffle(leaderboards)) { diff --git a/src/index.ts b/src/index.ts index 0d66c55..451ef95 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ +import { fetchAllLeaderboardsCategorized, fetchMemberLeaderboard, fetchMemberLeaderboardSpots } from './database' import { fetchMemberProfile, fetchUser } from './hypixel' -import express from 'express' -import { fetchAllLeaderboardsCategorized, fetchMemberLeaderboard } from './database' import rateLimit from 'express-rate-limit' +import express from 'express' const app = express() @@ -40,6 +40,12 @@ app.get('/player/:user/:profile', async(req, res) => { ) }) +app.get('/player/:user/:profile/leaderboards', async(req, res) => { + res.json( + await fetchMemberLeaderboardSpots(req.params.user, req.params.profile) + ) +}) + app.get('/leaderboard/:name', async(req, res) => { res.json( await fetchMemberLeaderboard(req.params.name) -- cgit