Skip to content

Commit

Permalink
Merge pull request #2196 from DuckySoLucky/fixErrorInventory
Browse files Browse the repository at this point in the history
feat: error handling for items processing && fix: API endpoints
  • Loading branch information
metalcupcake5 authored Mar 23, 2024
2 parents 04b9fda + e2ef2f9 commit 2654b32
Show file tree
Hide file tree
Showing 26 changed files with 506 additions and 548 deletions.
21 changes: 10 additions & 11 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import * as itemRoute from "./routes/item.js";
import * as headRoute from "./routes/head.js";
import * as leatherRoute from "./routes/leather.js";
import * as potionRoute from "./routes/potion.js";
import * as stats from "./stats.js";
import { SkyCryptError } from "./constants/error.js";

const folderPath = helper.getFolderPath();
Expand Down Expand Up @@ -277,15 +276,12 @@ app.all("/stats/:player/:profile?", async (req, res, next) => {

const paramBingo =
profile.game_mode === "bingo" ? await lib.getBingoProfile(db, paramPlayer, { cacheOnly, debugId }) : null;
const items = await stats.getItems(profile.members[profile.uuid], paramBingo, true, req.cookies.pack, {
cacheOnly,
debugId,
});
const calculated = await lib.getStats(db, profile, paramBingo, allProfiles, items, req.cookies.pack, {
const calculated = await lib.getStats(db, profile, paramBingo, allProfiles, req.cookies.pack, {
cacheOnly,
debugId,
updateLeaderboards: true,
updateGuild: true,
customTextures: true,
});

if (isFoolsDay) {
Expand All @@ -300,7 +296,7 @@ app.all("/stats/:player/:profile?", async (req, res, next) => {
"stats",
{
req,
items,
items: calculated.items,
calculated,
_,
constants,
Expand All @@ -315,7 +311,9 @@ app.all("/stats/:player/:profile?", async (req, res, next) => {
console.debug(`${debugId}: an error has occurred.`);
console.error(err);

await helper.sendWebhookMessage(err, req);
const username = req.params.player;
const profile = req.params.profile;
await helper.sendWebhookMessage(err, { username, profile });

const favorites = parseFavorites(req.cookies.favorite);
res.render(
Expand Down Expand Up @@ -347,9 +345,10 @@ app.all("/stats/:player/:profile?", async (req, res, next) => {
);
} catch (e) {
if (e instanceof SkyCryptError === false) {
if (e.message !== "socket hang up") {
helper.sendWebhookMessage(e, req);
}
const username = req.params.player;
const profile = req.params.profile;

helper.sendWebhookMessage(e, { username, profile });
}

const favorites = parseFavorites(req.cookies.favorite);
Expand Down
28 changes: 12 additions & 16 deletions src/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -1118,23 +1118,19 @@ export async function applyResourcePack(item, packs) {
return item;
}

export async function sendWebhookMessage(e, req) {
const webhookUrl = credentials.discord_webhook;
if (webhookUrl !== undefined && req.params !== undefined) {
let description = "";
const playerUsername = req.params.player;
if (playerUsername) {
description += `Username: \`${playerUsername}\`\n`;
export async function sendWebhookMessage(e, { username, profile }) {
try {
const webhookUrl = credentials.discord_webhook;
if (webhookUrl === undefined || username === undefined) {
return;
}

description += `Options: \`${JSON.stringify(req.params)}\`\n`;

const paramProfile = req.params.profile;
if (paramProfile) {
description += `Profile: \`${paramProfile}\`\n`;
let description = `Username: \`${username}\`\n`;
if (profile) {
description += `Profile: \`${profile}\`\n`;
}

description += `Link: https://sky.shiiyu.moe/stats/${playerUsername}${paramProfile ? `/${paramProfile}` : ""}\n`;
description += `Link: https://sky.shiiyu.moe/stats/${username}${profile ? `/${profile}` : ""}\n`;
description += `\`\`\`${e.stack}\`\`\``;

const embed = {
Expand All @@ -1144,8 +1140,8 @@ export async function sendWebhookMessage(e, req) {
fields: [],
};

await axios.post(webhookUrl, { embeds: [embed] }).catch((error) => {
console.log(error);
});
await axios.post(webhookUrl, { embeds: [embed] });
} catch (e) {
console.error(e);
}
}
50 changes: 14 additions & 36 deletions src/lib.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { getPreDecodedNetworth } from "skyhelper-networth";
import sanitize from "mongo-sanitize";
import retry from "async-retry";
import axios from "axios";
Expand Down Expand Up @@ -58,13 +57,13 @@ export async function getStats(
profile,
bingoProfile,
allProfiles,
items,
packs,
options = {
cacheOnly: false,
debugId: `${helper.getClusterId()}/unknown@getStats`,
updateLeaderboards: false,
updateGuild: false,
customTextures: false,
},
) {
const output = {};
Expand Down Expand Up @@ -160,40 +159,15 @@ export async function getStats(

output.harp_quest = userProfile.quests?.harp_quest || {};

const specialMuseumItems = items.museumItems.specialItems
? items.museumItems.specialItems.map((a) => a.data).flat()
: [];
const normalMuseumItems = items.museumItems.items
? Object.values(items.museumItems.items)
.filter((a) => a && a.data !== undefined && a.borrowing === false)
.map((a) => a.data)
.flat()
: [];

const museumItems = [...normalMuseumItems, ...specialMuseumItems];

const networthItems = {
armor: items.armor?.armor ?? [],
equipment: items.equipment?.equipment ?? [],
wardrobe: items.wardrobe_inventory ?? [],
inventory: items.inventory ?? [],
enderchest: items.enderchest ?? [],
accessories: items.accessory_bag ?? [],
personal_vault: items.personal_vault ?? [],
storage: items.storage ? items.storage.concat(items.storage.map((item) => item.containsItems).flat()) : [],
fishing_bag: items.fishing_bag ?? [],
potion_bag: items.potion_bag ?? [],
candy_inventory: items.candy_bag ?? [],
museum: museumItems,
};

const bank = profile.banking?.balance ?? 0;
const networthOptions = { cache: true, onlyNetworth: true, v2Endpoint: true };

const profileMembers = profile.members;
const uuid = profile.uuid;

const functions = {
items: {
fn: stats.getItems,
args: { userProfile, bingoProfile, customTextures: options.customTextures, packs, options },
promise: true,
},
fairy_souls: { fn: stats.getFairySouls, args: { userProfile, profile } },
skills: { fn: stats.getSkills, args: { userProfile, hypixelProfile, members: profileMembers } },
slayer: { fn: stats.getSlayer, args: { userProfile } },
Expand All @@ -214,11 +188,11 @@ export async function getStats(
user_data: { fn: stats.getUserData, args: { userProfile } },
currencies: { fn: stats.getCurrenciesData, args: { userProfile, profile } },
weight: { fn: stats.getWeight, args: { output }, promise: true },
accessories: { fn: stats.getMissingAccessories, args: { output, items, packs }, promise: true },
accessories: { fn: stats.getMissingAccessories, args: { output, packs }, promise: true, awaitPromises: true },
temp_stats: { fn: stats.getTempStats, args: { userProfile } },
rift: { fn: stats.getRift, args: { userProfile } },
networth: { fn: getPreDecodedNetworth, args: { userProfile, networthItems, bank, networthOptions }, promise: true },
pets: { fn: stats.getPets, args: { userProfile, output, items, profile }, promise: true, awaitPromises: true },
networth: { fn: stats.getNetworth, args: { userProfile, profile, output }, promise: true, awaitPromises: true },
pets: { fn: stats.getPets, args: { userProfile, output, profile }, promise: true, awaitPromises: true },
};

const { results, errors } = await executeFunctions(functions, [userProfile, hypixelProfile, profile.members]);
Expand All @@ -227,7 +201,11 @@ export async function getStats(
output.errors = errors;
if (Object.keys(errors).length > 0) {
for (const error in errors) {
helper.sendWebhookMessage(errors[error], { params: { player: profile.uuid, profile: profile.profile_id } });
const username = profile.uuid;
const profileId = profile.profile_id;

helper.sendWebhookMessage(errors[error], { username, profile: profileId });
console.log(errors[error]);
}
}

Expand Down
13 changes: 7 additions & 6 deletions src/routes/api/accessories.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ router.use(async (req, res, next) => {
const { profile, uuid } = await lib.getProfile(db, req.player, req.profile, req.options);
const userProfile = profile.members[uuid];

const items = await getItems(userProfile, false, undefined, req.options);
const items = await getItems(userProfile, null, false, undefined, req.options);

const accessories = items.accessories
const accessories = items.accessories.accessories
.filter((a) => a.isUnique)
.map((a) => {
return {
id: a.tag.ExtraAttributes.id,
id: helper.getId(a),
rarity: a.rarity,
reforge: a.reforge,
name: a.base_name,
isActive: a.isInactive ? "false" : "true",
name: a.display_name,
recombobulated: a.recombobulated,
enrichment: a.enrichment,
isActive: !a.isInactive,
};
});

Expand Down
37 changes: 9 additions & 28 deletions src/routes/api/armor.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,24 @@ router.use(async (req, res, next) => {
const { profile, uuid } = await lib.getProfile(db, req.player, req.profile, req.options);
const userProfile = profile.members[uuid];

const items = await getItems(userProfile, false, undefined, req.options);
const items = await getItems(userProfile, null, false, undefined, req.options);

const output = [];

for (const armor of items.armor) {
const enchantments = armor.tag.ExtraAttributes.enchantments;
let enchantmentsOutput = enchantments;

const stats = armor.stats;
let statsOutput = stats;

if (enchantments !== undefined) {
enchantmentsOutput = [];

for (const enchantment in enchantments) {
enchantmentsOutput.push(enchantment + "=" + enchantments[enchantment]);
}

enchantmentsOutput = enchantmentsOutput.join(",");
}

if (stats !== undefined) {
statsOutput = [];

for (const stat in stats) {
statsOutput.push(stat + "=" + stats[stat]);
}

statsOutput = statsOutput.join(",");
for (const armor of items.armor?.armor ?? []) {
const armorEnchantments = armor.tag.ExtraAttributes.enchantments;
let enchantmentsOutput;
if (armorEnchantments) {
enchantmentsOutput = Object.entries(armor.tag.ExtraAttributes.enchantments)
.map(([key, value]) => `${key}=${value}`)
.join(",");
}

output.push({
id: helper.getId(armor),
name: armor.display_name,
rarity: armor.rarity,
enchantments: enchantmentsOutput,
stats: statsOutput,
recombobulated: armor.recombobulated,
});
}

Expand Down
35 changes: 15 additions & 20 deletions src/routes/api/cakebag.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,24 @@ router.use(async (req, res, next) => {
const { profile, uuid } = await lib.getProfile(db, req.player, req.profile, { cacheOnly: true });
const userProfile = profile.members[uuid];

const items = await getItems(userProfile, false, undefined, req.options);

const allItems = items.armor.concat(items.inventory, items.accessory_bag, items.enderchest);

const cakeBags = allItems.filter((a) => a?.tag?.ExtraAttributes?.id == "NEW_YEAR_CAKE_BAG");
const items = await getItems(userProfile, null, false, undefined, req.options);

const cakeBags = items.allItems.filter((a) => helper.getId(a) === "NEW_YEAR_CAKE_BAG");
if (cakeBags.length == 0) {
handleError(req, res, new Error("Player has no cake bag"), 404);
} else {
const cakeBag = cakeBags[0];

let cakes = [];

for (const item of cakeBag.containsItems) {
if (item.tag?.ExtraAttributes?.new_years_cake) {
cakes.push({ cake: item.tag.ExtraAttributes.new_years_cake });
}
}

cakes = cakes.sort((a, b) => a.cake - b.cake);

res.send(tableify(cakes));
return handleError(req, res, new Error("Player has no cake bag"), 404);
}

const cakes = cakeBags
.map((a) =>
a.containsItems
.map((b) => b.tag?.ExtraAttributes?.new_years_cake)
.filter((c) => c)
.map((c) => ({ cake: c })),
)
.flat()
.sort((a, b) => a.cake - b.cake);

res.send(tableify(cakes));
} catch (e) {
next(e);
}
Expand Down
23 changes: 12 additions & 11 deletions src/routes/api/collections.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ router.use(async (req, res, next) => {
const { profile, uuid } = await lib.getProfile(db, req.player, req.profile, req.options);

const collections = await stats.getCollections(uuid, profile, req.options.cacheOnly);
const collectionData = Object.values(collections)
.filter((a) => a.collections !== undefined)
.map((a) => a.collections)
.flat();

res.send(
tableify(
Object.keys(collections).map((a) => [
a,
collections[a].name,
collections[a].tier,
collections[a].amount,
collections[a].totalAmount,
]),
),
);
const output = collectionData.map((a) => ({
name: a.name,
tier: a.tier,
amount: a.amount,
totalAmount: a.totalAmount,
}));

res.send(tableify(output));
} catch (e) {
next(e);
}
Expand Down
37 changes: 20 additions & 17 deletions src/routes/api/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,26 @@ router.use(async (req, res, next) => {
const { profile, uuid } = await lib.getProfile(db, req.player, req.profile, req.options);
const userProfile = profile.members[uuid];

const items = await getItems(userProfile, false, undefined, req.options);

const allItems = items.inventory.concat(items.enderchest);

for (const item of allItems) {
if (Array.isArray(item.containsItems)) {
allItems.push(...item.containsItems);
}
}

res.send(
tableify(
allItems
.filter((a) => helper.getId(a).length > 0)
.map((a) => [helper.getId(a), a.Count, a.display_name, a.rarity, a.type]),
),
);
const items = await getItems(userProfile, null, false, undefined, req.options);

const allItems = items.allItems
.concat(
items.allItems
.filter((a) => a.containsItems)
.map((a) => a.containsItems)
.flat(),
)
.filter((a) => a && helper.getId(a))
.map((a) => ({
id: helper.getId(a),
Count: a.Count,
display_name: a.display_name,
rarity: a.rarity,
type: a.type,
location: a.extra ? a.extra.source.toLowerCase() : undefined,
}));

res.send(tableify(allItems));
} catch (e) {
next(e);
}
Expand Down
Loading

0 comments on commit 2654b32

Please sign in to comment.