From 02337bdb2d50c67d6fe39b80e7aa8e4f73668104 Mon Sep 17 00:00:00 2001 From: ulysia Date: Sat, 28 Dec 2024 11:23:40 +0100 Subject: [PATCH 01/13] added docker, environment variables, renamed vars --- .dockerignore | 7 + .gitignore | 2 + .prettierrc | 8 + AuctionHandler.js | 238 +++++--- Dockerfile | 9 + README.md | 17 + config.json | 19 +- docker-compose.yml | 12 + index.js | 252 +++++---- package.json | 3 +- pnpm-lock.yaml | 1191 ++++++++++++++++++++++++++++++++++++++++ src/helperFunctions.js | 18 +- 12 files changed, 1567 insertions(+), 209 deletions(-) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 pnpm-lock.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d9d2aad --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +config* +docker* +Docker* +README* +node_modules/ +.* +pnpm-lock* \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1dcef2d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +.env \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b4ecedb --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "parser": "babel-flow", + "bracketSameLine": true +} diff --git a/AuctionHandler.js b/AuctionHandler.js index 234de45..089f949 100644 --- a/AuctionHandler.js +++ b/AuctionHandler.js @@ -1,114 +1,176 @@ -const { default: axios } = require("axios"); -const { getParsed, getProfit, splitNumber, getRawCraft } = require("./src/helperFunctions"); -const { parentPort, workerData } = require("worker_threads"); -const config = require("./config.json"); +const { default: axios } = require('axios'); +const { + getParsed, + getProfit, + splitNumber, + getRawCraft, +} = require('./src/helperFunctions'); +const { parentPort, workerData } = require('worker_threads'); +const config = require('./config.json'); let minProfit = config.data.minSnipeProfit; let minPercentProfit = config.data.minSnipePP; let ignoredAuctions = []; -const { Item } = require("./src/Item"); -const threadsToUse = require("./config.json").data["threadsToUse/speed"]; +const { Item } = require('./src/Item'); +const threadsToUse = require('./config.json').data['threadsToUse/speed']; const promises = []; console.log(`[Worker ${workerData.workerNumber}] Worker started`); -parentPort.on("message", async (message) => { - console.log(`[Worker ${workerData.workerNumber}] Received message: ${message.type}`); - if (message.type === "pageCount") { - await doTask(message.data); - } else if (message.type === "moulberry") { - workerData.itemDatas = message.data; - console.log(`[Worker ${workerData.workerNumber}] Updated item data`); - } +parentPort.on('message', async (message) => { + console.log( + `[Worker ${workerData.workerNumber}] Received message: ${message.type}` + ); + if (message.type === 'pageCount') { + await doTask(message.data); + } else if (message.type === 'moulberry') { + workerData.itemDatas = message.data; + console.log(`[Worker ${workerData.workerNumber}] Updated item data`); + } }); async function parsePage(i) { - console.log(`[Worker ${workerData.workerNumber}] Parsing page ${i}`); - try { - const auctionPage = await axios.get(`https://api.hypixel.net/skyblock/auctions?page=${i}`); - for (const auction of auctionPage.data.auctions) { - if (!auction.bin) continue; - const uuid = auction.uuid; - if (ignoredAuctions.includes(uuid) || config.data.ignoreCategories[auction.category]) continue; - const item = await getParsed(auction.item_bytes); - const extraAtt = item["i"][0].tag.ExtraAttributes; - const itemID = extraAtt.id; - let startingBid = auction.starting_bid; - const itemData = workerData.itemDatas[itemID]; - if (!itemData) continue; - const lbin = itemData.lbin; - const sales = itemData.sales; - const prettyItem = new Item(item.i[0].tag.display.Name, uuid, startingBid, auction.tier, extraAtt.enchantments, - extraAtt.hot_potato_count > 10 ? 10 : extraAtt.hot_potato_count, extraAtt.hot_potato_count > 10 ? - extraAtt.hot_potato_count - 10 : 0, extraAtt.rarity_upgrades === 1, - extraAtt.art_of_war_count === 1, extraAtt.dungeon_item_level, - extraAtt.gems, itemID, auction.category, 0, 0, lbin, sales, auction.item_lore); - const unstableOrMarketManipulated = Math.abs((lbin - itemData.cleanPrice) / lbin) > config.data.maxAvgLbinDiff; - ignoredAuctions.push(uuid); - const rcCost = config.data.includeCraftCost ? getRawCraft(prettyItem, workerData.bazaarData, workerData.itemDatas) : 0; - const carriedByRC = rcCost >= config.data.rawCraftMaxWeightPP * lbin; + console.log(`[Worker ${workerData.workerNumber}] Parsing page ${i}`); + try { + const auctionPage = await axios.get( + `https://api.hypixel.net/skyblock/auctions?page=${i}` + ); + for (const auction of auctionPage.data.auctions) { + if (!auction.bin) continue; + const uuid = auction.uuid; + if ( + ignoredAuctions.includes(uuid) || + config.data.ignoreCategories[auction.category] + ) + continue; + const item = await getParsed(auction.item_bytes); + const extraAtt = item['i'][0].tag.ExtraAttributes; + const itemID = extraAtt.id; + let startingBid = auction.starting_bid; + const itemData = workerData.itemDatas[itemID]; + if (!itemData) continue; + const lbin = itemData.lbin; + const sales = itemData.sales; + const prettyItem = new Item( + item.i[0].tag.display.Name, + uuid, + startingBid, + auction.tier, + extraAtt.enchantments, + extraAtt.hot_potato_count > 10 ? 10 : extraAtt.hot_potato_count, + extraAtt.hot_potato_count > 10 ? extraAtt.hot_potato_count - 10 : 0, + extraAtt.rarity_upgrades === 1, + extraAtt.art_of_war_count === 1, + extraAtt.dungeon_item_level, + extraAtt.gems, + itemID, + auction.category, + 0, + 0, + lbin, + sales, + auction.item_lore + ); + const unstableOrMarketManipulated = + Math.abs((lbin - itemData.cleanPrice) / lbin) > + config.data.maxAvgLbinDiff; + ignoredAuctions.push(uuid); + const rcCost = config.data.includeCraftCost + ? getRawCraft(prettyItem, workerData.bazaarData, workerData.itemDatas) + : 0; + const carriedByRC = rcCost >= config.data.rawCraftMaxWeightPP * lbin; - if (carriedByRC || unstableOrMarketManipulated || sales <= config.data.minSales || !sales) continue; + if ( + carriedByRC || + unstableOrMarketManipulated || + sales <= config.data.minSales || + !sales + ) + continue; - if (config.filters.nameFilter.find((name) => itemID.includes(name)) === undefined) { - if ((lbin + rcCost) - startingBid > minProfit) { - const profitData = getProfit(startingBid, rcCost, lbin); - let auctionType = null; - if (rcCost > (lbin - startingBid) && profitData.snipeProfit < minProfit) { - auctionType = "VALUE"; - } else if (profitData.snipeProfit >= minProfit && rcCost < (lbin - startingBid)) { - auctionType = "SNIPE"; - } else if (profitData.snipeProfit >= minProfit && rcCost > 0) { - auctionType = "BOTH"; - } + if ( + config.filters.itemIDExclusions.find((name) => + itemID.includes(name) + ) === undefined + ) { + if (lbin + rcCost - startingBid > minProfit) { + const profitData = getProfit(startingBid, rcCost, lbin); + let auctionType = null; + if ( + rcCost > lbin - startingBid && + profitData.snipeProfit < minProfit + ) { + auctionType = 'VALUE'; + } else if ( + profitData.snipeProfit >= minProfit && + rcCost < lbin - startingBid + ) { + auctionType = 'SNIPE'; + } else if (profitData.snipeProfit >= minProfit && rcCost > 0) { + auctionType = 'BOTH'; + } - prettyItem.auctionData.ahType = auctionType; + prettyItem.auctionData.ahType = auctionType; - if (auctionType === "VALUE" || auctionType === "BOTH") { - if (profitData.RCProfit > config.data.minCraftProfit && profitData.RCPP > config.data.minCraftPP) { - prettyItem.auctionData.profit = profitData.RCProfit; - prettyItem.auctionData.percentProfit = profitData.RCPP; - parentPort.postMessage(prettyItem); - } - } else { - if (profitData.snipeProfit > minProfit && profitData.snipePP > minPercentProfit) { - prettyItem.auctionData.profit = profitData.snipeProfit; - prettyItem.auctionData.percentProfit = profitData.snipePP; - parentPort.postMessage(prettyItem); - } - } - } + if (auctionType === 'VALUE' || auctionType === 'BOTH') { + if ( + profitData.RCProfit > config.data.minCraftProfit && + profitData.RCPP > config.data.minCraftPP + ) { + prettyItem.auctionData.profit = profitData.RCProfit; + prettyItem.auctionData.percentProfit = profitData.RCPP; + parentPort.postMessage(prettyItem); } + } else { + if ( + profitData.snipeProfit > minProfit && + profitData.snipePP > minPercentProfit + ) { + prettyItem.auctionData.profit = profitData.snipeProfit; + prettyItem.auctionData.percentProfit = profitData.snipePP; + parentPort.postMessage(prettyItem); + } + } } - } catch (error) { - console.error(`[Worker ${workerData.workerNumber}] Error parsing page ${i}:`, error); + } } + } catch (error) { + console.error( + `[Worker ${workerData.workerNumber}] Error parsing page ${i}:`, + error + ); + } } async function doTask(totalPages) { - console.log(`[Worker ${workerData.workerNumber}] Starting task for ${totalPages} pages`); - let startingPage = 0; - const pagePerThread = splitNumber(totalPages, threadsToUse); + console.log( + `[Worker ${workerData.workerNumber}] Starting task for ${totalPages} pages` + ); + let startingPage = 0; + const pagePerThread = splitNumber(totalPages, threadsToUse); - if (workerData.workerNumber !== 0 && startingPage === 0) { - const clonedStarting = pagePerThread.slice(); - clonedStarting.splice(workerData.workerNumber, 9999); - clonedStarting.forEach((pagePer) => { - startingPage += pagePer; - }); - } + if (workerData.workerNumber !== 0 && startingPage === 0) { + const clonedStarting = pagePerThread.slice(); + clonedStarting.splice(workerData.workerNumber, 9999); + clonedStarting.forEach((pagePer) => { + startingPage += pagePer; + }); + } - let pageToStop = parseInt(startingPage) + parseInt(pagePerThread[workerData.workerNumber]); + let pageToStop = + parseInt(startingPage) + parseInt(pagePerThread[workerData.workerNumber]); - if (pageToStop !== totalPages) { - pageToStop -= 1; - } + if (pageToStop !== totalPages) { + pageToStop -= 1; + } - console.log(`[Worker ${workerData.workerNumber}] Processing pages from ${startingPage} to ${pageToStop}`); + console.log( + `[Worker ${workerData.workerNumber}] Processing pages from ${startingPage} to ${pageToStop}` + ); - for (let i = startingPage; i < pageToStop; i++) { - promises.push(parsePage(i)); - } - await Promise.all(promises); - console.log(`[Worker ${workerData.workerNumber}] Finished task`); - parentPort.postMessage("finished"); + for (let i = startingPage; i < pageToStop; i++) { + promises.push(parsePage(i)); + } + await Promise.all(promises); + console.log(`[Worker ${workerData.workerNumber}] Finished task`); + parentPort.postMessage('finished'); } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c1bbdf0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM node:23-alpine3.20 + +COPY . /app + +WORKDIR /app + +RUN npm install + +CMD ["node", "index.js"] \ No newline at end of file diff --git a/README.md b/README.md index 255c96f..3220689 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,20 @@ - Ability to make some high tier enchantments worthless (like Looking 4, Luck 6 etc..) - Bad Enchantment filter - And more.. + +# Setup + +## .env +`.env` file is needed due to docker compose. Even if you are not using docker and docker compose, **.ENV IS NEEDED** +the example .env is +``` +webhook_url= +webhook_name=Flipper +webhook_profile_picture_link=https://cdn.discordapp.com/avatars/486155512568741900/164084b936b4461fe9505398f7383a0e.png?size=4096 +``` +You can also add these as environment variables into your system when running Node or run the app via `node --env-file=.env index.js` + +## config.json +### filters +- itemIDExclusions: exclusion based on itemID (contains, doesnt have to be the full itemID name) +- EnchantThreshold and EnchantThresholdConditionalBypass are used for **Raw Crafting**. I suggest leaving them as they are. diff --git a/config.json b/config.json index 08d6ee7..5b83ee8 100644 --- a/config.json +++ b/config.json @@ -23,13 +23,8 @@ "includeCraftCost": true, "minPriceForRawcraft": 5000000 }, - "webhook": { - "discordWebhookUrl": "WEBHOOK_URL", - "webhookName": "Flipper", - "webhookPFP": "https://cdn.discordapp.com/avatars/486155512568741900/164084b936b4461fe9505398f7383a0e.png?size=4096" - }, "filters": { - "rawCraftIgnoreEnchants": { + "EnchantThresholdConditionalBypass": { "WITHER_": { "growth": 6, "protection": 6 @@ -39,7 +34,7 @@ "protection": 6 }, "NECROMANCER": { - "growth": 6, + "growth": 4, "protection": 6 }, "SHREDDED": { @@ -50,7 +45,7 @@ "protection": 6 } }, - "badEnchants": { + "EnchantThreshold": { "giant_killer": 6, "growth": 6, "power": 6, @@ -63,12 +58,12 @@ "vampirism": 6, "luck": 6, "syphon": 4, - "ultimate_soul_eater": 3, - "ultimate_wise": 4, - "ultimate_wisdom": 4, + "ultimate_soul_eater": 6, + "ultimate_wise": 5, + "ultimate_wisdom": 5, "ultimate_legion": 3 }, - "nameFilter": [ + "itemIDExclusions": [ "SALMON", "PERFECT", "BEASTMASTER", diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f590339 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +--- +services: + hypixel-flipper: + container_name: hypixel-flipper + build: . + restart: unless-stopped + env_file: + - .env + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ./config.json:/app/config.json \ No newline at end of file diff --git a/index.js b/index.js index 8f69656..a4c135c 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,11 @@ -const { default: axios } = require("axios"); -const config = require("./config.json"); -const { WebhookClient, MessageEmbed } = require('discord.js'); -const { Worker } = require("worker_threads"); -const { asyncInterval, addNotation } = require("./src/helperFunctions"); +const { default: axios } = require('axios'); +const config = require('./config.json'); +const { WebhookClient, EmbedBuilder, Embed } = require('discord.js'); +const { Worker } = require('worker_threads'); +const { asyncInterval, addNotation } = require('./src/helperFunctions'); +const { string } = require('prismarine-nbt'); -let threadsToUse = config.data["threadsToUse/speed"] ?? 1; +let threadsToUse = config.data['threadsToUse/speed'] ?? 1; let lastUpdated = 0; let doneWorkers = 0; let startingTime; @@ -14,124 +15,171 @@ const workers = []; const webhookRegex = /https:\/\/discord.com\/api\/webhooks\/(.+)\/(.+)/; const bazaarPrice = { - "RECOMBOBULATOR_3000": 0, - "HOT_POTATO_BOOK": 0, - "FUMING_POTATO_BOOK": 0 + RECOMBOBULATOR_3000: 0, + HOT_POTATO_BOOK: 0, + FUMING_POTATO_BOOK: 0, }; async function initialize() { - const matches = config.webhook.discordWebhookUrl.match(webhookRegex); - if (!matches) return console.log(`[Main thread] Couldn't parse Webhook URL`); - const webhook = new WebhookClient({ id: matches[1], token: matches[2] }); + const matches = process.env.webhook_url.match(webhookRegex); + if (!matches) return console.log(`[Main thread] Couldn't parse Webhook URL`); + const webhook = new WebhookClient({ id: matches[1], token: matches[2] }); - await getBzData(); - await getMoulberry(); - await getLBINs(); + await getBzData(); + await getMoulberry(); + await getLBINs(); - for (let j = 0; j < threadsToUse; j++) { - workers[j] = new Worker('./AuctionHandler.js', { - workerData: { - itemDatas: itemDatas, - bazaarData: bazaarPrice, - workerNumber: j, - maxPrice: maxPrice - } - }); + for (let j = 0; j < threadsToUse; j++) { + workers[j] = new Worker('./AuctionHandler.js', { + workerData: { + itemDatas: itemDatas, + bazaarData: bazaarPrice, + workerNumber: j, + maxPrice: maxPrice, + }, + }); - workers[j].on("message", async (result) => { - if (result.itemData !== undefined) { - let averagePrice = itemDatas[result.itemData.id]?.cleanPrice || "N/A"; - if (result.auctionData.lbin - result.auctionData.price >= config.data.minSnipeProfit && averagePrice - result.auctionData.price >= config.data.minAvgProfit) { - let mustBuyMessage = ''; - const embed = new MessageEmbed() - .setTitle(`**${(result.itemData.name).replace(/§./g, '')}**`) - .setColor("#2e3137") - .setThumbnail(`https://sky.shiiyu.moe/item/${result.itemData.id}`) - .setDescription(`${mustBuyMessage}\nAuction: \`\`\`/viewauction ${result.auctionData.auctionID}\`\`\`\nProfit: \`${addNotation("oneLetters", (result.auctionData.profit))} (${result.auctionData.percentProfit}%)\`\nCost: \`${addNotation("oneLetters", (result.auctionData.price))}\`\nLBIN: \`${addNotation("oneLetters", (result.auctionData.lbin))}\`\nSales/Day: \`${addNotation("oneLetters", result.auctionData.sales)}\`\nType: \`${result.auctionData.ahType}\`\nAverage Price: \`${addNotation("oneLetters", averagePrice)}\``); + workers[j].on('message', async (result) => { + if (result.itemData !== undefined) { + let averagePrice = itemDatas[result.itemData.id]?.cleanPrice || 'N/A'; + if ( + result.auctionData.lbin - result.auctionData.price >= + config.data.minSnipeProfit && + averagePrice - result.auctionData.price >= config.data.minAvgProfit + ) { + let mustBuyMessage = ''; + const embed = new EmbedBuilder() + .setTitle(`**${result.itemData.name.replace(/§./g, '')}**`) + .setColor('#2e3137') + .setThumbnail(`https://sky.shiiyu.moe/item/${result.itemData.id}`) + .setDescription( + `${mustBuyMessage}\nAuction: + \`\`\`/viewauction ${result.auctionData.auctionID}\`\`\` + \nProfit: \`${addNotation( + 'oneLetters', + result.auctionData.profit + )} (${result.auctionData.percentProfit}%)\` + \nCost: \`${addNotation('oneLetters', result.auctionData.price)}\` + \nLBIN: \`${addNotation('oneLetters', result.auctionData.lbin)}\` + \nSales/Day: \`${addNotation( + 'oneLetters', + result.auctionData.sales + )}\` + \nType: \`${result.auctionData.ahType}\` + \nAverage Price: \`${addNotation('oneLetters', averagePrice)}\`` + ); - await webhook.send({ - username: config.webhook.webhookName, - avatarURL: config.webhook.webhookPFP, - embeds: [embed] - }); - } - } else if (result === "finished") { - doneWorkers++; - if (doneWorkers === threadsToUse) { - doneWorkers = 0; - console.log(`Completed in ${(Date.now() - startingTime) / 1000} seconds`); - startingTime = 0; - workers[0].emit("done"); - } - } - }); - } + await webhook.send({ + username: process.env.webhook_name, + avatarURL: process.env.webhook_profile_picture_link, + embeds: [embed], + }); + } + } else if (result === 'finished') { + doneWorkers++; + if (doneWorkers === threadsToUse) { + doneWorkers = 0; + console.log( + `Completed in ${(Date.now() - startingTime) / 1000} seconds` + ); + startingTime = 0; + workers[0].emit('done'); + } + } + }); + } - asyncInterval(async () => { - await getLBINs(); - workers.forEach((worker) => { - worker.postMessage({ type: "moulberry", data: itemDatas }); - }); - }, "lbin", 60000); + asyncInterval( + async () => { + await getLBINs(); + workers.forEach((worker) => { + worker.postMessage({ type: 'moulberry', data: itemDatas }); + }); + }, + 'lbin', + 60000 + ); - asyncInterval(async () => { - await getMoulberry(); - workers.forEach((worker) => { - worker.postMessage({ type: "moulberry", data: itemDatas }); - }); - }, "avg", 60e5); + asyncInterval( + async () => { + await getMoulberry(); + workers.forEach((worker) => { + worker.postMessage({ type: 'moulberry', data: itemDatas }); + }); + }, + 'avg', + 60e5 + ); - asyncInterval(async () => { - return new Promise(async (resolve) => { - const ahFirstPage = await axios.get("https://api.hypixel.net/skyblock/auctions?page=0"); - const totalPages = ahFirstPage.data.totalPages; - if (ahFirstPage.data.lastUpdated === lastUpdated) { - resolve(); - } else { - lastUpdated = ahFirstPage.data.lastUpdated; - startingTime = Date.now(); - console.log("Getting auctions.."); - workers.forEach((worker) => { - worker.postMessage({ type: "pageCount", data: totalPages }); - }); - workers[0].once("done", () => { - resolve(); - }); - } - }); - }, "check", 0); + asyncInterval( + async () => { + return new Promise(async (resolve) => { + const ahFirstPage = await axios.get( + 'https://api.hypixel.net/skyblock/auctions?page=0' + ); + const totalPages = ahFirstPage.data.totalPages; + if (ahFirstPage.data.lastUpdated === lastUpdated) { + resolve(); + } else { + lastUpdated = ahFirstPage.data.lastUpdated; + startingTime = Date.now(); + console.log('Getting auctions..'); + workers.forEach((worker) => { + worker.postMessage({ type: 'pageCount', data: totalPages }); + }); + workers[0].once('done', () => { + resolve(); + }); + } + }); + }, + 'check', + 0 + ); } async function getLBINs() { - const lbins = await axios.get("https://moulberry.codes/lowestbin.json"); - const lbinData = lbins.data; - for (const item of Object.keys(lbinData)) { - if (!itemDatas[item]) itemDatas[item] = {}; - itemDatas[item].lbin = lbinData[item]; - } + const lbins = await axios.get('https://moulberry.codes/lowestbin.json'); + const lbinData = lbins.data; + for (const item of Object.keys(lbinData)) { + if (!itemDatas[item]) itemDatas[item] = {}; + itemDatas[item].lbin = lbinData[item]; + } } async function getMoulberry() { - const moulberryAvgs = await axios.get("https://moulberry.codes/auction_averages/3day.json"); - const avgData = moulberryAvgs.data; + const moulberryAvgs = await axios.get( + 'https://moulberry.codes/auction_averages/3day.json' + ); + const avgData = moulberryAvgs.data; - const cleanPriceAvgs = await axios.get("https://moulberry.codes/auction_averages_lbin/1day.json"); - const cleanPriceData = cleanPriceAvgs.data; + const cleanPriceAvgs = await axios.get( + 'https://moulberry.codes/auction_averages_lbin/1day.json' + ); + const cleanPriceData = cleanPriceAvgs.data; - for (const item of Object.keys(avgData)) { - if (!itemDatas[item]) itemDatas[item] = {}; - const itemInfo = avgData[item]; + for (const item of Object.keys(avgData)) { + if (!itemDatas[item]) itemDatas[item] = {}; + const itemInfo = avgData[item]; - itemDatas[item].sales = itemInfo.sales !== undefined ? itemInfo.sales : 0; - itemDatas[item].cleanPrice = cleanPriceData[item] !== undefined ? Math.round(cleanPriceData[item]) : (itemInfo.clean_price !== undefined ? itemInfo.clean_price : itemInfo.price); - } + itemDatas[item].sales = itemInfo.sales !== undefined ? itemInfo.sales : 0; + itemDatas[item].cleanPrice = + cleanPriceData[item] !== undefined + ? Math.round(cleanPriceData[item]) + : itemInfo.clean_price !== undefined + ? itemInfo.clean_price + : itemInfo.price; + } } async function getBzData() { - const bzData = await axios.get("https://api.hypixel.net/skyblock/bazaar"); - bazaarPrice["RECOMBOBULATOR_3000"] = bzData.data.products.RECOMBOBULATOR_3000.quick_status.buyPrice; - bazaarPrice["HOT_POTATO_BOOK"] = bzData.data.products.HOT_POTATO_BOOK.quick_status.buyPrice; - bazaarPrice["FUMING_POTATO_BOOK"] = bzData.data.products.FUMING_POTATO_BOOK.quick_status.buyPrice; + const bzData = await axios.get('https://api.hypixel.net/skyblock/bazaar'); + bazaarPrice['RECOMBOBULATOR_3000'] = + bzData.data.products.RECOMBOBULATOR_3000.quick_status.buyPrice; + bazaarPrice['HOT_POTATO_BOOK'] = + bzData.data.products.HOT_POTATO_BOOK.quick_status.buyPrice; + bazaarPrice['FUMING_POTATO_BOOK'] = + bzData.data.products.FUMING_POTATO_BOOK.quick_status.buyPrice; } initialize(); diff --git a/package.json b/package.json index cec1a8c..2323c54 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "dependencies": { "axios": "^0.24.0", "copy-paste": "^1.3.0", - "discord.js": "^12.5.3", + "discord.js": "^14.16.3", "express": "^4.17.1", "node-notifier": "^10.0.0", "open": "^8.4.0", @@ -14,7 +14,6 @@ }, "description": "Hypixel Skyblock Auction House Flip Notifier", "main": "index.js", - "devDependencies": {}, "scripts": { "start": "node ." }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..d7e373c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1191 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + axios: + specifier: ^0.24.0 + version: 0.24.0 + copy-paste: + specifier: ^1.3.0 + version: 1.5.3 + discord.js: + specifier: ^14.16.3 + version: 14.16.3 + express: + specifier: ^4.17.1 + version: 4.21.2 + node-notifier: + specifier: ^10.0.0 + version: 10.0.1 + open: + specifier: ^8.4.0 + version: 8.4.2 + prismarine-nbt: + specifier: ^2.0.0 + version: 2.7.0 + socket.io: + specifier: ^4.4.0 + version: 4.8.1 + toastify-js: + specifier: ^1.11.2 + version: 1.12.0 + +packages: + + '@discordjs/builders@1.9.0': + resolution: {integrity: sha512-0zx8DePNVvQibh5ly5kCEei5wtPBIUbSoE9n+91Rlladz4tgtFbJ36PZMxxZrTEOQ7AHMZ/b0crT/0fCy6FTKg==} + engines: {node: '>=18'} + + '@discordjs/collection@1.5.3': + resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/collection@2.1.1': + resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==} + engines: {node: '>=18'} + + '@discordjs/formatters@0.5.0': + resolution: {integrity: sha512-98b3i+Y19RFq1Xke4NkVY46x8KjJQjldHUuEbCqMvp1F5Iq9HgnGpu91jOi/Ufazhty32eRsKnnzS8n4c+L93g==} + engines: {node: '>=18'} + + '@discordjs/rest@2.4.0': + resolution: {integrity: sha512-Xb2irDqNcq+O8F0/k/NaDp7+t091p+acb51iA4bCKfIn+WFWd6HrNvcsSbMMxIR9NjcMZS6NReTKygqiQN+ntw==} + engines: {node: '>=18'} + + '@discordjs/util@1.1.1': + resolution: {integrity: sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==} + engines: {node: '>=18'} + + '@discordjs/ws@1.1.1': + resolution: {integrity: sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==} + engines: {node: '>=16.11.0'} + + '@sapphire/async-queue@1.5.5': + resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@sapphire/shapeshift@4.0.0': + resolution: {integrity: sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==} + engines: {node: '>=v16'} + + '@sapphire/snowflake@3.5.3': + resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@types/cookie@0.4.1': + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + + '@types/node@22.10.2': + resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==} + + '@types/ws@8.5.13': + resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} + + '@vladfrangu/async_event_emitter@2.4.6': + resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + axios@0.24.0: + resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.1: + resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} + engines: {node: '>= 0.4'} + + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} + engines: {node: '>= 0.4'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + copy-paste@1.5.3: + resolution: {integrity: sha512-qOnFo+8l8vemGmdcoCiD7gPTefkXEg2rivYE+EBtuKOj754eFivkGhGAM9e/xqShrpuVE11evSxGnHwVAUK1Iw==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + discord-api-types@0.37.100: + resolution: {integrity: sha512-a8zvUI0GYYwDtScfRd/TtaNBDTXwP5DiDVX7K5OmE+DRT57gBqKnwtOC5Ol8z0mRW8KQfETIgiB8U0YZ9NXiCA==} + + discord-api-types@0.37.83: + resolution: {integrity: sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==} + + discord-api-types@0.37.97: + resolution: {integrity: sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==} + + discord.js@14.16.3: + resolution: {integrity: sha512-EPCWE9OkA9DnFFNrO7Kl1WHHDYFXu3CNVFJg63bfU7hVtjZGyhShwZtSBImINQRWxWP2tgo2XI+QhdXx28r0aA==} + engines: {node: '>=18'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + engine.io@6.6.2: + resolution: {integrity: sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==} + engines: {node: '>=10.2.0'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.2.6: + resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + growly@1.3.0: + resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + + lodash.reduce@4.6.0: + resolution: {integrity: sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + magic-bytes.js@1.10.0: + resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + node-notifier@10.0.1: + resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + + prismarine-nbt@2.7.0: + resolution: {integrity: sha512-Du9OLQAcCj3y29YtewOJbbV4ARaSUEJiTguw0PPQbPBy83f+eCyDRkyBpnXTi/KPyEpgYCzsjGzElevLpFoYGQ==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + protodef-validator@1.4.0: + resolution: {integrity: sha512-2y2coBolqCEuk5Kc3QwO7ThR+/7TZiOit4FrpAgl+vFMvq8w76nDhh09z08e2NQOdrgPLsN2yzXsvRvtADgUZQ==} + hasBin: true + + protodef@1.18.0: + resolution: {integrity: sha512-jO64lkzkh0dYc0AVWCU/GzCKwqhFFIz1kfEz0NBf0RUuRNcmvgKbopabJdfZ6W8NvALdySUXgEhvKDZPhdBwrg==} + engines: {node: '>=14'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + readable-stream@4.6.0: + resolution: {integrity: sha512-cbAdYt0VcnpN2Bekq7PU+k363ZRsPwJoEEJOEtSJQlJXzwaxt3FIo/uL+KeDSGIjJqtkwyge4KQgD2S2kd+CQw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shellwords@0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + socket.io-adapter@2.5.5: + resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + + socket.io@4.8.1: + resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} + engines: {node: '>=10.2.0'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + toastify-js@1.12.0: + resolution: {integrity: sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + ts-mixer@6.0.4: + resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@6.19.8: + resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} + engines: {node: '>=18.17'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + +snapshots: + + '@discordjs/builders@1.9.0': + dependencies: + '@discordjs/formatters': 0.5.0 + '@discordjs/util': 1.1.1 + '@sapphire/shapeshift': 4.0.0 + discord-api-types: 0.37.97 + fast-deep-equal: 3.1.3 + ts-mixer: 6.0.4 + tslib: 2.8.1 + + '@discordjs/collection@1.5.3': {} + + '@discordjs/collection@2.1.1': {} + + '@discordjs/formatters@0.5.0': + dependencies: + discord-api-types: 0.37.97 + + '@discordjs/rest@2.4.0': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/util': 1.1.1 + '@sapphire/async-queue': 1.5.5 + '@sapphire/snowflake': 3.5.3 + '@vladfrangu/async_event_emitter': 2.4.6 + discord-api-types: 0.37.97 + magic-bytes.js: 1.10.0 + tslib: 2.8.1 + undici: 6.19.8 + + '@discordjs/util@1.1.1': {} + + '@discordjs/ws@1.1.1': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/rest': 2.4.0 + '@discordjs/util': 1.1.1 + '@sapphire/async-queue': 1.5.5 + '@types/ws': 8.5.13 + '@vladfrangu/async_event_emitter': 2.4.6 + discord-api-types: 0.37.83 + tslib: 2.8.1 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@sapphire/async-queue@1.5.5': {} + + '@sapphire/shapeshift@4.0.0': + dependencies: + fast-deep-equal: 3.1.3 + lodash: 4.17.21 + + '@sapphire/snowflake@3.5.3': {} + + '@socket.io/component-emitter@3.1.2': {} + + '@types/cookie@0.4.1': {} + + '@types/cors@2.8.17': + dependencies: + '@types/node': 22.10.2 + + '@types/node@22.10.2': + dependencies: + undici-types: 6.20.0 + + '@types/ws@8.5.13': + dependencies: + '@types/node': 22.10.2 + + '@vladfrangu/async_event_emitter@2.4.6': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + array-flatten@1.1.1: {} + + axios@0.24.0: + dependencies: + follow-redirects: 1.15.9 + transitivePeerDependencies: + - debug + + base64-js@1.5.1: {} + + base64id@2.0.0: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.1: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.3: + dependencies: + call-bind-apply-helpers: 1.0.1 + get-intrinsic: 1.2.6 + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.6: {} + + cookie@0.7.1: {} + + cookie@0.7.2: {} + + copy-paste@1.5.3: + dependencies: + iconv-lite: 0.4.24 + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + define-lazy-prop@2.0.0: {} + + depd@2.0.0: {} + + destroy@1.2.0: {} + + discord-api-types@0.37.100: {} + + discord-api-types@0.37.83: {} + + discord-api-types@0.37.97: {} + + discord.js@14.16.3: + dependencies: + '@discordjs/builders': 1.9.0 + '@discordjs/collection': 1.5.3 + '@discordjs/formatters': 0.5.0 + '@discordjs/rest': 2.4.0 + '@discordjs/util': 1.1.1 + '@discordjs/ws': 1.1.1 + '@sapphire/snowflake': 3.5.3 + discord-api-types: 0.37.100 + fast-deep-equal: 3.1.3 + lodash.snakecase: 4.1.1 + tslib: 2.8.1 + undici: 6.19.8 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + engine.io-parser@5.2.3: {} + + engine.io@6.6.2: + dependencies: + '@types/cookie': 0.4.1 + '@types/cors': 2.8.17 + '@types/node': 22.10.2 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.7.2 + cors: 2.8.5 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + + escape-html@1.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + events@3.3.0: {} + + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + follow-redirects@1.15.9: {} + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + function-bind@1.1.2: {} + + get-intrinsic@1.2.6: + dependencies: + call-bind-apply-helpers: 1.0.1 + dunder-proto: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + function-bind: 1.1.2 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + gopd@1.2.0: {} + + growly@1.3.0: {} + + has-symbols@1.1.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + inherits@2.0.4: {} + + ipaddr.js@1.9.1: {} + + is-docker@2.2.1: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isexe@2.0.0: {} + + json-schema-traverse@0.4.1: {} + + lodash.get@4.4.2: {} + + lodash.reduce@4.6.0: {} + + lodash.snakecase@4.1.1: {} + + lodash@4.17.21: {} + + magic-bytes.js@1.10.0: {} + + math-intrinsics@1.1.0: {} + + media-typer@0.3.0: {} + + merge-descriptors@1.0.3: {} + + methods@1.1.2: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + negotiator@0.6.3: {} + + node-notifier@10.0.1: + dependencies: + growly: 1.3.0 + is-wsl: 2.2.0 + semver: 7.6.3 + shellwords: 0.1.1 + uuid: 8.3.2 + which: 2.0.2 + + object-assign@4.1.1: {} + + object-inspect@1.13.3: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + parseurl@1.3.3: {} + + path-to-regexp@0.1.12: {} + + prismarine-nbt@2.7.0: + dependencies: + protodef: 1.18.0 + + process@0.11.10: {} + + protodef-validator@1.4.0: + dependencies: + ajv: 6.12.6 + + protodef@1.18.0: + dependencies: + lodash.get: 4.4.2 + lodash.reduce: 4.6.0 + protodef-validator: 1.4.0 + readable-stream: 4.6.0 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + punycode@2.3.1: {} + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + readable-stream@4.6.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + semver@7.6.3: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + + shellwords@0.1.1: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.3 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + object-inspect: 1.13.3 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + object-inspect: 1.13.3 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.3 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + socket.io-adapter@2.5.5: + dependencies: + debug: 4.3.7 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + socket.io@4.8.1: + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.5 + debug: 4.3.7 + engine.io: 6.6.2 + socket.io-adapter: 2.5.5 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + statuses@2.0.1: {} + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + toastify-js@1.12.0: {} + + toidentifier@1.0.1: {} + + ts-mixer@6.0.4: {} + + tslib@2.8.1: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + undici-types@6.20.0: {} + + undici@6.19.8: {} + + unpipe@1.0.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + utils-merge@1.0.1: {} + + uuid@8.3.2: {} + + vary@1.1.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + ws@8.17.1: {} + + ws@8.18.0: {} diff --git a/src/helperFunctions.js b/src/helperFunctions.js index 890eb29..f546094 100644 --- a/src/helperFunctions.js +++ b/src/helperFunctions.js @@ -90,17 +90,25 @@ function splitNumber (num = 1, parts = 1) { function getRawCraft(item, bazaarPrice, lbins) { let price = 0 - const ignoreMatch = Object.keys(config.filters.rawCraftIgnoreEnchants).find((key) => { - if (item.itemData.id.includes(key)) return true - }) + const ignoreMatch = Object.keys( + config.filters.EnchantThresholdConditionalBypass + ).find((key) => { + if (item.itemData.id.includes(key)) return true; + }); if (item.auctionData.lbin < config.data.minPriceForRawcraft) return 0 let isInIgnore = ignoreMatch ? ignoreMatch : false if (item.itemData.enchants && !item.itemData.id.includes(';')) { for (const enchant of Object.keys(item.itemData.enchants)) { const degree = item.itemData.enchants[enchant] - const badEnchant = typeof config.filters.badEnchants[enchant] === 'number' ? degree >= config.filters.badEnchants[enchant] : false + const badEnchant = + typeof config.filters.EnchantThreshold[enchant] === 'number' + ? degree >= config.filters.EnchantThreshold[enchant] + : false; if (isInIgnore) { - const enchantMinValue = config.filters.rawCraftIgnoreEnchants[ignoreMatch][enchant] + const enchantMinValue = + config.filters.EnchantThresholdConditionalBypass[ignoreMatch][ + enchant + ]; if (enchantMinValue >= degree) continue } if (badEnchant) { From 95c39eca7c3394ffac0fc38dbe4b852c5ec0ec57 Mon Sep 17 00:00:00 2001 From: ulysia Date: Sat, 28 Dec 2024 11:23:57 +0100 Subject: [PATCH 02/13] renamed service and container --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f590339..1c0bfef 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ --- services: - hypixel-flipper: - container_name: hypixel-flipper + hypixel-auc-notifier: + container_name: hypixel-auc-notifier build: . restart: unless-stopped env_file: From 470f9e0a25cf0a79e20adccf3267f43f62547701 Mon Sep 17 00:00:00 2001 From: ulysia Date: Sat, 28 Dec 2024 11:25:31 +0100 Subject: [PATCH 03/13] uppercased environment variables --- README.md | 11 ++++++++--- index.js | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3220689..8b13d04 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,14 @@ `.env` file is needed due to docker compose. Even if you are not using docker and docker compose, **.ENV IS NEEDED** the example .env is ``` -webhook_url= -webhook_name=Flipper -webhook_profile_picture_link=https://cdn.discordapp.com/avatars/486155512568741900/164084b936b4461fe9505398f7383a0e.png?size=4096 +WEBHOOK_URL= +<<<<<<< HEAD +WEBHOOK_NAME=Auction_Notifier +WEBHOOK_PROFILE_PICTURE= +======= +WEBHOOK_NAME=Flipper +WEBHOOK_PROFILE_PICTURE=https://cdn.discordapp.com/avatars/486155512568741900/164084b936b4461fe9505398f7383a0e.png?size=4096 +>>>>>>> aad843d (uppercased environment variables) ``` You can also add these as environment variables into your system when running Node or run the app via `node --env-file=.env index.js` diff --git a/index.js b/index.js index a4c135c..e17cc67 100644 --- a/index.js +++ b/index.js @@ -21,7 +21,7 @@ const bazaarPrice = { }; async function initialize() { - const matches = process.env.webhook_url.match(webhookRegex); + const matches = process.env.WEBHOOK_URL.match(webhookRegex); if (!matches) return console.log(`[Main thread] Couldn't parse Webhook URL`); const webhook = new WebhookClient({ id: matches[1], token: matches[2] }); @@ -70,8 +70,8 @@ async function initialize() { ); await webhook.send({ - username: process.env.webhook_name, - avatarURL: process.env.webhook_profile_picture_link, + username: process.env.WEBHOOK_NAME, + avatarURL: process.env.WEBHOOK_PROFILE_PICTURE, embeds: [embed], }); } From e4495938ff4e1af27e35d82a333dc76fa9d06587 Mon Sep 17 00:00:00 2001 From: ulysia Date: Sat, 28 Dec 2024 11:25:54 +0100 Subject: [PATCH 04/13] fixed formatting 001 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b13d04..17e88ff 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ ## .env `.env` file is needed due to docker compose. Even if you are not using docker and docker compose, **.ENV IS NEEDED** -the example .env is + +__the example .env is__ ``` WEBHOOK_URL= <<<<<<< HEAD From b756637cad1bf0464aca035b10bf7f04bba249c1 Mon Sep 17 00:00:00 2001 From: ulysia Date: Sat, 28 Dec 2024 11:26:10 +0100 Subject: [PATCH 05/13] added pnpm lock to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1dcef2d..7ad6f33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -.env \ No newline at end of file +.env +pnpm-lock* \ No newline at end of file From e9d2c9a6cf7018aa47d14a48397e56b562ce2441 Mon Sep 17 00:00:00 2001 From: ulysia Date: Fri, 27 Dec 2024 01:32:46 +0100 Subject: [PATCH 06/13] Delete pnpm-lock.yaml --- pnpm-lock.yaml | 1191 ------------------------------------------------ 1 file changed, 1191 deletions(-) delete mode 100644 pnpm-lock.yaml diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index d7e373c..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,1191 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - axios: - specifier: ^0.24.0 - version: 0.24.0 - copy-paste: - specifier: ^1.3.0 - version: 1.5.3 - discord.js: - specifier: ^14.16.3 - version: 14.16.3 - express: - specifier: ^4.17.1 - version: 4.21.2 - node-notifier: - specifier: ^10.0.0 - version: 10.0.1 - open: - specifier: ^8.4.0 - version: 8.4.2 - prismarine-nbt: - specifier: ^2.0.0 - version: 2.7.0 - socket.io: - specifier: ^4.4.0 - version: 4.8.1 - toastify-js: - specifier: ^1.11.2 - version: 1.12.0 - -packages: - - '@discordjs/builders@1.9.0': - resolution: {integrity: sha512-0zx8DePNVvQibh5ly5kCEei5wtPBIUbSoE9n+91Rlladz4tgtFbJ36PZMxxZrTEOQ7AHMZ/b0crT/0fCy6FTKg==} - engines: {node: '>=18'} - - '@discordjs/collection@1.5.3': - resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==} - engines: {node: '>=16.11.0'} - - '@discordjs/collection@2.1.1': - resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==} - engines: {node: '>=18'} - - '@discordjs/formatters@0.5.0': - resolution: {integrity: sha512-98b3i+Y19RFq1Xke4NkVY46x8KjJQjldHUuEbCqMvp1F5Iq9HgnGpu91jOi/Ufazhty32eRsKnnzS8n4c+L93g==} - engines: {node: '>=18'} - - '@discordjs/rest@2.4.0': - resolution: {integrity: sha512-Xb2irDqNcq+O8F0/k/NaDp7+t091p+acb51iA4bCKfIn+WFWd6HrNvcsSbMMxIR9NjcMZS6NReTKygqiQN+ntw==} - engines: {node: '>=18'} - - '@discordjs/util@1.1.1': - resolution: {integrity: sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==} - engines: {node: '>=18'} - - '@discordjs/ws@1.1.1': - resolution: {integrity: sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==} - engines: {node: '>=16.11.0'} - - '@sapphire/async-queue@1.5.5': - resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} - engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - - '@sapphire/shapeshift@4.0.0': - resolution: {integrity: sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==} - engines: {node: '>=v16'} - - '@sapphire/snowflake@3.5.3': - resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==} - engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - - '@socket.io/component-emitter@3.1.2': - resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - - '@types/cookie@0.4.1': - resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} - - '@types/cors@2.8.17': - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - - '@types/node@22.10.2': - resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==} - - '@types/ws@8.5.13': - resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} - - '@vladfrangu/async_event_emitter@2.4.6': - resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==} - engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - - abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - - accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - - axios@0.24.0: - resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - base64id@2.0.0: - resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} - engines: {node: ^4.5.0 || >= 5.9} - - body-parser@1.20.3: - resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - call-bind-apply-helpers@1.0.1: - resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} - engines: {node: '>= 0.4'} - - call-bound@1.0.3: - resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} - engines: {node: '>= 0.4'} - - content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - - cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - - cookie@0.7.1: - resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} - engines: {node: '>= 0.6'} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - - copy-paste@1.5.3: - resolution: {integrity: sha512-qOnFo+8l8vemGmdcoCiD7gPTefkXEg2rivYE+EBtuKOj754eFivkGhGAM9e/xqShrpuVE11evSxGnHwVAUK1Iw==} - - cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - - debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - discord-api-types@0.37.100: - resolution: {integrity: sha512-a8zvUI0GYYwDtScfRd/TtaNBDTXwP5DiDVX7K5OmE+DRT57gBqKnwtOC5Ol8z0mRW8KQfETIgiB8U0YZ9NXiCA==} - - discord-api-types@0.37.83: - resolution: {integrity: sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==} - - discord-api-types@0.37.97: - resolution: {integrity: sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==} - - discord.js@14.16.3: - resolution: {integrity: sha512-EPCWE9OkA9DnFFNrO7Kl1WHHDYFXu3CNVFJg63bfU7hVtjZGyhShwZtSBImINQRWxWP2tgo2XI+QhdXx28r0aA==} - engines: {node: '>=18'} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} - - engine.io-parser@5.2.3: - resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} - engines: {node: '>=10.0.0'} - - engine.io@6.6.2: - resolution: {integrity: sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==} - engines: {node: '>=10.2.0'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - - event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - - express@4.21.2: - resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} - engines: {node: '>= 0.10.0'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - finalhandler@1.3.1: - resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} - engines: {node: '>= 0.8'} - - follow-redirects@1.15.9: - resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - - fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - get-intrinsic@1.2.6: - resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==} - engines: {node: '>= 0.4'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - growly@1.3.0: - resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - lodash.get@4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - - lodash.reduce@4.6.0: - resolution: {integrity: sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw==} - - lodash.snakecase@4.1.1: - resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - magic-bytes.js@1.10.0: - resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==} - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - - merge-descriptors@1.0.3: - resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} - - methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - - ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - - node-notifier@10.0.1: - resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} - engines: {node: '>= 0.4'} - - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - - open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - - path-to-regexp@0.1.12: - resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} - - prismarine-nbt@2.7.0: - resolution: {integrity: sha512-Du9OLQAcCj3y29YtewOJbbV4ARaSUEJiTguw0PPQbPBy83f+eCyDRkyBpnXTi/KPyEpgYCzsjGzElevLpFoYGQ==} - - process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - - protodef-validator@1.4.0: - resolution: {integrity: sha512-2y2coBolqCEuk5Kc3QwO7ThR+/7TZiOit4FrpAgl+vFMvq8w76nDhh09z08e2NQOdrgPLsN2yzXsvRvtADgUZQ==} - hasBin: true - - protodef@1.18.0: - resolution: {integrity: sha512-jO64lkzkh0dYc0AVWCU/GzCKwqhFFIz1kfEz0NBf0RUuRNcmvgKbopabJdfZ6W8NvALdySUXgEhvKDZPhdBwrg==} - engines: {node: '>=14'} - - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - qs@6.13.0: - resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} - engines: {node: '>=0.6'} - - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - - readable-stream@4.6.0: - resolution: {integrity: sha512-cbAdYt0VcnpN2Bekq7PU+k363ZRsPwJoEEJOEtSJQlJXzwaxt3FIo/uL+KeDSGIjJqtkwyge4KQgD2S2kd+CQw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - send@0.19.0: - resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} - engines: {node: '>= 0.8.0'} - - serve-static@1.16.2: - resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} - engines: {node: '>= 0.8.0'} - - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - shellwords@0.1.1: - resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} - - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - - socket.io-adapter@2.5.5: - resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} - - socket.io-parser@4.2.4: - resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} - engines: {node: '>=10.0.0'} - - socket.io@4.8.1: - resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} - engines: {node: '>=10.2.0'} - - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - toastify-js@1.12.0: - resolution: {integrity: sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==} - - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - - ts-mixer@6.0.4: - resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - - undici@6.19.8: - resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} - engines: {node: '>=18.17'} - - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - -snapshots: - - '@discordjs/builders@1.9.0': - dependencies: - '@discordjs/formatters': 0.5.0 - '@discordjs/util': 1.1.1 - '@sapphire/shapeshift': 4.0.0 - discord-api-types: 0.37.97 - fast-deep-equal: 3.1.3 - ts-mixer: 6.0.4 - tslib: 2.8.1 - - '@discordjs/collection@1.5.3': {} - - '@discordjs/collection@2.1.1': {} - - '@discordjs/formatters@0.5.0': - dependencies: - discord-api-types: 0.37.97 - - '@discordjs/rest@2.4.0': - dependencies: - '@discordjs/collection': 2.1.1 - '@discordjs/util': 1.1.1 - '@sapphire/async-queue': 1.5.5 - '@sapphire/snowflake': 3.5.3 - '@vladfrangu/async_event_emitter': 2.4.6 - discord-api-types: 0.37.97 - magic-bytes.js: 1.10.0 - tslib: 2.8.1 - undici: 6.19.8 - - '@discordjs/util@1.1.1': {} - - '@discordjs/ws@1.1.1': - dependencies: - '@discordjs/collection': 2.1.1 - '@discordjs/rest': 2.4.0 - '@discordjs/util': 1.1.1 - '@sapphire/async-queue': 1.5.5 - '@types/ws': 8.5.13 - '@vladfrangu/async_event_emitter': 2.4.6 - discord-api-types: 0.37.83 - tslib: 2.8.1 - ws: 8.18.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@sapphire/async-queue@1.5.5': {} - - '@sapphire/shapeshift@4.0.0': - dependencies: - fast-deep-equal: 3.1.3 - lodash: 4.17.21 - - '@sapphire/snowflake@3.5.3': {} - - '@socket.io/component-emitter@3.1.2': {} - - '@types/cookie@0.4.1': {} - - '@types/cors@2.8.17': - dependencies: - '@types/node': 22.10.2 - - '@types/node@22.10.2': - dependencies: - undici-types: 6.20.0 - - '@types/ws@8.5.13': - dependencies: - '@types/node': 22.10.2 - - '@vladfrangu/async_event_emitter@2.4.6': {} - - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 - - accepts@1.3.8: - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - array-flatten@1.1.1: {} - - axios@0.24.0: - dependencies: - follow-redirects: 1.15.9 - transitivePeerDependencies: - - debug - - base64-js@1.5.1: {} - - base64id@2.0.0: {} - - body-parser@1.20.3: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.13.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bytes@3.1.2: {} - - call-bind-apply-helpers@1.0.1: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bound@1.0.3: - dependencies: - call-bind-apply-helpers: 1.0.1 - get-intrinsic: 1.2.6 - - content-disposition@0.5.4: - dependencies: - safe-buffer: 5.2.1 - - content-type@1.0.5: {} - - cookie-signature@1.0.6: {} - - cookie@0.7.1: {} - - cookie@0.7.2: {} - - copy-paste@1.5.3: - dependencies: - iconv-lite: 0.4.24 - - cors@2.8.5: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - - debug@2.6.9: - dependencies: - ms: 2.0.0 - - debug@4.3.7: - dependencies: - ms: 2.1.3 - - define-lazy-prop@2.0.0: {} - - depd@2.0.0: {} - - destroy@1.2.0: {} - - discord-api-types@0.37.100: {} - - discord-api-types@0.37.83: {} - - discord-api-types@0.37.97: {} - - discord.js@14.16.3: - dependencies: - '@discordjs/builders': 1.9.0 - '@discordjs/collection': 1.5.3 - '@discordjs/formatters': 0.5.0 - '@discordjs/rest': 2.4.0 - '@discordjs/util': 1.1.1 - '@discordjs/ws': 1.1.1 - '@sapphire/snowflake': 3.5.3 - discord-api-types: 0.37.100 - fast-deep-equal: 3.1.3 - lodash.snakecase: 4.1.1 - tslib: 2.8.1 - undici: 6.19.8 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - ee-first@1.1.1: {} - - encodeurl@1.0.2: {} - - encodeurl@2.0.0: {} - - engine.io-parser@5.2.3: {} - - engine.io@6.6.2: - dependencies: - '@types/cookie': 0.4.1 - '@types/cors': 2.8.17 - '@types/node': 22.10.2 - accepts: 1.3.8 - base64id: 2.0.0 - cookie: 0.7.2 - cors: 2.8.5 - debug: 4.3.7 - engine.io-parser: 5.2.3 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-object-atoms@1.0.0: - dependencies: - es-errors: 1.3.0 - - escape-html@1.0.3: {} - - etag@1.8.1: {} - - event-target-shim@5.0.1: {} - - events@3.3.0: {} - - express@4.21.2: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.3 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.7.1 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.3.1 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.3 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.12 - proxy-addr: 2.0.7 - qs: 6.13.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.19.0 - serve-static: 1.16.2 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - fast-deep-equal@3.1.3: {} - - fast-json-stable-stringify@2.1.0: {} - - finalhandler@1.3.1: - dependencies: - debug: 2.6.9 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - follow-redirects@1.15.9: {} - - forwarded@0.2.0: {} - - fresh@0.5.2: {} - - function-bind@1.1.2: {} - - get-intrinsic@1.2.6: - dependencies: - call-bind-apply-helpers: 1.0.1 - dunder-proto: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - function-bind: 1.1.2 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - gopd@1.2.0: {} - - growly@1.3.0: {} - - has-symbols@1.1.0: {} - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - http-errors@2.0.0: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - - ieee754@1.2.1: {} - - inherits@2.0.4: {} - - ipaddr.js@1.9.1: {} - - is-docker@2.2.1: {} - - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - - isexe@2.0.0: {} - - json-schema-traverse@0.4.1: {} - - lodash.get@4.4.2: {} - - lodash.reduce@4.6.0: {} - - lodash.snakecase@4.1.1: {} - - lodash@4.17.21: {} - - magic-bytes.js@1.10.0: {} - - math-intrinsics@1.1.0: {} - - media-typer@0.3.0: {} - - merge-descriptors@1.0.3: {} - - methods@1.1.2: {} - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mime@1.6.0: {} - - ms@2.0.0: {} - - ms@2.1.3: {} - - negotiator@0.6.3: {} - - node-notifier@10.0.1: - dependencies: - growly: 1.3.0 - is-wsl: 2.2.0 - semver: 7.6.3 - shellwords: 0.1.1 - uuid: 8.3.2 - which: 2.0.2 - - object-assign@4.1.1: {} - - object-inspect@1.13.3: {} - - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - - open@8.4.2: - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - - parseurl@1.3.3: {} - - path-to-regexp@0.1.12: {} - - prismarine-nbt@2.7.0: - dependencies: - protodef: 1.18.0 - - process@0.11.10: {} - - protodef-validator@1.4.0: - dependencies: - ajv: 6.12.6 - - protodef@1.18.0: - dependencies: - lodash.get: 4.4.2 - lodash.reduce: 4.6.0 - protodef-validator: 1.4.0 - readable-stream: 4.6.0 - - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - - punycode@2.3.1: {} - - qs@6.13.0: - dependencies: - side-channel: 1.1.0 - - range-parser@1.2.1: {} - - raw-body@2.5.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - - readable-stream@4.6.0: - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 - - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - - semver@7.6.3: {} - - send@0.19.0: - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - - serve-static@1.16.2: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.19.0 - transitivePeerDependencies: - - supports-color - - setprototypeof@1.2.0: {} - - shellwords@0.1.1: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.6 - object-inspect: 1.13.3 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.6 - object-inspect: 1.13.3 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.3 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - socket.io-adapter@2.5.5: - dependencies: - debug: 4.3.7 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - socket.io-parser@4.2.4: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - - socket.io@4.8.1: - dependencies: - accepts: 1.3.8 - base64id: 2.0.0 - cors: 2.8.5 - debug: 4.3.7 - engine.io: 6.6.2 - socket.io-adapter: 2.5.5 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - statuses@2.0.1: {} - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - toastify-js@1.12.0: {} - - toidentifier@1.0.1: {} - - ts-mixer@6.0.4: {} - - tslib@2.8.1: {} - - type-is@1.6.18: - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - - undici-types@6.20.0: {} - - undici@6.19.8: {} - - unpipe@1.0.0: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - utils-merge@1.0.1: {} - - uuid@8.3.2: {} - - vary@1.1.2: {} - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - ws@8.17.1: {} - - ws@8.18.0: {} From 97ac5bf9f1e4c44fa79bb21db463c32d6f15f2d7 Mon Sep 17 00:00:00 2001 From: ulysia Date: Fri, 27 Dec 2024 21:17:59 +0100 Subject: [PATCH 07/13] mayhaps functioning TS conversion --- .dockerignore | 3 +- .gitignore | 3 +- .prettierrc | 7 +- AuctionHandler.js => AuctionHandler.worker.ts | 40 +-- Dockerfile | 4 +- docker-compose.yml | 6 +- env.d.ts | 10 + index.js => index.ts | 25 +- package.json | 39 +-- src/Item.js | 28 -- src/Item.ts | 78 ++++++ src/configLoader.ts | 41 +++ src/helperFunctions.js | 159 ----------- src/helperFunctions.ts | 247 ++++++++++++++++++ tsconfig.json | 19 ++ 15 files changed, 467 insertions(+), 242 deletions(-) rename AuctionHandler.js => AuctionHandler.worker.ts (85%) create mode 100644 env.d.ts rename index.js => index.ts (91%) delete mode 100644 src/Item.js create mode 100644 src/Item.ts create mode 100644 src/configLoader.ts delete mode 100644 src/helperFunctions.js create mode 100644 src/helperFunctions.ts create mode 100644 tsconfig.json diff --git a/.dockerignore b/.dockerignore index d9d2aad..7bd6c38 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,4 +4,5 @@ Docker* README* node_modules/ .* -pnpm-lock* \ No newline at end of file +pnpm-lock* +dist \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7ad6f33..d1319a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules .env -pnpm-lock* \ No newline at end of file +pnpm-lock* +dist \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index b4ecedb..a383926 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,9 @@ { - "trailingComma": "es5", + "trailingComma": "none", "tabWidth": 2, "semi": true, "singleQuote": true, - "parser": "babel-flow", - "bracketSameLine": true + "parser": "babel-ts", + "bracketSameLine": true, + "printWidth": 120 } diff --git a/AuctionHandler.js b/AuctionHandler.worker.ts similarity index 85% rename from AuctionHandler.js rename to AuctionHandler.worker.ts index 089f949..2a90d06 100644 --- a/AuctionHandler.js +++ b/AuctionHandler.worker.ts @@ -1,18 +1,21 @@ -const { default: axios } = require('axios'); -const { - getParsed, - getProfit, - splitNumber, - getRawCraft, -} = require('./src/helperFunctions'); -const { parentPort, workerData } = require('worker_threads'); -const config = require('./config.json'); +import axios from 'axios'; +import { getParsed, getProfit, splitNumber, getRawCraft } from './src/helperFunctions'; +import { parentPort, workerData, isMainThread } from 'worker_threads'; +import { Item } from './src/Item'; + +import { loadConfig } from './src/configLoader'; +const config = loadConfig(); + +if (isMainThread || !parentPort) { + throw new Error('This module can only be run in a Worker thread.'); +} + +const threadsToUse: number = config.data['threadsToUse/speed']; + let minProfit = config.data.minSnipeProfit; let minPercentProfit = config.data.minSnipePP; -let ignoredAuctions = []; -const { Item } = require('./src/Item'); -const threadsToUse = require('./config.json').data['threadsToUse/speed']; -const promises = []; +let ignoredAuctions: any[] = []; +const promises: Promise[] = []; console.log(`[Worker ${workerData.workerNumber}] Worker started`); @@ -94,7 +97,7 @@ async function parsePage(i) { ) { if (lbin + rcCost - startingBid > minProfit) { const profitData = getProfit(startingBid, rcCost, lbin); - let auctionType = null; + let auctionType: string | null = null; if ( rcCost > lbin - startingBid && profitData.snipeProfit < minProfit @@ -118,7 +121,7 @@ async function parsePage(i) { ) { prettyItem.auctionData.profit = profitData.RCProfit; prettyItem.auctionData.percentProfit = profitData.RCPP; - parentPort.postMessage(prettyItem); + parentPort!.postMessage(prettyItem); } } else { if ( @@ -127,7 +130,7 @@ async function parsePage(i) { ) { prettyItem.auctionData.profit = profitData.snipeProfit; prettyItem.auctionData.percentProfit = profitData.snipePP; - parentPort.postMessage(prettyItem); + parentPort!.postMessage(prettyItem); } } } @@ -156,8 +159,7 @@ async function doTask(totalPages) { }); } - let pageToStop = - parseInt(startingPage) + parseInt(pagePerThread[workerData.workerNumber]); + let pageToStop = startingPage + pagePerThread[workerData.workerNumber]; if (pageToStop !== totalPages) { pageToStop -= 1; @@ -172,5 +174,5 @@ async function doTask(totalPages) { } await Promise.all(promises); console.log(`[Worker ${workerData.workerNumber}] Finished task`); - parentPort.postMessage('finished'); + parentPort!.postMessage('finished'); } diff --git a/Dockerfile b/Dockerfile index c1bbdf0..607e2fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,4 +6,6 @@ WORKDIR /app RUN npm install -CMD ["node", "index.js"] \ No newline at end of file +RUN npm run build + +CMD npm start \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 1c0bfef..b5ffae7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,14 @@ --- services: - hypixel-auc-notifier: + bot: container_name: hypixel-auc-notifier build: . restart: unless-stopped env_file: - .env + environment: + NODE_ENV: "production" volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - - ./config.json:/app/config.json \ No newline at end of file + - ./config.json:/app/dist/src/config.json \ No newline at end of file diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..e1914a0 --- /dev/null +++ b/env.d.ts @@ -0,0 +1,10 @@ +declare global { + namespace NodeJS { + interface ProcessEnv { + WEBHOOK_URL: string; + WEBHOOK_NAME: string; + WEBHOOK_PROFILE_PICTURE: string; + } + } +} +export { }; diff --git a/index.js b/index.ts similarity index 91% rename from index.js rename to index.ts index e17cc67..fb9faee 100644 --- a/index.js +++ b/index.ts @@ -1,9 +1,12 @@ -const { default: axios } = require('axios'); -const config = require('./config.json'); -const { WebhookClient, EmbedBuilder, Embed } = require('discord.js'); -const { Worker } = require('worker_threads'); -const { asyncInterval, addNotation } = require('./src/helperFunctions'); -const { string } = require('prismarine-nbt'); +import axios from 'axios'; +import { WebhookClient, EmbedBuilder, Embed } from 'discord.js'; +import { Worker } from 'worker_threads'; +import { asyncInterval, addNotation } from './src/helperFunctions'; +import { string } from 'prismarine-nbt'; + +import { loadConfig } from './src/configLoader'; +const config = loadConfig(); + let threadsToUse = config.data['threadsToUse/speed'] ?? 1; let lastUpdated = 0; @@ -11,7 +14,7 @@ let doneWorkers = 0; let startingTime; let maxPrice = 0; let itemDatas = {}; -const workers = []; +const workers: Worker[] = []; const webhookRegex = /https:\/\/discord.com\/api\/webhooks\/(.+)\/(.+)/; const bazaarPrice = { @@ -30,7 +33,7 @@ async function initialize() { await getLBINs(); for (let j = 0; j < threadsToUse; j++) { - workers[j] = new Worker('./AuctionHandler.js', { + workers[j] = new Worker('./AuctionHandler.worker.ts', { workerData: { itemDatas: itemDatas, bazaarData: bazaarPrice, @@ -44,7 +47,7 @@ async function initialize() { let averagePrice = itemDatas[result.itemData.id]?.cleanPrice || 'N/A'; if ( result.auctionData.lbin - result.auctionData.price >= - config.data.minSnipeProfit && + config.data.minSnipeProfit && averagePrice - result.auctionData.price >= config.data.minAvgProfit ) { let mustBuyMessage = ''; @@ -167,8 +170,8 @@ async function getMoulberry() { cleanPriceData[item] !== undefined ? Math.round(cleanPriceData[item]) : itemInfo.clean_price !== undefined - ? itemInfo.clean_price - : itemInfo.price; + ? itemInfo.clean_price + : itemInfo.price; } } diff --git a/package.json b/package.json index 2323c54..7266540 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,27 @@ { "name": "hypixel-auction-flipper", - "version": "0.6.9", - "dependencies": { - "axios": "^0.24.0", - "copy-paste": "^1.3.0", - "discord.js": "^14.16.3", - "express": "^4.17.1", - "node-notifier": "^10.0.0", - "open": "^8.4.0", - "prismarine-nbt": "^2.0.0", - "socket.io": "^4.4.0", - "toastify-js": "^1.11.2" - }, + "version": "1.0.0", "description": "Hypixel Skyblock Auction House Flip Notifier", - "main": "index.js", - "scripts": { - "start": "node ." - }, + "main": "dist/index.js", + "author": "DuckySoLucky + MashClashXD + Ulysia + Sol", "keywords": [], - "author": "DuckySoLucky + MashClashXD" + "scripts": { + "build": "tsc", + "start": "node dist/index.js", + "dev": "ts-node index.ts" + }, + "dependencies": { + "@types/toastify-js": "^1.12.3", + "axios": "^0.24.0", + "copy-paste": "^1.5.3", + "discord.js": "^14.16.3", + "express": "^4.21.2", + "node-notifier": "^10.0.1", + "open": "^8.4.2", + "prismarine-nbt": "^2.7.0", + "socket.io": "^4.8.1", + "toastify-js": "^1.12.0", + "ts-node": "^10.9.2", + "typescript": "^5.7.2" + } } diff --git a/src/Item.js b/src/Item.js deleted file mode 100644 index 27b0717..0000000 --- a/src/Item.js +++ /dev/null @@ -1,28 +0,0 @@ -function Item(name, auctionID, price, rarity, enchants, hpbs, fpbs, recomb, artofwar, stars, gemstones, id, category, profit, percentProfit, lbin, sales, lore) { - this.itemData = { - "name": name, - "id": id, - "stars": stars, - "rarity": rarity, - "recomb": recomb, - "enchants": enchants, - "hpbs": hpbs, - "fpbs": fpbs, - "gemstones": gemstones, - "aow": artofwar, - "lore": lore - } - this.auctionData = { - "auctionID": auctionID, - "category": category, - "sales": sales, - "price": price, - "profit": profit, - "percentProfit": percentProfit, - "lbin": lbin - } -} - -module.exports = { - Item -} \ No newline at end of file diff --git a/src/Item.ts b/src/Item.ts new file mode 100644 index 0000000..ee054a7 --- /dev/null +++ b/src/Item.ts @@ -0,0 +1,78 @@ +// item.ts + +export interface ItemData { + name: string; + id: string; + stars: number; + rarity: string; + recomb: boolean; + enchants: string[]; + hpbs: number; + fpbs: number; + gemstones: string[]; + aow: boolean; + lore: string; +} + +export interface AuctionData { + auctionID: string; + category: string; + sales: number; + price: number; + profit: number; + percentProfit: number; + lbin: number; + ahType: string | null; +} + +export class Item { + public itemData: ItemData; + public auctionData: AuctionData; + + constructor( + name: string, + auctionID: string, + price: number, + rarity: string, + enchants: string[], + hpbs: number, + fpbs: number, + recomb: boolean, + artofwar: boolean, + stars: number, + gemstones: string[], + id: string, + category: string, + profit: number, + percentProfit: number, + lbin: number, + sales: number, + lore: string, + ahType: string | null = null + ) { + this.itemData = { + name, + id, + stars, + rarity, + recomb, + enchants, + hpbs, + fpbs, + gemstones, + aow: artofwar, + lore, + }; + + this.auctionData = { + auctionID, + category, + sales, + price, + profit, + percentProfit, + lbin, + ahType, + }; + } +} diff --git a/src/configLoader.ts b/src/configLoader.ts new file mode 100644 index 0000000..c477fde --- /dev/null +++ b/src/configLoader.ts @@ -0,0 +1,41 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export interface ConfigType { + data: { + 'threadsToUse/speed': number; + minSnipeProfit: number; + minAvgProfit: number; + minCraftProfit: number; + maxAvgLbinDiff: number; + rawCraftMaxWeightPP: number; + minSnipePP: number; + minCraftPP: number; + ignoreCategories: { + weapon: boolean; + accessories: boolean; + armor: boolean; + misc: boolean; + blocks: boolean; + consumables: boolean; + } + minSales: number; + includeCraftCost: boolean; + minPriceForRawcraft: number; + }; + filters: { + EnchantThresholdConditionalBypass: Record>; + EnchantThreshold: Record; + itemIDExclusions: string[]; + }; +} + +export function loadConfig(): ConfigType { + const configPath = path.join(__dirname, 'config.json'); + try { + const fileContents = fs.readFileSync(configPath, 'utf8'); + return JSON.parse(fileContents) as ConfigType; + } catch (error) { + throw new Error(`Failed to load config.json at ${configPath}: ${error}`); + } +} diff --git a/src/helperFunctions.js b/src/helperFunctions.js deleted file mode 100644 index f546094..0000000 --- a/src/helperFunctions.js +++ /dev/null @@ -1,159 +0,0 @@ -const config = require('../config.json') -const nbt = require('prismarine-nbt') -let currentAsyncIntervals = {} - -function addNotation(type, value) { - let returnVal = value; - let notList = []; - if (type === "shortScale") { - notList = [ - " Thousand", - " Million", - " Billion", - " Trillion", - " Quadrillion", - " Quintillion" - ]; - } - - if (type === "oneLetters") { - notList = ["K", "M", "B", "T"]; - } - - let checkNum = 1000; - if (type !== "none" && type !== "commas") { - let notValue = notList[notList.length - 1]; - for (let u = notList.length; u >= 1; u--) { - notValue = notList.shift(); - for (let o = 3; o >= 1; o--) { - if (value >= checkNum) { - returnVal = value / (checkNum / 100); - returnVal = Math.floor(returnVal); - returnVal = (returnVal / Math.pow(10, o)) * 10; - returnVal = +returnVal.toFixed(o - 1) + notValue; - } - checkNum *= 10; - } - } - } else { - returnVal = numberWithCommas(value.toFixed(0)); - } - - return returnVal; -} - -async function getParsed(encoded) { - return new Promise((resolve) => { - let buf = Buffer.from(encoded, 'base64'); - nbt.parse(buf, (err, dat) => { - if (err) throw err; - resolve(nbt.simplify(dat)) - }); - }) -} - -function getProfit(price, rcCost, lbin) { - const profitItem = {} - if (price >= 1000000) { - profitItem.RCProfit = ((lbin + rcCost) - price) - - ((lbin + rcCost) * 0.02); - profitItem.RCPP = parseFloat(((profitItem.RCProfit * 100) / lbin).toFixed(1)) - profitItem.snipeProfit = (lbin - price) - (lbin * 0.02) - profitItem.snipePP = parseFloat(((profitItem.snipeProfit * 100) / lbin).toFixed(1)) - } else { - profitItem.RCProfit = ((lbin + rcCost) - price) - - ((lbin + rcCost) * 0.01); - profitItem.RCPP = parseFloat(((profitItem.RCProfit * 100) / lbin).toFixed(1)) - profitItem.snipeProfit = (lbin - price) - (lbin * 0.01) - profitItem.snipePP = parseFloat(((profitItem.snipeProfit * 100) / lbin).toFixed(1)) - } - - return profitItem -} - -function splitNumber (num = 1, parts = 1) { - let n = Math.floor(num / parts); - const arr = []; - for (let i = 0; i < parts; i++){ - arr.push(n) - } - if(arr.reduce((a, b)=> a + b,0) === num){ - return arr; - } - for(let i = 0; i < parts; i++){ - arr[i]++; - if(arr.reduce((a, b) => a + b, 0) === num){ - return arr; - } - } -} - -function getRawCraft(item, bazaarPrice, lbins) { - let price = 0 - const ignoreMatch = Object.keys( - config.filters.EnchantThresholdConditionalBypass - ).find((key) => { - if (item.itemData.id.includes(key)) return true; - }); - if (item.auctionData.lbin < config.data.minPriceForRawcraft) return 0 - let isInIgnore = ignoreMatch ? ignoreMatch : false - if (item.itemData.enchants && !item.itemData.id.includes(';')) { - for (const enchant of Object.keys(item.itemData.enchants)) { - const degree = item.itemData.enchants[enchant] - const badEnchant = - typeof config.filters.EnchantThreshold[enchant] === 'number' - ? degree >= config.filters.EnchantThreshold[enchant] - : false; - if (isInIgnore) { - const enchantMinValue = - config.filters.EnchantThresholdConditionalBypass[ignoreMatch][ - enchant - ]; - if (enchantMinValue >= degree) continue - } - if (badEnchant) { - price += lbins[`${enchant.toUpperCase()};${degree.toString()}`] ? lbins[`${enchant.toUpperCase()};${degree.toString()}`].lbin * 0.5 : 0 - } - } - } - if (item.itemData.aow) { - price += lbins['THE_ART_OF_WAR'] * 0.3 - } - if (item.itemData.recomb && (item.auctionData.category === 'weapon' || item.auctionData.category === 'armor' || item.auctionData.category === 'accessories')) { - price += bazaarPrice['RECOMBOBULATOR_3000'] * 0.5 - } - price += (item.itemData.hpbs ? item.itemData.hpbs : 0) * bazaarPrice['HOT_POTATO_BOOK'] * 0.05 - price += (item.itemData.fpbs ? item.itemData.fpbs : 0) * bazaarPrice['FUMING_POTATO_BOOK'] * 0.1 - - return price -} - -async function asyncInterval(asyncTask, intervalname, timeout) { - currentAsyncIntervals[intervalname] = true - setTimeout(async function () { - if (!currentAsyncIntervals[intervalname]) return - asyncTask().then(async function () { - await asyncInterval(asyncTask, intervalname, timeout) - }) - }, timeout) -} - -function stopAsyncInterval(intervalname) { - currentAsyncIntervals[intervalname] = false -} - -function currentIntervals() { - return currentAsyncIntervals -} - - -module.exports = { - addNotation, - getParsed, - getProfit, - splitNumber, - getRawCraft, - asyncInterval, - stopAsyncInterval, - currentIntervals -} diff --git a/src/helperFunctions.ts b/src/helperFunctions.ts new file mode 100644 index 0000000..859c590 --- /dev/null +++ b/src/helperFunctions.ts @@ -0,0 +1,247 @@ +// utils.ts +import nbt from 'prismarine-nbt'; +import { Item } from './Item'; + +import { loadConfig } from './configLoader'; +const config = loadConfig(); + +// If you have a defined structure for your config file, feel free to refine this type. +interface ConfigType { + data: { + minPriceForRawcraft: number; + [key: string]: any; + }; + filters: { + EnchantThreshold: Record; + EnchantThresholdConditionalBypass: Record>; + [key: string]: any; + }; +} + +// Prismarine-nbt parse’s callback has this shape: +interface NbtData { + // If you know the exact shape of the parsed data, define it here + [key: string]: any; +} + +// Keep track of current intervals by name +let currentAsyncIntervals: Record = {}; + +type ProfitItem = { + RCProfit: number; + RCPP: number; + snipeProfit: number; + snipePP: number; +}; + +function numberWithCommas(x: number | string): string { + return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); +} + +function addNotation(type: string, value: number): string { + let returnVal: string = value.toString(); + let notList: string[] = []; + + if (type === 'shortScale') { + notList = [' Thousand', ' Million', ' Billion', ' Trillion', ' Quadrillion', ' Quintillion']; + } else if (type === 'oneLetters') { + notList = ['K', 'M', 'B', 'T']; + } + + let checkNum = 1000; + if (type !== 'none' && type !== 'commas') { + let notValue = notList[notList.length - 1] ?? ''; + for (let u = notList.length; u >= 1; u--) { + notValue = notList.shift() ?? ''; + for (let o = 3; o >= 1; o--) { + if (value >= checkNum) { + // Use a fixed decimal approach + returnVal = ( + +(Math.floor(value / (checkNum / 100)) / Math.pow(10, o)) * 10 + ).toFixed(o - 1) + notValue; + } + checkNum *= 10; + } + } + } else { + returnVal = numberWithCommas(value.toFixed(0)); + } + + return returnVal; +} + +async function getParsed(encoded: string): Promise { + return new Promise((resolve, reject) => { + const buf = Buffer.from(encoded, 'base64'); + // The callback signature must match the prismarine-nbt types: + nbt.parse(buf, (err: Error | null, data) => { + if (err) return reject(err); + resolve(nbt.simplify(data)); + }); + }); +} + +function getProfit(price: number, rcCost: number, lbin: number): ProfitItem { + const profitItem: ProfitItem = { + RCProfit: 0, + RCPP: 0, + snipeProfit: 0, + snipePP: 0, + }; + + // Auction house fee logic + if (price >= 1_000_000) { + profitItem.RCProfit = lbin + rcCost - price - (lbin + rcCost) * 0.02; + profitItem.RCPP = parseFloat(((profitItem.RCProfit * 100) / lbin).toFixed(1)); + profitItem.snipeProfit = lbin - price - lbin * 0.02; + profitItem.snipePP = parseFloat(((profitItem.snipeProfit * 100) / lbin).toFixed(1)); + } else { + profitItem.RCProfit = lbin + rcCost - price - (lbin + rcCost) * 0.01; + profitItem.RCPP = parseFloat(((profitItem.RCProfit * 100) / lbin).toFixed(1)); + profitItem.snipeProfit = lbin - price - lbin * 0.01; + profitItem.snipePP = parseFloat(((profitItem.snipeProfit * 100) / lbin).toFixed(1)); + } + + return profitItem; +} + +function splitNumber(num: number = 1, parts: number = 1): number[] { + const n: number = Math.floor(num / parts); + const arr: number[] = []; + + for (let i = 0; i < parts; i++) { + arr.push(n); + } + + if (arr.reduce((a, b) => a + b, 0) === num) { + return arr; + } + for (let i = 0; i < parts; i++) { + arr[i]++; + if (arr.reduce((a, b) => a + b, 0) === num) { + return arr; + } + } + // If we still haven’t balanced it out, it’ll just return this array + return arr; +} + +// Adjust the below types as needed to match your item structure: +interface ItemType { + itemData: { + id: string; + enchants?: Record; + aow?: boolean; + recomb?: boolean; + hpbs?: number; + fpbs?: number; + }; + auctionData: { + lbin: number; + category?: string; + }; + [key: string]: any; +} + +interface LbinsType { + [key: string]: { + lbin: number; + }; +} + +interface BazaarPriceType { + [key: string]: number; +} + +function getRawCraft( + item: Item, + bazaarPrice: BazaarPriceType, + lbins: LbinsType +): number { + let price = 0; + + // If you have a more specific type for config, use that + const typedConfig = config as ConfigType; + + const ignoreMatch: string = + Object.keys(typedConfig.filters.EnchantThresholdConditionalBypass ?? {}).find((key) => { + return item.itemData.id.includes(key); + }) ?? ''; + + if (item.auctionData.lbin < typedConfig.data.minPriceForRawcraft) return 0; + + const isInIgnore = !!ignoreMatch; + + if (item.itemData.enchants && !item.itemData.id.includes(';')) { + for (const enchant of Object.keys(item.itemData.enchants)) { + const degree = item.itemData.enchants[enchant]; + const badEnchant = + typeof typedConfig.filters.EnchantThreshold[enchant] === 'number' + ? degree >= typedConfig.filters.EnchantThreshold[enchant] + : false; + + if (isInIgnore) { + const enchantMinValue = + typedConfig.filters.EnchantThresholdConditionalBypass[ignoreMatch]?.[enchant]; + // If enchantMinValue is defined and the degree is within that threshold, skip. + if (enchantMinValue && degree <= enchantMinValue) continue; + } + + if (badEnchant) { + price += lbins[`${enchant.toUpperCase()};${degree.toString()}`] + ? lbins[`${enchant.toUpperCase()};${degree.toString()}`].lbin * 0.5 + : 0; + } + } + } + + if (item.itemData.aow) { + price += lbins['THE_ART_OF_WAR'].lbin * 0.3; + } + + if ( + item.itemData.recomb && + ['weapon', 'armor', 'accessories'].includes(item.auctionData.category ?? '') + ) { + price += bazaarPrice['RECOMBOBULATOR_3000'] * 0.5; + } + + price += (item.itemData.hpbs ?? 0) * bazaarPrice['HOT_POTATO_BOOK'] * 0.05; + price += (item.itemData.fpbs ?? 0) * bazaarPrice['FUMING_POTATO_BOOK'] * 0.1; + + return price; +} + +// Schedules a recurring async task. +async function asyncInterval( + asyncTask: () => Promise, + intervalName: string, + timeout: number +): Promise { + currentAsyncIntervals[intervalName] = true; + setTimeout(async function () { + if (!currentAsyncIntervals[intervalName]) return; + await asyncTask(); + await asyncInterval(asyncTask, intervalName, timeout); + }, timeout); +} + +function stopAsyncInterval(intervalName: string): void { + currentAsyncIntervals[intervalName] = false; +} + +function currentIntervals(): Record { + return currentAsyncIntervals; +} + +// Exports +export { + addNotation, + getParsed, + getProfit, + splitNumber, + getRawCraft, + asyncInterval, + stopAsyncInterval, + currentIntervals, +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5b3c33d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "nodenext", + "target": "ES2024", + "jsx": "preserve", + "strictNullChecks": true, + "strictFunctionTypes": true, + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "./dist", + }, + "exclude": [ + "node_modules", + "**/node_modules/*" + ] +} \ No newline at end of file From 14759592b813ef035057c8d2628dff064affb98c Mon Sep 17 00:00:00 2001 From: ulysia Date: Fri, 27 Dec 2024 21:40:09 +0100 Subject: [PATCH 08/13] works (somehow). Ts almost done, just missing types here and there --- config.json | 2 +- index.ts | 14 +++++++------- package.json | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/config.json b/config.json index 5b83ee8..c9973b6 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "data": { - "threadsToUse/speed": 48, + "thread_count/speed": 48, "minSnipeProfit": 900000, "minAvgProfit": 500000, diff --git a/index.ts b/index.ts index fb9faee..95b8cba 100644 --- a/index.ts +++ b/index.ts @@ -8,7 +8,7 @@ import { loadConfig } from './src/configLoader'; const config = loadConfig(); -let threadsToUse = config.data['threadsToUse/speed'] ?? 1; +let thread_count = config.data['thread_count/speed'] ?? 1; let lastUpdated = 0; let doneWorkers = 0; let startingTime; @@ -32,8 +32,8 @@ async function initialize() { await getMoulberry(); await getLBINs(); - for (let j = 0; j < threadsToUse; j++) { - workers[j] = new Worker('./AuctionHandler.worker.ts', { + for (let j = 0; j < thread_count; j++) { + workers[j] = new Worker('/app/dist/AuctionHandler.worker.js', { workerData: { itemDatas: itemDatas, bazaarData: bazaarPrice, @@ -80,7 +80,7 @@ async function initialize() { } } else if (result === 'finished') { doneWorkers++; - if (doneWorkers === threadsToUse) { + if (doneWorkers === thread_count) { doneWorkers = 0; console.log( `Completed in ${(Date.now() - startingTime) / 1000} seconds` @@ -141,7 +141,7 @@ async function initialize() { ); } -async function getLBINs() { +async function getLBINs(): Promise { const lbins = await axios.get('https://moulberry.codes/lowestbin.json'); const lbinData = lbins.data; for (const item of Object.keys(lbinData)) { @@ -150,7 +150,7 @@ async function getLBINs() { } } -async function getMoulberry() { +async function getMoulberry(): Promise { const moulberryAvgs = await axios.get( 'https://moulberry.codes/auction_averages/3day.json' ); @@ -175,7 +175,7 @@ async function getMoulberry() { } } -async function getBzData() { +async function getBzData(): Promise { const bzData = await axios.get('https://api.hypixel.net/skyblock/bazaar'); bazaarPrice['RECOMBOBULATOR_3000'] = bzData.data.products.RECOMBOBULATOR_3000.quick_status.buyPrice; diff --git a/package.json b/package.json index 7266540..33e90aa 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,13 @@ "dev": "ts-node index.ts" }, "dependencies": { + "@types/node": "^22.10.2", "@types/toastify-js": "^1.12.3", "axios": "^0.24.0", "copy-paste": "^1.5.3", "discord.js": "^14.16.3", "express": "^4.21.2", + "node": "^23.5.0", "node-notifier": "^10.0.1", "open": "^8.4.2", "prismarine-nbt": "^2.7.0", From c3badac62672469c8c7622e51a61540683539cca Mon Sep 17 00:00:00 2001 From: sol Date: Fri, 27 Dec 2024 22:45:04 +0200 Subject: [PATCH 09/13] setup sql framework --- src/sqlFunctions.js | 68 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/sqlFunctions.js diff --git a/src/sqlFunctions.js b/src/sqlFunctions.js new file mode 100644 index 0000000..0dc6c02 --- /dev/null +++ b/src/sqlFunctions.js @@ -0,0 +1,68 @@ +const sqlite3 = require('sqlite3').verbose(); + +//TODO +// MUTEX functions for adding/removing/upsert +// basic read function by id +// complex read function by value range + +async function InitTable() { + const db = new sqlite3.Database('bot_data'); + try{ + await runQuery(db,'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)') + console.log('Table created successfully.'); + + // Insert data + await runQuery(db, 'INSERT INTO users (name) VALUES (?)', ['Alice']); + console.log('Data inserted successfully.'); + + // Retrieve a single row + const row = await getQuery(db, 'SELECT * FROM users WHERE name = ?', ['Alice']); + console.log('Retrieved row:', row); + + // Retrieve all rows + const rows = await allQuery(db, 'SELECT * FROM users'); + console.log('All rows:', rows); + } catch (err) { + console.error('Database error:', err.message); + } finally { + db.close(); + } +} +function runQuery(db, query , params = []) { + return new Promise((resolve,reject) => { + db.run(query, params, function (err) { + if(err){ + reject(err); + } + else{ + resolve(this); + } + }); + }); +} +function getQuery(db, query, params = []) { + return new Promise((resolve, reject) => { + db.get(query, params, (err, row) => { + if (err) { + reject(err); + } else { + resolve(row); + } + }); + }); +} +function allQuery(db, query, params = []) { + return new Promise((resolve, reject) => { + db.all(query, params, (err, rows) => { + if (err) { + reject(err); + } else { + resolve(rows); + } + }); + }); +} + +module.exports = { + InitTable +} \ No newline at end of file From d44ad19efc9f4ed35b223867a856e80c30d8a241 Mon Sep 17 00:00:00 2001 From: sol Date: Fri, 27 Dec 2024 23:08:44 +0200 Subject: [PATCH 10/13] sql: javascript > typescript --- .gitignore | 4 +++- index.ts | 3 ++- package.json | 1 + src/{sqlFunctions.js => sqlFunctions.ts} | 10 +++++----- 4 files changed, 11 insertions(+), 7 deletions(-) rename src/{sqlFunctions.js => sqlFunctions.ts} (83%) diff --git a/.gitignore b/.gitignore index d1319a2..2619d2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ node_modules .env pnpm-lock* -dist \ No newline at end of file +dist +*.db +*.sqlite* \ No newline at end of file diff --git a/index.ts b/index.ts index 95b8cba..0aafccd 100644 --- a/index.ts +++ b/index.ts @@ -3,7 +3,7 @@ import { WebhookClient, EmbedBuilder, Embed } from 'discord.js'; import { Worker } from 'worker_threads'; import { asyncInterval, addNotation } from './src/helperFunctions'; import { string } from 'prismarine-nbt'; - +import { InitTable } from './src/sqlFunctions'; import { loadConfig } from './src/configLoader'; const config = loadConfig(); @@ -24,6 +24,7 @@ const bazaarPrice = { }; async function initialize() { + await InitTable(); const matches = process.env.WEBHOOK_URL.match(webhookRegex); if (!matches) return console.log(`[Main thread] Couldn't parse Webhook URL`); const webhook = new WebhookClient({ id: matches[1], token: matches[2] }); diff --git a/package.json b/package.json index 33e90aa..0ebb551 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "open": "^8.4.2", "prismarine-nbt": "^2.7.0", "socket.io": "^4.8.1", + "sqlite3": "^5.1.7", "toastify-js": "^1.12.0", "ts-node": "^10.9.2", "typescript": "^5.7.2" diff --git a/src/sqlFunctions.js b/src/sqlFunctions.ts similarity index 83% rename from src/sqlFunctions.js rename to src/sqlFunctions.ts index 0dc6c02..496642c 100644 --- a/src/sqlFunctions.js +++ b/src/sqlFunctions.ts @@ -1,4 +1,4 @@ -const sqlite3 = require('sqlite3').verbose(); +import sqlite3 from 'sqlite3'; //TODO // MUTEX functions for adding/removing/upsert @@ -28,7 +28,7 @@ async function InitTable() { db.close(); } } -function runQuery(db, query , params = []) { +function runQuery(db: sqlite3.Database, query: string, params: string[] = []) { return new Promise((resolve,reject) => { db.run(query, params, function (err) { if(err){ @@ -40,7 +40,7 @@ function runQuery(db, query , params = []) { }); }); } -function getQuery(db, query, params = []) { +function getQuery(db: sqlite3.Database, query: string, params: string[] = []) { return new Promise((resolve, reject) => { db.get(query, params, (err, row) => { if (err) { @@ -51,7 +51,7 @@ function getQuery(db, query, params = []) { }); }); } -function allQuery(db, query, params = []) { +function allQuery(db: sqlite3.Database, query: string, params: string[] = []) { return new Promise((resolve, reject) => { db.all(query, params, (err, rows) => { if (err) { @@ -63,6 +63,6 @@ function allQuery(db, query, params = []) { }); } -module.exports = { +export { InitTable } \ No newline at end of file From d4275929ac2849e4128790bd8f1aea42c3842134 Mon Sep 17 00:00:00 2001 From: ulysia Date: Fri, 27 Dec 2024 22:16:26 +0100 Subject: [PATCH 11/13] enforcing strict types --- src/helperFunctions.ts | 6 ------ tsconfig.json | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/helperFunctions.ts b/src/helperFunctions.ts index 859c590..0d7e391 100644 --- a/src/helperFunctions.ts +++ b/src/helperFunctions.ts @@ -18,9 +18,7 @@ interface ConfigType { }; } -// Prismarine-nbt parse’s callback has this shape: interface NbtData { - // If you know the exact shape of the parsed data, define it here [key: string]: any; } @@ -89,7 +87,6 @@ function getProfit(price: number, rcCost: number, lbin: number): ProfitItem { snipePP: 0, }; - // Auction house fee logic if (price >= 1_000_000) { profitItem.RCProfit = lbin + rcCost - price - (lbin + rcCost) * 0.02; profitItem.RCPP = parseFloat(((profitItem.RCProfit * 100) / lbin).toFixed(1)); @@ -126,7 +123,6 @@ function splitNumber(num: number = 1, parts: number = 1): number[] { return arr; } -// Adjust the below types as needed to match your item structure: interface ItemType { itemData: { id: string; @@ -160,7 +156,6 @@ function getRawCraft( ): number { let price = 0; - // If you have a more specific type for config, use that const typedConfig = config as ConfigType; const ignoreMatch: string = @@ -183,7 +178,6 @@ function getRawCraft( if (isInIgnore) { const enchantMinValue = typedConfig.filters.EnchantThresholdConditionalBypass[ignoreMatch]?.[enchant]; - // If enchantMinValue is defined and the degree is within that threshold, skip. if (enchantMinValue && degree <= enchantMinValue) continue; } diff --git a/tsconfig.json b/tsconfig.json index 5b3c33d..9eb6412 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,7 @@ "esModuleInterop": true, "skipLibCheck": true, "outDir": "./dist", + "strict": true, }, "exclude": [ "node_modules", From 9f7cc8f8e9dfe09d715601257a9075782ec711da Mon Sep 17 00:00:00 2001 From: ulysia Date: Fri, 27 Dec 2024 22:58:39 +0100 Subject: [PATCH 12/13] added more types --- AuctionHandler.worker.ts | 12 ++++++------ config.json | 2 +- index.ts | 34 ++++++++++++++++++++++++---------- package.json | 1 - src/Item.ts | 4 ++-- src/auctionType.ts | 39 +++++++++++++++++++++++++++++++++++++++ src/configLoader.ts | 11 ++--------- src/sqlFunctions.ts | 2 +- 8 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 src/auctionType.ts diff --git a/AuctionHandler.worker.ts b/AuctionHandler.worker.ts index 2a90d06..c801103 100644 --- a/AuctionHandler.worker.ts +++ b/AuctionHandler.worker.ts @@ -2,6 +2,7 @@ import axios from 'axios'; import { getParsed, getProfit, splitNumber, getRawCraft } from './src/helperFunctions'; import { parentPort, workerData, isMainThread } from 'worker_threads'; import { Item } from './src/Item'; +import { AuctionResponse, Auction, Bid } from './src/auctionType'; import { loadConfig } from './src/configLoader'; const config = loadConfig(); @@ -10,8 +11,7 @@ if (isMainThread || !parentPort) { throw new Error('This module can only be run in a Worker thread.'); } -const threadsToUse: number = config.data['threadsToUse/speed']; - +const worker_count: number = config.data.worker_count; let minProfit = config.data.minSnipeProfit; let minPercentProfit = config.data.minSnipePP; let ignoredAuctions: any[] = []; @@ -31,10 +31,10 @@ parentPort.on('message', async (message) => { } }); -async function parsePage(i) { +async function parsePage(i: number) { console.log(`[Worker ${workerData.workerNumber}] Parsing page ${i}`); try { - const auctionPage = await axios.get( + const auctionPage = await axios.get( `https://api.hypixel.net/skyblock/auctions?page=${i}` ); for (const auction of auctionPage.data.auctions) { @@ -144,12 +144,12 @@ async function parsePage(i) { } } -async function doTask(totalPages) { +async function doTask(totalPages: number) { console.log( `[Worker ${workerData.workerNumber}] Starting task for ${totalPages} pages` ); let startingPage = 0; - const pagePerThread = splitNumber(totalPages, threadsToUse); + const pagePerThread = splitNumber(totalPages, worker_count); if (workerData.workerNumber !== 0 && startingPage === 0) { const clonedStarting = pagePerThread.slice(); diff --git a/config.json b/config.json index c9973b6..23cd625 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "data": { - "thread_count/speed": 48, + "worker_count": 48, "minSnipeProfit": 900000, "minAvgProfit": 500000, diff --git a/index.ts b/index.ts index 0aafccd..8847a94 100644 --- a/index.ts +++ b/index.ts @@ -7,13 +7,27 @@ import { InitTable } from './src/sqlFunctions'; import { loadConfig } from './src/configLoader'; const config = loadConfig(); +class ItemData { + public sales: number; + public lbin: number; + public cleanPrice: number; + public price: number; -let thread_count = config.data['thread_count/speed'] ?? 1; + constructor(sales: number = 0, lbin: number = 0, cleanPrice: number = 0, price: number = 0) { + this.sales = sales; + this.lbin = lbin; + this.cleanPrice = cleanPrice; + this.price = price; + } + +} + +let worker_count = config.data.worker_count ?? 1; let lastUpdated = 0; let doneWorkers = 0; -let startingTime; +let startingTime: number; let maxPrice = 0; -let itemDatas = {}; +let itemDatas: Record = {}; const workers: Worker[] = []; const webhookRegex = /https:\/\/discord.com\/api\/webhooks\/(.+)\/(.+)/; @@ -33,7 +47,7 @@ async function initialize() { await getMoulberry(); await getLBINs(); - for (let j = 0; j < thread_count; j++) { + for (let j = 0; j < worker_count; j++) { workers[j] = new Worker('/app/dist/AuctionHandler.worker.js', { workerData: { itemDatas: itemDatas, @@ -45,11 +59,11 @@ async function initialize() { workers[j].on('message', async (result) => { if (result.itemData !== undefined) { - let averagePrice = itemDatas[result.itemData.id]?.cleanPrice || 'N/A'; + let averagePrice: number | null = itemDatas[result.itemData.id]?.cleanPrice || null; if ( result.auctionData.lbin - result.auctionData.price >= config.data.minSnipeProfit && - averagePrice - result.auctionData.price >= config.data.minAvgProfit + (averagePrice || averagePrice! - result.auctionData.price >= config.data.minAvgProfit) ) { let mustBuyMessage = ''; const embed = new EmbedBuilder() @@ -70,7 +84,7 @@ async function initialize() { result.auctionData.sales )}\` \nType: \`${result.auctionData.ahType}\` - \nAverage Price: \`${addNotation('oneLetters', averagePrice)}\`` + \nAverage Price: \`${averagePrice ? addNotation('oneLetters', averagePrice) : 'N/A'}\`` ); await webhook.send({ @@ -81,7 +95,7 @@ async function initialize() { } } else if (result === 'finished') { doneWorkers++; - if (doneWorkers === thread_count) { + if (doneWorkers === worker_count) { doneWorkers = 0; console.log( `Completed in ${(Date.now() - startingTime) / 1000} seconds` @@ -146,7 +160,7 @@ async function getLBINs(): Promise { const lbins = await axios.get('https://moulberry.codes/lowestbin.json'); const lbinData = lbins.data; for (const item of Object.keys(lbinData)) { - if (!itemDatas[item]) itemDatas[item] = {}; + if (!itemDatas[item]) itemDatas[item] = new ItemData(); itemDatas[item].lbin = lbinData[item]; } } @@ -163,7 +177,7 @@ async function getMoulberry(): Promise { const cleanPriceData = cleanPriceAvgs.data; for (const item of Object.keys(avgData)) { - if (!itemDatas[item]) itemDatas[item] = {}; + if (!itemDatas[item]) itemDatas[item] = new ItemData(); const itemInfo = avgData[item]; itemDatas[item].sales = itemInfo.sales !== undefined ? itemInfo.sales : 0; diff --git a/package.json b/package.json index 0ebb551..a417188 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "copy-paste": "^1.5.3", "discord.js": "^14.16.3", "express": "^4.21.2", - "node": "^23.5.0", "node-notifier": "^10.0.1", "open": "^8.4.2", "prismarine-nbt": "^2.7.0", diff --git a/src/Item.ts b/src/Item.ts index ee054a7..36b9aa1 100644 --- a/src/Item.ts +++ b/src/Item.ts @@ -6,7 +6,7 @@ export interface ItemData { stars: number; rarity: string; recomb: boolean; - enchants: string[]; + enchants: Record; hpbs: number; fpbs: number; gemstones: string[]; @@ -34,7 +34,7 @@ export class Item { auctionID: string, price: number, rarity: string, - enchants: string[], + enchants: Record, hpbs: number, fpbs: number, recomb: boolean, diff --git a/src/auctionType.ts b/src/auctionType.ts new file mode 100644 index 0000000..4c97f5b --- /dev/null +++ b/src/auctionType.ts @@ -0,0 +1,39 @@ +export type AuctionResponse = { + success: boolean + page: number + totalPages: number + totalAuctions: number + lastUpdated: number + auctions: Auction[] +} + +export type Auction = { + uuid: string + auctioneer: string + profile_id: string + coop: string[] + start: number + end: number + item_name: string + item_lore: string + extra: string + category: string + tier: string + starting_bid: number + item_bytes: string + claimed: boolean + claimed_bidders: any[] + highest_bid_amount: number + last_updated: number + bin: boolean + bids: Bid[] + item_uuid?: string +} + +export type Bid = { + auction_id: string + bidder: string + profile_id: string + amount: number + timestamp: number +} \ No newline at end of file diff --git a/src/configLoader.ts b/src/configLoader.ts index c477fde..9e3a83c 100644 --- a/src/configLoader.ts +++ b/src/configLoader.ts @@ -3,7 +3,7 @@ import * as path from 'path'; export interface ConfigType { data: { - 'threadsToUse/speed': number; + worker_count: number; minSnipeProfit: number; minAvgProfit: number; minCraftProfit: number; @@ -11,14 +11,7 @@ export interface ConfigType { rawCraftMaxWeightPP: number; minSnipePP: number; minCraftPP: number; - ignoreCategories: { - weapon: boolean; - accessories: boolean; - armor: boolean; - misc: boolean; - blocks: boolean; - consumables: boolean; - } + ignoreCategories: Record; minSales: number; includeCraftCost: boolean; minPriceForRawcraft: number; diff --git a/src/sqlFunctions.ts b/src/sqlFunctions.ts index 496642c..d673b68 100644 --- a/src/sqlFunctions.ts +++ b/src/sqlFunctions.ts @@ -22,7 +22,7 @@ async function InitTable() { // Retrieve all rows const rows = await allQuery(db, 'SELECT * FROM users'); console.log('All rows:', rows); - } catch (err) { + } catch (err: any) { console.error('Database error:', err.message); } finally { db.close(); From cd3b9520ea604f5a8c1b81b3d81612eb244bcb64 Mon Sep 17 00:00:00 2001 From: ulysia Date: Sat, 28 Dec 2024 09:57:15 +0100 Subject: [PATCH 13/13] added remote adding scripts --- add_remotes.bat | 2 ++ add_remotes.sh | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 add_remotes.bat create mode 100644 add_remotes.sh diff --git a/add_remotes.bat b/add_remotes.bat new file mode 100644 index 0000000..2c6e98d --- /dev/null +++ b/add_remotes.bat @@ -0,0 +1,2 @@ +git remote add upstream https://github.com/MashClashXD/Hypixel-Auction-Flipper.git +git remote add upstream2 https://github.com/DuckySoLucky/Hypixel-Auction-Flipper.git diff --git a/add_remotes.sh b/add_remotes.sh new file mode 100644 index 0000000..2c6e98d --- /dev/null +++ b/add_remotes.sh @@ -0,0 +1,2 @@ +git remote add upstream https://github.com/MashClashXD/Hypixel-Auction-Flipper.git +git remote add upstream2 https://github.com/DuckySoLucky/Hypixel-Auction-Flipper.git