aboutsummaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2021-04-13 16:30:27 -0500
committerGitHub <noreply@github.com>2021-04-13 16:30:27 -0500
commitac79dfbc6ad6eb56bc814471d49b95f014d3eb5f (patch)
tree600846dd4804c487d16d33dd99ad4073d815e8f3 /build
parentc0d03a8d0c1e75967f48cb27d9c55bc4707af22c (diff)
downloadskyblock-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.js30
-rw-r--r--build/cleaners/skyblock/stats.js1
-rw-r--r--build/constants.js47
-rw-r--r--build/database.js44
-rw-r--r--build/hypixelApi.js10
-rw-r--r--build/mojang.js24
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();