aboutsummaryrefslogtreecommitdiff
path: root/src/hypixel.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/hypixel.ts')
-rw-r--r--src/hypixel.ts98
1 files changed, 96 insertions, 2 deletions
diff --git a/src/hypixel.ts b/src/hypixel.ts
index d7a5887..060cff4 100644
--- a/src/hypixel.ts
+++ b/src/hypixel.ts
@@ -13,9 +13,13 @@ import {
AccountCustomization,
AccountSchema,
fetchAccount,
+ fetchItemsAuctions,
+ ItemAuctionsSchema,
queueUpdateDatabaseMember,
queueUpdateDatabaseProfile,
- removeDeletedProfilesFromLeaderboards
+ removeDeletedProfilesFromLeaderboards,
+ SimpleAuctionSchema,
+ updateItemAuction
} from './database.js'
import { cleanElectionResponse, ElectionData } from './cleaners/skyblock/election.js'
import { cleanItemListResponse, ItemListData } from './cleaners/skyblock/itemList.js'
@@ -27,6 +31,7 @@ import typedHypixelApi from 'typed-hypixel-api'
import * as cached from './hypixelCached.js'
import { debug } from './index.js'
import { WithId } from 'mongodb'
+import { cleanEndedAuctions } from './cleaners/skyblock/endedAuctions.js'
export type Included = 'profiles' | 'player' | 'stats' | 'inventories' | undefined
@@ -57,8 +62,9 @@ const cleanResponseFunctions = {
'player': (data, options) => cleanPlayerResponse(data.player),
'skyblock/profile': (data: typedHypixelApi.SkyBlockProfileResponse, options) => cleanSkyblockProfileResponse(data.profile, options),
'skyblock/profiles': (data, options) => cleanSkyblockProfilesResponse(data.profiles),
+ 'skyblock/auctions_ended': (data, options) => cleanEndedAuctions(data),
'resources/skyblock/election': (data, options) => cleanElectionResponse(data),
- 'resources/skyblock/items': (data, options) => cleanItemListResponse(data)
+ 'resources/skyblock/items': (data, options) => cleanItemListResponse(data),
} as const
@@ -354,3 +360,91 @@ export async function fetchItemList() {
return itemList
}
+// this function is called from database.ts so it starts when we connect to the database
+// it should only ever be called once!
+export async function periodicallyFetchRecentlyEndedAuctions() {
+ let previousAuctionIds = new Set()
+
+ while (true) {
+ const endedAuctions = await sendCleanApiRequest(
+ 'skyblock/auctions_ended',
+ {}
+ )
+
+
+ let newAuctionUuids: Set<string> = new Set()
+ let newAuctionItemIds: Set<string> = new Set()
+
+ for (const auction of endedAuctions.auctions) {
+ if (previousAuctionIds.has(auction.id)) continue
+ newAuctionUuids.add(auction.id)
+ newAuctionItemIds.add(auction.item.id)
+ }
+ let updatedDatabaseAuctionItems: Map<string, ItemAuctionsSchema> = new Map()
+
+ const itemsAuctions = await fetchItemsAuctions(Array.from(newAuctionItemIds))
+ for (const itemAuctions of itemsAuctions) {
+ updatedDatabaseAuctionItems[itemAuctions._id] = itemAuctions
+ }
+
+ for (const auction of endedAuctions.auctions) {
+ if (previousAuctionIds.has(auction.id)) continue
+
+ let auctions: SimpleAuctionSchema[]
+ if (!updatedDatabaseAuctionItems.has(auction.item.id)) {
+ updatedDatabaseAuctionItems.set(auction.item.id, {
+ _id: auction.item.id,
+ auctions: [],
+ })
+ auctions = []
+ } else {
+ auctions = updatedDatabaseAuctionItems.get(auction.item.id)!.auctions
+ }
+
+ const simpleAuction: SimpleAuctionSchema = {
+ success: true,
+ coins: auction.coins,
+ id: auction.id,
+ ts: Math.floor(auction.timestamp / 1000),
+ bin: auction.bin,
+ }
+ // make sure the auction isn't already in there
+ if (auctions.findIndex((a) => a.id === simpleAuction.id) !== null) {
+ auctions.push(simpleAuction)
+ // keep only the last 100 items
+ if (auctions.length > 100)
+ auctions = auctions.slice(auctions.length - 100)
+ }
+
+ updatedDatabaseAuctionItems.set(auction.item.id, {
+ _id: auction.item.id,
+ auctions,
+ })
+ }
+
+ // we use a promise pool to set all the things fast but not overload the database
+ let tasks = Array.from(updatedDatabaseAuctionItems.values()).map(t => updateItemAuction(t))
+ async function doTasks() {
+ let hasTask = true
+ while (hasTask) {
+ const task = tasks.pop()
+ if (task) {
+ await task
+ } else
+ hasTask = false
+ }
+ }
+ // Promise.all 5 cycles
+ await Promise.all(Array(5).fill(0).map(_ => doTasks()))
+
+ previousAuctionIds = newAuctionUuids
+
+ let endedAgo = Date.now() - endedAuctions.lastUpdated
+ // +10 seconds just so we're sure we'll get the update
+ let refetchIn = 60 * 1000 - endedAgo + 10000
+
+ await new Promise(resolve => setTimeout(resolve, refetchIn))
+ }
+}
+
+