aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitpod.yml2
-rw-r--r--src/cleaners/skyblock/itemList.ts60
-rw-r--r--src/cleaners/skyblock/pets.ts10
-rw-r--r--src/hypixel.ts39
-rw-r--r--src/index.ts13
5 files changed, 118 insertions, 6 deletions
diff --git a/.gitpod.yml b/.gitpod.yml
index 92eee2d..f9a34b3 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -11,5 +11,5 @@ tasks:
ports:
- port: 8080
- onOpen: open-browser
+ onOpen: ignore
diff --git a/src/cleaners/skyblock/itemList.ts b/src/cleaners/skyblock/itemList.ts
new file mode 100644
index 0000000..a534628
--- /dev/null
+++ b/src/cleaners/skyblock/itemList.ts
@@ -0,0 +1,60 @@
+import typedHypixelApi from 'typed-hypixel-api'
+
+export interface ItemRequirement {
+ // idk what these do
+ // they'll probably be renamed at some point
+ dungeon: {
+ type: string
+ level: number
+ }
+}
+
+// based on Item from inventory.ts
+export interface ItemListItem {
+ id: string
+ vanillaId: string
+ tier: string | null
+ display: {
+ name: string
+ glint: boolean
+ }
+ npc_sell_price: number | null
+ requirements: ItemRequirement | null
+}
+
+export interface ItemListData {
+ lastUpdated: number
+ list: ItemListItem[]
+}
+
+function cleanItemRequirements(data: typedHypixelApi.SkyBlockItemsResponse['items'][number]['requirements'] & typedHypixelApi.SkyBlockItemsResponse['items'][number]['catacombs_requirements']): ItemRequirement | null {
+ if (!data || !data.dungeon) return null
+ return {
+ dungeon: {
+ type: data.dungeon.type,
+ level: data.dungeon.level
+ }
+ }
+}
+
+function cleanItemListItem(item: typedHypixelApi.SkyBlockItemsResponse['items'][number]): ItemListItem {
+ const vanillaId = item.material.toLowerCase()
+ return {
+ id: item.id,
+ vanillaId: item.durability ? `${vanillaId}:${item.durability}` : vanillaId,
+ tier: item.tier ?? null,
+ display: {
+ name: item.name,
+ glint: item.glowing ?? false
+ },
+ npc_sell_price: item.npc_sell_price ?? null,
+ requirements: cleanItemRequirements(item.catacombs_requirements ?? item.requirements)
+ }
+}
+
+export async function cleanItemListResponse(data: typedHypixelApi.SkyBlockItemsResponse): Promise<ItemListData> {
+ return {
+ lastUpdated: data.lastUpdated,
+ list: data.items.map(cleanItemListItem)
+ }
+} \ No newline at end of file
diff --git a/src/cleaners/skyblock/pets.ts b/src/cleaners/skyblock/pets.ts
index d6265e5..4c0fe4a 100644
--- a/src/cleaners/skyblock/pets.ts
+++ b/src/cleaners/skyblock/pets.ts
@@ -1,6 +1,8 @@
import typedHypixelApi from 'typed-hypixel-api'
-import { fetchPets } from '../../constants.js'
+import { fetchItemList } from '../../hypixel.js'
import { levelFromXpTable } from '../../util.js'
+import { fetchPets } from '../../constants.js'
+import { ItemListItem } from './itemList.js'
// https://hypixel-skyblock.fandom.com/wiki/Module:Pet/LevelingData?action=edit
@@ -43,7 +45,7 @@ export interface Pet {
level: number
tier: typedHypixelApi.Pet['tier']
skin: string | null
- item: string | null
+ item: ItemListItem | null
}
export interface PetsData {
@@ -59,6 +61,8 @@ export async function cleanPets(data: typedHypixelApi.SkyBlockProfileMember): Pr
const allPetIds = await fetchPets()
const obtainedPetIds: string[] = []
+ const itemList = await fetchItemList()
+
for (const petData of data.pets ?? []) {
const xpTable = RARITY_XP_TABLES[petData.tier]
const level = levelFromXpTable(petData.exp, xpTable)
@@ -69,7 +73,7 @@ export async function cleanPets(data: typedHypixelApi.SkyBlockProfileMember): Pr
level,
tier: petData.tier,
skin: petData.skin ?? null,
- item: petData.heldItem
+ item: petData.heldItem ? (itemList.list.find(i => i.id === petData.heldItem) ?? null) : null
}
obtainedPetIds.push(pet.id)
obtainedPets.push(pet)
diff --git a/src/hypixel.ts b/src/hypixel.ts
index 30a9f9b..80c73b1 100644
--- a/src/hypixel.ts
+++ b/src/hypixel.ts
@@ -25,6 +25,7 @@ import typedHypixelApi from 'typed-hypixel-api'
import * as cached from './hypixelCached.js'
import { debug } from './index.js'
import { WithId } from 'mongodb'
+import { cleanItemListResponse, ItemListData } from './cleaners/skyblock/itemList.js'
export type Included = 'profiles' | 'player' | 'stats' | 'inventories' | undefined
@@ -56,7 +57,8 @@ 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),
- 'resources/skyblock/election': (data, options) => cleanElectionResponse(data)
+ 'resources/skyblock/election': (data, options) => cleanElectionResponse(data),
+ 'resources/skyblock/items': (data, options) => cleanItemListResponse(data)
} as const
@@ -310,3 +312,38 @@ export async function fetchElection(): Promise<ElectionData> {
return election
}
+
+let isFetchingItemList = false
+let cachedItemListData: ItemListData | null = null
+let nextItemListUpdate: Date = new Date(0)
+
+export async function fetchItemList() {
+ if (cachedItemListData && nextItemListUpdate > new Date())
+ return cachedItemListData
+
+ // if it's currently fetching the election data and it doesn't have it,
+ // wait until we do have the election data
+ if (isFetchingItemList && !cachedItemListData) {
+ await new Promise(resolve => {
+ const interval = setInterval(() => {
+ if (cachedItemListData) {
+ clearInterval(interval)
+ resolve(cachedItemListData)
+ }
+ }, 100)
+ })
+ }
+
+ isFetchingItemList = true
+ const itemList: ItemListData = await sendCleanApiRequest(
+ 'resources/skyblock/items',
+ {}
+ )
+ isFetchingItemList = false
+
+ cachedItemListData = itemList
+ // updates every 60 minutes
+ nextElectionUpdate = new Date((itemList.lastUpdated + 60 * 60) * 1000)
+ return itemList
+}
+
diff --git a/src/index.ts b/src/index.ts
index 4464ca7..460fec3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,5 @@
import { createSession, fetchAccountFromDiscord, fetchAllLeaderboardsCategorized, fetchLeaderboard, fetchMemberLeaderboardSpots, fetchSession, finishedCachingRawLeaderboards, leaderboardUpdateMemberQueue, leaderboardUpdateProfileQueue, updateAccount, fetchServerStatus, deleteSession } from './database.js'
-import { fetchElection, fetchMemberProfile, fetchUser } from './hypixel.js'
+import { 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'
@@ -153,6 +153,17 @@ app.get('/election', async (req, res) => {
}
})
+app.get('/items', async (req, res) => {
+ try {
+ res.json(
+ await fetchItemList()
+ )
+ } catch (err) {
+ console.error(err)
+ res.json({ ok: false })
+ }
+})
+
app.post('/accounts/createsession', async (req, res) => {
try {
const { code } = req.body