2024-12-27 21:17:59 +01:00
|
|
|
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';
|
2024-12-28 13:41:48 +01:00
|
|
|
import { SqlSystem } from './src/sqlFunctions';
|
2024-12-28 14:05:03 +01:00
|
|
|
import { setupErrorHandlers } from './src/errorHandler';
|
|
|
|
import { ItemCompactData } from './src/Types';
|
2024-12-27 21:17:59 +01:00
|
|
|
|
2024-12-28 14:05:03 +01:00
|
|
|
setupErrorHandlers();
|
2024-12-27 22:58:39 +01:00
|
|
|
|
2024-12-28 14:05:03 +01:00
|
|
|
import { loadConfig } from './src/configLoader';
|
|
|
|
const config = loadConfig();
|
2024-12-28 11:23:40 +01:00
|
|
|
|
2024-12-27 22:58:39 +01:00
|
|
|
let worker_count = config.data.worker_count ?? 1;
|
2024-06-06 06:13:48 +02:00
|
|
|
let lastUpdated = 0;
|
|
|
|
let doneWorkers = 0;
|
2024-12-27 22:58:39 +01:00
|
|
|
let startingTime: number;
|
2024-06-06 06:13:48 +02:00
|
|
|
let maxPrice = 0;
|
2024-12-28 14:05:03 +01:00
|
|
|
let itemDatas: Record<string, ItemCompactData> = {};
|
2024-12-27 21:17:59 +01:00
|
|
|
const workers: Worker[] = [];
|
2024-06-06 06:13:48 +02:00
|
|
|
const webhookRegex = /https:\/\/discord.com\/api\/webhooks\/(.+)\/(.+)/;
|
2022-08-06 19:02:15 +02:00
|
|
|
|
|
|
|
const bazaarPrice = {
|
2024-12-28 11:23:40 +01:00
|
|
|
RECOMBOBULATOR_3000: 0,
|
|
|
|
HOT_POTATO_BOOK: 0,
|
2024-12-28 15:09:44 +01:00
|
|
|
FUMING_POTATO_BOOK: 0
|
2024-06-06 06:13:48 +02:00
|
|
|
};
|
2024-06-05 23:04:10 +02:00
|
|
|
|
2022-08-06 19:02:15 +02:00
|
|
|
async function initialize() {
|
2024-12-28 13:41:48 +01:00
|
|
|
await SqlSystem.InitTable();
|
2024-12-28 11:25:31 +01:00
|
|
|
const matches = process.env.WEBHOOK_URL.match(webhookRegex);
|
2024-12-28 11:23:40 +01:00
|
|
|
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();
|
|
|
|
|
2024-12-27 22:58:39 +01:00
|
|
|
for (let j = 0; j < worker_count; j++) {
|
2024-12-27 21:40:09 +01:00
|
|
|
workers[j] = new Worker('/app/dist/AuctionHandler.worker.js', {
|
2024-12-28 11:23:40 +01:00
|
|
|
workerData: {
|
|
|
|
itemDatas: itemDatas,
|
|
|
|
bazaarData: bazaarPrice,
|
|
|
|
workerNumber: j,
|
2024-12-28 15:09:44 +01:00
|
|
|
maxPrice: maxPrice
|
|
|
|
}
|
2024-12-28 11:23:40 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
workers[j].on('message', async (result) => {
|
|
|
|
if (result.itemData !== undefined) {
|
2024-12-27 22:58:39 +01:00
|
|
|
let averagePrice: number | null = itemDatas[result.itemData.id]?.cleanPrice || null;
|
2024-12-28 11:23:40 +01:00
|
|
|
if (
|
2024-12-28 15:09:44 +01:00
|
|
|
result.auctionData.lbin - result.auctionData.price >= config.data.minSnipeProfit &&
|
2024-12-27 22:58:39 +01:00
|
|
|
(averagePrice || averagePrice! - result.auctionData.price >= config.data.minAvgProfit)
|
2024-12-28 11:23:40 +01:00
|
|
|
) {
|
|
|
|
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}\`\`\`
|
2024-12-28 15:09:44 +01:00
|
|
|
\nProfit: \`${addNotation('oneLetters', result.auctionData.profit)} (${result.auctionData.percentProfit
|
|
|
|
}%)\`
|
2024-12-28 11:23:40 +01:00
|
|
|
\nCost: \`${addNotation('oneLetters', result.auctionData.price)}\`
|
|
|
|
\nLBIN: \`${addNotation('oneLetters', result.auctionData.lbin)}\`
|
2024-12-28 15:09:44 +01:00
|
|
|
\nSales/Day: \`${addNotation('oneLetters', result.auctionData.sales)}\`
|
2024-12-28 11:23:40 +01:00
|
|
|
\nType: \`${result.auctionData.ahType}\`
|
2024-12-27 22:58:39 +01:00
|
|
|
\nAverage Price: \`${averagePrice ? addNotation('oneLetters', averagePrice) : 'N/A'}\``
|
2024-12-28 11:23:40 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
await webhook.send({
|
2024-12-28 11:25:31 +01:00
|
|
|
username: process.env.WEBHOOK_NAME,
|
|
|
|
avatarURL: process.env.WEBHOOK_PROFILE_PICTURE,
|
2024-12-28 15:09:44 +01:00
|
|
|
embeds: [embed]
|
2024-12-28 11:23:40 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
} else if (result === 'finished') {
|
|
|
|
doneWorkers++;
|
2024-12-27 22:58:39 +01:00
|
|
|
if (doneWorkers === worker_count) {
|
2024-12-28 11:23:40 +01:00
|
|
|
doneWorkers = 0;
|
2024-12-28 15:09:44 +01:00
|
|
|
console.log(`Completed in ${(Date.now() - startingTime) / 1000} seconds`);
|
2024-12-28 11:23:40 +01:00
|
|
|
startingTime = 0;
|
|
|
|
workers[0].emit('done');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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 () => {
|
|
|
|
return new Promise(async (resolve) => {
|
2024-12-28 15:09:44 +01:00
|
|
|
const ahFirstPage = await axios.get('https://api.hypixel.net/skyblock/auctions?page=0');
|
2024-12-28 11:23:40 +01:00
|
|
|
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
|
|
|
|
);
|
2022-08-06 19:02:15 +02:00
|
|
|
}
|
|
|
|
|
2024-12-27 21:40:09 +01:00
|
|
|
async function getLBINs(): Promise<void> {
|
2024-12-28 11:23:40 +01:00
|
|
|
const lbins = await axios.get('https://moulberry.codes/lowestbin.json');
|
|
|
|
const lbinData = lbins.data;
|
|
|
|
for (const item of Object.keys(lbinData)) {
|
2024-12-28 14:05:03 +01:00
|
|
|
if (!itemDatas[item]) itemDatas[item] = new ItemCompactData();
|
2024-12-28 11:23:40 +01:00
|
|
|
itemDatas[item].lbin = lbinData[item];
|
|
|
|
}
|
2022-08-06 19:02:15 +02:00
|
|
|
}
|
|
|
|
|
2024-12-27 21:40:09 +01:00
|
|
|
async function getMoulberry(): Promise<void> {
|
2024-12-28 15:09:44 +01:00
|
|
|
const moulberryAvgs = await axios.get('https://moulberry.codes/auction_averages/3day.json');
|
2024-12-28 11:23:40 +01:00
|
|
|
const avgData = moulberryAvgs.data;
|
|
|
|
|
2024-12-28 15:09:44 +01:00
|
|
|
const cleanPriceAvgs = await axios.get('https://moulberry.codes/auction_averages_lbin/1day.json');
|
2024-12-28 11:23:40 +01:00
|
|
|
const cleanPriceData = cleanPriceAvgs.data;
|
|
|
|
|
|
|
|
for (const item of Object.keys(avgData)) {
|
2024-12-28 14:05:03 +01:00
|
|
|
if (!itemDatas[item]) itemDatas[item] = new ItemCompactData();
|
2024-12-28 11:23:40 +01:00
|
|
|
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
|
2024-12-27 21:17:59 +01:00
|
|
|
? itemInfo.clean_price
|
|
|
|
: itemInfo.price;
|
2024-12-28 11:23:40 +01:00
|
|
|
}
|
2022-08-06 19:02:15 +02:00
|
|
|
}
|
|
|
|
|
2024-12-27 21:40:09 +01:00
|
|
|
async function getBzData(): Promise<void> {
|
2024-12-28 11:23:40 +01:00
|
|
|
const bzData = await axios.get('https://api.hypixel.net/skyblock/bazaar');
|
2024-12-28 15:09:44 +01:00
|
|
|
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;
|
2022-08-06 19:02:15 +02:00
|
|
|
}
|
|
|
|
|
2024-06-06 06:13:48 +02:00
|
|
|
initialize();
|