diff options
-rw-r--r-- | src/cleaners/skyblock/auctions.ts | 36 | ||||
-rw-r--r-- | src/database.ts | 11 | ||||
-rw-r--r-- | src/hypixel.ts | 49 | ||||
-rw-r--r-- | src/index.ts | 14 |
4 files changed, 108 insertions, 2 deletions
diff --git a/src/cleaners/skyblock/auctions.ts b/src/cleaners/skyblock/auctions.ts new file mode 100644 index 0000000..28e1958 --- /dev/null +++ b/src/cleaners/skyblock/auctions.ts @@ -0,0 +1,36 @@ +import typedHypixelApi from 'typed-hypixel-api' +import { cleanInventory, headIdFromBase64, Item } from './inventory.js' + + +export interface Auction { + id: string + sellerUuid: string + sellerProfileUuid: string + buyerUuid: string | null + creationTimestamp: number + boughtTimestamp: number + coins: number + bin: boolean + item: Item +} + +export async function cleanAuctions(data: typedHypixelApi.SkyBlockRequestAuctionResponse): Promise<Auction[]> { + console.log(data) + const auctions: Auction[] = [] + for (const auction of data.auctions) { + auctions.push({ + id: auction.uuid, + sellerUuid: auction.auctioneer, + sellerProfileUuid: auction.profile_id, + creationTimestamp: auction.start, + buyerUuid: auction.end ? auction.bids[auction.bids.length - 1].bidder : null, + boughtTimestamp: auction.end, + coins: auction.highest_bid_amount, + bin: auction.bin ?? false, + item: (await cleanInventory(typeof auction.item_bytes === 'string' ? auction.item_bytes : auction.item_bytes.data))[0] + }) + } + + return auctions + +}
\ No newline at end of file diff --git a/src/database.ts b/src/database.ts index 3aafd05..a8dd1a4 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1110,6 +1110,17 @@ export async function updateItemAuction(auction: ItemAuctionsSchema) { }, { $set: auction }, { upsert: true }) } +/** + * Fetches the SkyBlock ids of all the items in the auctions database. This method is slow and should be cached! + */ +export async function fetchItemsAuctionsIds(): Promise<string[]> { + const docs = await itemAuctionsCollection?.aggregate([ + // this removes everything except the _id + { $project: { _id: true } } + ]).toArray() + return docs.map(r => r._id) +} + export async function fetchServerStatus() { return await database.admin().serverStatus() diff --git a/src/hypixel.ts b/src/hypixel.ts index 88f3768..5865878 100644 --- a/src/hypixel.ts +++ b/src/hypixel.ts @@ -14,6 +14,7 @@ import { AccountSchema, fetchAccount, fetchItemsAuctions, + fetchItemsAuctionsIds, ItemAuctionsSchema, queueUpdateDatabaseMember, queueUpdateDatabaseProfile, @@ -33,6 +34,7 @@ import { debug } from './index.js' import { WithId } from 'mongodb' import { cleanEndedAuctions } from './cleaners/skyblock/endedAuctions.js' import { cleanAuctions } from './cleaners/skyblock/auctions.js' +import { string } from 'prismarine-nbt' export type Included = 'profiles' | 'player' | 'stats' | 'inventories' | undefined @@ -452,4 +454,51 @@ export async function periodicallyFetchRecentlyEndedAuctions() { } } +let isFetchingAuctionItemList = false +let cachedAuctionItemListData: Map<string, string> | null = null +let nextAuctionItemListUpdate: Date = new Date(0) + +export async function fetchAuctionItems() { + if (cachedAuctionItemListData && nextAuctionItemListUpdate > new Date()) + return cachedAuctionItemListData + + // if it's currently fetching the election data and it doesn't have it, + // wait until we do have the election data + if (isFetchingAuctionItemList && !cachedAuctionItemListData) { + await new Promise(resolve => { + const interval = setInterval(() => { + if (cachedAuctionItemListData) { + clearInterval(interval) + resolve(cachedAuctionItemListData) + } + }, 100) + }) + } + + isFetchingAuctionItemList = true + const itemList = await fetchAuctionItemsUncached() + isFetchingAuctionItemList = false + + cachedAuctionItemListData = itemList + // updates every 60 minutes + nextAuctionItemListUpdate = new Date(Date.now() + 10 * 60 * 1000); + return Object.fromEntries(itemList) +} + +async function fetchAuctionItemsUncached() { + const auctionItemIds = await fetchItemsAuctionsIds() + const itemList = await fetchItemList() + const idsToNames: Map<string, string> = new Map() + for (const item of itemList.list) + // we only return items in auctionItemIds so the response isn't too big, + // since usually it would contain stuff that we don't care about like + // minions + if (auctionItemIds.includes(item.id)) + idsToNames.set(item.id, item.display.name) + // if the item in the database isn't in the items api, just set the name to the id + for (const item of auctionItemIds) + if (!idsToNames.has(item)) + idsToNames.set(item, item) + return idsToNames +} diff --git a/src/index.ts b/src/index.ts index 1dcb523..9311fe6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import { createSession, fetchAccountFromDiscord, fetchAllLeaderboardsCategorized, fetchLeaderboard, fetchMemberLeaderboardSpots, fetchSession, finishedCachingRawLeaderboards, leaderboardUpdateMemberQueue, leaderboardUpdateProfileQueue, updateAccount, deleteSession, fetchPaginatedItemsAuctions, fetchItemsAuctions } from './database.js' -import { fetchAuctionUncached, fetchElection, fetchItemList, fetchMemberProfile, fetchUser } from './hypixel.js' +import { fetchAuctionItems, fetchAuctionUncached, fetchElection, fetchItemList, fetchMemberProfile, fetchUser } from './hypixel.js' import rateLimit from 'express-rate-limit' import * as constants from './constants.js' import * as discord from './discord.js' @@ -166,7 +166,6 @@ app.get('/items', async (req, res) => { } }) - app.get('/auctionprices', async (req, res) => { const itemIds = typeof req.query.items === 'string' ? req.query.items.split(',') : null if (itemIds && itemIds.length > 100) @@ -186,6 +185,17 @@ app.get('/auctionprices', async (req, res) => { } }) +app.get('/auctionitems', async (req, res) => { + try { + res + .setHeader('Cache-Control', 'public, max-age=600') + .json(await fetchAuctionItems()) + } catch (err) { + console.error(err) + res.json({ ok: false }) + } +}) + app.get('/auction/:uuid', async (req, res) => { console.log('fetching auction', req.params.uuid) const auction = await fetchAuctionUncached(req.params.uuid) |