diff options
author | mat <27899617+mat-1@users.noreply.github.com> | 2021-04-13 16:30:27 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-13 16:30:27 -0500 |
commit | ac79dfbc6ad6eb56bc814471d49b95f014d3eb5f (patch) | |
tree | 600846dd4804c487d16d33dd99ad4073d815e8f3 /build | |
parent | c0d03a8d0c1e75967f48cb27d9c55bc4707af22c (diff) | |
download | skyblock-api-ac79dfbc6ad6eb56bc814471d49b95f014d3eb5f.tar.gz skyblock-api-ac79dfbc6ad6eb56bc814471d49b95f014d3eb5f.tar.bz2 skyblock-api-ac79dfbc6ad6eb56bc814471d49b95f014d3eb5f.zip |
Slayer leaderboard (#4)
* add slayers to constants
* Compiled TS into JS
* change units to also show up when only changing one constant item
* Compiled TS into JS
* add slayer leaderboards
* remove debugging stuff
Diffstat (limited to 'build')
-rw-r--r-- | build/cleaners/skyblock/slayers.js | 30 | ||||
-rw-r--r-- | build/cleaners/skyblock/stats.js | 1 | ||||
-rw-r--r-- | build/constants.js | 47 | ||||
-rw-r--r-- | build/database.js | 44 | ||||
-rw-r--r-- | build/hypixelApi.js | 10 | ||||
-rw-r--r-- | build/mojang.js | 24 |
6 files changed, 124 insertions, 32 deletions
diff --git a/build/cleaners/skyblock/slayers.js b/build/cleaners/skyblock/slayers.js index d2b9dbe..dbc20fc 100644 --- a/build/cleaners/skyblock/slayers.js +++ b/build/cleaners/skyblock/slayers.js @@ -1,52 +1,64 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.cleanSlayers = void 0; -const slayerLevels = 4; // number of slayer levels, this might be 5 soon +exports.cleanSlayers = exports.slayerLevels = void 0; +exports.slayerLevels = 4; // number of slayer levels, this might be 5 soon const SLAYER_NAMES = { spider: 'tarantula', zombie: 'revenant', wolf: 'sven' }; function cleanSlayers(data) { + var _a, _b; const slayers = []; const slayersDataRaw = data === null || data === void 0 ? void 0 : data.slayer_bosses; let totalXp = 0; + let totalKills = 0; for (const slayerNameRaw in slayersDataRaw) { const slayerDataRaw = slayersDataRaw[slayerNameRaw]; // convert name provided by api (spider) to the real name (tarantula) - const slayerName = SLAYER_NAMES[slayerDataRaw]; - const slayerXp = slayerDataRaw.xp; + const slayerName = SLAYER_NAMES[slayerNameRaw]; + const slayerXp = (_a = slayerDataRaw.xp) !== null && _a !== void 0 ? _a : 0; + let slayerKills = 0; const slayerTiers = []; for (const slayerDataKey in slayerDataRaw) { // if a key starts with boss_kills_tier_ (boss_kills_tier_1), get the last number if (slayerDataKey.startsWith('boss_kills_tier_')) { const slayerTierRaw = parseInt(slayerDataKey.substr('boss_kills_tier_'.length)); - const slayerTierKills = slayerDataRaw[slayerDataKey]; + const slayerTierKills = (_b = slayerDataRaw[slayerDataKey]) !== null && _b !== void 0 ? _b : 0; // add 1 since hypixel is using 0 indexed tiers const slayerTier = slayerTierRaw + 1; slayerTiers.push({ kills: slayerTierKills, tier: slayerTier }); + // count up the total number of kills for this slayer + if (slayerTierKills) + slayerKills += slayerTierKills; } } // if the slayer tier length is less than the max, add more empty ones - while (slayerTiers.length < slayerLevels) + while (slayerTiers.length < exports.slayerLevels) slayerTiers.push({ tier: slayerTiers.length + 1, kills: 0 }); const slayer = { name: slayerName, + raw_name: slayerNameRaw, tiers: slayerTiers, - xp: slayerXp + xp: slayerXp !== null && slayerXp !== void 0 ? slayerXp : 0, + kills: slayerKills }; slayers.push(slayer); - // add the xp from this slayer to the total xp - totalXp += slayerXp; + // add the xp and kills from this slayer to the total xp + if (slayerXp) + totalXp += slayerXp; + if (slayerKills) + totalKills += slayerKills; } return { xp: totalXp, + kills: totalKills, bosses: slayers }; } diff --git a/build/cleaners/skyblock/stats.js b/build/cleaners/skyblock/stats.js index 5673d99..0eb94c7 100644 --- a/build/cleaners/skyblock/stats.js +++ b/build/cleaners/skyblock/stats.js @@ -10,6 +10,7 @@ const statCategories = { 'mythos': ['mythos_burrows_', 'mythos_kills'], 'collection': ['collection_'], 'skills': ['skill_'], + 'slayer': ['slayer_'], 'misc': null // everything else goes here }; function categorizeStat(statNameRaw) { diff --git a/build/constants.js b/build/constants.js index 6344a12..96ae2e7 100644 --- a/build/constants.js +++ b/build/constants.js @@ -6,7 +6,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.addZones = exports.fetchZones = exports.addSkills = exports.fetchSkills = exports.addCollections = exports.fetchCollections = exports.addStats = exports.fetchStats = exports.addJSONConstants = void 0; +exports.addSlayers = exports.fetchSlayers = exports.addZones = exports.fetchZones = exports.addSkills = exports.fetchSkills = exports.addCollections = exports.fetchCollections = exports.addStats = exports.fetchStats = exports.addJSONConstants = void 0; const node_fetch_1 = __importDefault(require("node-fetch")); const https_1 = require("https"); const node_cache_1 = __importDefault(require("node-cache")); @@ -30,14 +30,21 @@ const queue = new queue_promise_1.default({ * @param json The JSON body, only applicable for some types of methods */ async function fetchGithubApi(method, route, headers, json) { - return await node_fetch_1.default(githubApiBase + route, { - agent: () => httpsAgent, - body: json ? JSON.stringify(json) : null, - method, - headers: Object.assign({ - 'Authorization': `token ${process.env.github_token}` - }, headers), - }); + try { + return await node_fetch_1.default(githubApiBase + route, { + agent: () => httpsAgent, + body: json ? JSON.stringify(json) : null, + method, + headers: Object.assign({ + 'Authorization': `token ${process.env.github_token}` + }, headers), + }); + } + catch { + // if there's an error, wait a second and try again + await new Promise((resolve) => setTimeout(resolve, 1000)); + return await fetchGithubApi(method, route, headers, json); + } } // cache files for an hour const fileCache = new node_cache_1.default({ @@ -95,7 +102,7 @@ async function fetchJSONConstant(filename) { } } /** Add stats to skyblock-constants. This has caching so it's fine to call many times */ -async function addJSONConstants(filename, addingValues, units = 'stats') { +async function addJSONConstants(filename, addingValues, unit = 'stat') { if (addingValues.length === 0) return; // no stats provided, just return queue.enqueue(async () => { @@ -119,7 +126,7 @@ async function addJSONConstants(filename, addingValues, units = 'stats') { // there's not actually any new stats, just return if (newStats.length === 0) return; - const commitMessage = newStats.length >= 2 ? `Add ${newStats.length} new ${units}` : `Add '${newStats[0]}'`; + const commitMessage = newStats.length >= 2 ? `Add ${newStats.length} new ${unit}s` : `Add '${newStats[0]}' ${unit}`; await editFile(file, commitMessage, JSON.stringify(updatedStats, null, 2)); }); } @@ -131,7 +138,7 @@ async function fetchStats() { exports.fetchStats = fetchStats; /** Add stats to skyblock-constants. This has caching so it's fine to call many times */ async function addStats(addingStats) { - await addJSONConstants('stats.json', addingStats, 'stats'); + await addJSONConstants('stats.json', addingStats, 'stat'); } exports.addStats = addStats; /** Fetch all the known SkyBlock collections as an array of strings */ @@ -141,7 +148,7 @@ async function fetchCollections() { exports.fetchCollections = fetchCollections; /** Add collections to skyblock-constants. This has caching so it's fine to call many times */ async function addCollections(addingCollections) { - await addJSONConstants('collections.json', addingCollections, 'collections'); + await addJSONConstants('collections.json', addingCollections, 'collection'); } exports.addCollections = addCollections; /** Fetch all the known SkyBlock collections as an array of strings */ @@ -151,7 +158,7 @@ async function fetchSkills() { exports.fetchSkills = fetchSkills; /** Add skills to skyblock-constants. This has caching so it's fine to call many times */ async function addSkills(addingSkills) { - await addJSONConstants('skills.json', addingSkills, 'skills'); + await addJSONConstants('skills.json', addingSkills, 'skill'); } exports.addSkills = addSkills; /** Fetch all the known SkyBlock collections as an array of strings */ @@ -161,6 +168,16 @@ async function fetchZones() { exports.fetchZones = fetchZones; /** Add skills to skyblock-constants. This has caching so it's fine to call many times */ async function addZones(addingZones) { - await addJSONConstants('zones.json', addingZones, 'zones'); + await addJSONConstants('zones.json', addingZones, 'zone'); } exports.addZones = addZones; +/** Fetch all the known SkyBlock slayer names as an array of strings */ +async function fetchSlayers() { + return await fetchJSONConstant('slayers.json'); +} +exports.fetchSlayers = fetchSlayers; +/** Add skills to skyblock-constants. This has caching so it's fine to call many times */ +async function addSlayers(addingSlayers) { + await addJSONConstants('slayers.json', addingSlayers, 'slayer'); +} +exports.addSlayers = addSlayers; diff --git a/build/database.js b/build/database.js index b40d30c..967828e 100644 --- a/build/database.js +++ b/build/database.js @@ -25,7 +25,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.queueUpdateDatabaseMember = exports.updateDatabaseMember = exports.fetchMemberLeaderboardSpots = exports.fetchMemberLeaderboard = exports.fetchAllMemberLeaderboardAttributes = exports.fetchAllLeaderboardsCategorized = void 0; +exports.queueUpdateDatabaseMember = exports.updateDatabaseMember = exports.fetchMemberLeaderboardSpots = exports.fetchMemberLeaderboard = exports.fetchAllMemberLeaderboardAttributes = exports.fetchSlayerLeaderboards = exports.fetchAllLeaderboardsCategorized = void 0; const stats_1 = require("./cleaners/skyblock/stats"); const mongodb_1 = require("mongodb"); const cached = __importStar(require("./hypixelCached")); @@ -34,6 +34,7 @@ const util_1 = require("./util"); const node_cache_1 = __importDefault(require("node-cache")); const queue_promise_1 = __importDefault(require("queue-promise")); const _1 = require("."); +const slayers_1 = require("./cleaners/skyblock/slayers"); // don't update the user for 3 minutes const recentlyUpdated = new node_cache_1.default({ stdTTL: 60 * 3, @@ -74,6 +75,20 @@ function getMemberSkillAttributes(member) { } return skillAttributes; } +function getMemberSlayerAttributes(member) { + const slayerAttributes = { + slayer_total_xp: member.slayers.xp, + slayer_total_kills: member.slayers.kills, + }; + for (const slayer of member.slayers.bosses) { + slayerAttributes[`slayer_${slayer.name}_total_xp`] = slayer.xp; + slayerAttributes[`slayer_${slayer.name}_total_kills`] = slayer.kills; + for (const tier of slayer.tiers) { + slayerAttributes[`slayer_${slayer.name}_${tier.tier}_kills`] = tier.kills; + } + } + return slayerAttributes; +} function getMemberLeaderboardAttributes(member) { // if you want to add a new leaderboard for member attributes, add it here (and getAllLeaderboardAttributes) return { @@ -83,6 +98,8 @@ function getMemberLeaderboardAttributes(member) { ...getMemberCollectionAttributes(member), // skill leaderboards ...getMemberSkillAttributes(member), + // slayer leaderboards + ...getMemberSlayerAttributes(member), fairy_souls: member.fairy_souls.total, first_join: member.first_join, purse: member.purse, @@ -105,6 +122,24 @@ async function fetchAllLeaderboardsCategorized() { return categorizedLeaderboards; } exports.fetchAllLeaderboardsCategorized = fetchAllLeaderboardsCategorized; +/** Fetch the raw names for the slayer leaderboards */ +async function fetchSlayerLeaderboards() { + const rawSlayerNames = await constants.fetchSlayers(); + let leaderboardNames = [ + 'slayer_total_xp', + 'slayer_total_kills' + ]; + // we use the raw names (zombie, spider, wolf) instead of the clean names (revenant, tarantula, sven) because the raw names are guaranteed to never change + for (const slayerNameRaw of rawSlayerNames) { + leaderboardNames.push(`slayer_${slayerNameRaw}_total_xp`); + leaderboardNames.push(`slayer_${slayerNameRaw}_total_kills`); + for (let slayerTier = 1; slayerTier <= slayers_1.slayerLevels; slayerTier++) { + leaderboardNames.push(`slayer_${slayerNameRaw}_${slayerTier}_kills`); + } + } + return leaderboardNames; +} +exports.fetchSlayerLeaderboards = fetchSlayerLeaderboards; /** Fetch the names of all the leaderboards */ async function fetchAllMemberLeaderboardAttributes() { return [ @@ -114,6 +149,8 @@ async function fetchAllMemberLeaderboardAttributes() { ...(await constants.fetchCollections()).map(value => `collection_${value}`), // skill leaderboards ...(await constants.fetchSkills()).map(value => `skill_${value}`), + // slayer leaderboards + ...await fetchSlayerLeaderboards(), 'fairy_souls', 'first_join', 'purse', @@ -231,6 +268,7 @@ async function updateDatabaseMember(member, profile) { await constants.addCollections(member.collections.map(coll => coll.name)); await constants.addSkills(member.skills.map(skill => skill.name)); await constants.addZones(member.visited_zones.map(zone => zone.name)); + await constants.addSlayers(member.slayers.bosses.map(s => s.raw_name)); if (_1.debug) console.log('done constants..'); const leaderboardAttributes = await getApplicableAttributes(member); @@ -265,13 +303,13 @@ async function updateDatabaseMember(member, profile) { console.log('added member to leaderboards', member.username, leaderboardAttributes); } exports.updateDatabaseMember = updateDatabaseMember; -const queue = new queue_promise_1.default({ +const leaderboardUpdateQueue = new queue_promise_1.default({ concurrent: 1, interval: 500 }); /** Queue an update for the member's leaderboard data on the server if applicable */ async function queueUpdateDatabaseMember(member, profile) { - queue.enqueue(async () => await updateDatabaseMember(member, profile)); + leaderboardUpdateQueue.enqueue(async () => await updateDatabaseMember(member, profile)); } exports.queueUpdateDatabaseMember = queueUpdateDatabaseMember; /** diff --git a/build/hypixelApi.js b/build/hypixelApi.js index ca2526f..2b3a601 100644 --- a/build/hypixelApi.js +++ b/build/hypixelApi.js @@ -51,7 +51,15 @@ async function sendApiRequest({ path, key, args }) { args.key = key; // Construct a url from the base api url, path, and arguments const fetchUrl = baseHypixelAPI + '/' + path + '?' + util_1.jsonToQuery(args); - const fetchResponse = await node_fetch_1.default(fetchUrl, { agent: () => httpsAgent }); + let fetchResponse; + try { + fetchResponse = await node_fetch_1.default(fetchUrl, { agent: () => httpsAgent }); + } + catch { + // if there's an error, wait a second and try again + await new Promise((resolve) => setTimeout(resolve, 1000)); + return await sendApiRequest({ path, key, args }); + } if (fetchResponse.headers['ratelimit-limit']) // remember how many uses it has apiKeyUsage[key] = { diff --git a/build/mojang.js b/build/mojang.js index f18875d..9641422 100644 --- a/build/mojang.js +++ b/build/mojang.js @@ -18,9 +18,17 @@ const httpsAgent = new https_1.Agent({ * Get mojang api data from the session server */ async function profileFromUuid(uuid) { - const fetchResponse = await node_fetch_1.default( - // 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 }); + let fetchResponse; + try { + fetchResponse = await node_fetch_1.default( + // 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 }); + } + catch { + // if there's an error, wait a second and try again + await new Promise((resolve) => setTimeout(resolve, 1000)); + return await profileFromUuid(uuid); + } let data; try { data = await fetchResponse.json(); @@ -37,7 +45,15 @@ async function profileFromUuid(uuid) { exports.profileFromUuid = profileFromUuid; async function profileFromUsername(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.mojang.com/users/profiles/minecraft/${username}`, { agent: () => httpsAgent }); + let fetchResponse; + try { + fetchResponse = await node_fetch_1.default(`https://api.mojang.com/users/profiles/minecraft/${username}`, { agent: () => httpsAgent }); + } + catch { + // if there's an error, wait a second and try again + await new Promise((resolve) => setTimeout(resolve, 1000)); + return await profileFromUsername(username); + } let data; try { data = await fetchResponse.json(); |