aboutsummaryrefslogtreecommitdiff
path: root/src/cleaners
diff options
context:
space:
mode:
Diffstat (limited to 'src/cleaners')
-rw-r--r--src/cleaners/achievements.ts18
-rw-r--r--src/cleaners/player.ts12
-rw-r--r--src/cleaners/skyblock/member.ts14
-rw-r--r--src/cleaners/skyblock/skills.ts66
4 files changed, 94 insertions, 16 deletions
diff --git a/src/cleaners/achievements.ts b/src/cleaners/achievements.ts
new file mode 100644
index 0000000..9e4c7ae
--- /dev/null
+++ b/src/cleaners/achievements.ts
@@ -0,0 +1,18 @@
+import typedHypixelApi from 'typed-hypixel-api'
+
+export interface Achievements {
+ skyblock: Record<string, number>
+}
+
+export function cleanPlayerAchievements(data: typedHypixelApi.PlayerDataResponse['player']): Achievements {
+ const achievements: Achievements = {
+ skyblock: {}
+ }
+
+ for (const [id, value] of Object.entries(data.achievements)) {
+ if (id.startsWith('skyblock_'))
+ achievements.skyblock[id.substring(9)] = value
+ }
+
+ return achievements
+}
diff --git a/src/cleaners/player.ts b/src/cleaners/player.ts
index 2d819e9..8facdad 100644
--- a/src/cleaners/player.ts
+++ b/src/cleaners/player.ts
@@ -1,6 +1,7 @@
import { cleanSocialMedia, CleanSocialMedia } from './socialmedia.js'
import { cleanPlayerSkyblockProfiles } from './skyblock/profiles.js'
import { cleanPlayerSkyblockClaimed } from './skyblock/claimed.js'
+import { cleanPlayerAchievements, Achievements } from './achievements.js'
import { CleanBasicProfile } from './skyblock/profile.js'
import { cleanRank, CleanRank } from './rank.js'
import typedHypixelApi from 'typed-hypixel-api'
@@ -28,16 +29,21 @@ export interface CleanPlayer extends CleanBasicPlayer {
claimed?: ClaimedSkyBlockItem[]
}
-export async function cleanPlayerResponse(data: typedHypixelApi.PlayerDataResponse['player']): Promise<CleanPlayer | null> {
+export interface CleanFullPlayer extends CleanPlayer {
+ achievements: Achievements
+}
+
+export async function cleanPlayerResponse(data: typedHypixelApi.PlayerDataResponse['player']): Promise<CleanFullPlayer | null> {
// Cleans up a 'player' api response
if (!data)
- return null // bruh
+ return null
return {
uuid: undashUuid(data.uuid),
username: data.displayname,
rank: cleanRank(data),
socials: cleanSocialMedia(data),
profiles: cleanPlayerSkyblockProfiles(data.stats?.SkyBlock?.profiles),
- claimed: cleanPlayerSkyblockClaimed(data)
+ claimed: cleanPlayerSkyblockClaimed(data),
+ achievements: cleanPlayerAchievements(data)
}
}
diff --git a/src/cleaners/skyblock/member.ts b/src/cleaners/skyblock/member.ts
index 57462ed..6b2f452 100644
--- a/src/cleaners/skyblock/member.ts
+++ b/src/cleaners/skyblock/member.ts
@@ -10,7 +10,7 @@ import { CleanMinion, cleanMinions } from './minions.js'
import { cleanSlayers, SlayerData } from './slayers.js'
import { AccountCustomization } from '../../database.js'
import { cleanVisitedZones, Zone } from './zones.js'
-import { cleanSkills, Skill } from './skills.js'
+import { cleanSkills, Skills } from './skills.js'
import * as cached from '../../hypixelCached.js'
import typedHypixelApi from 'typed-hypixel-api'
import { cleanPets, PetsData } from './pets.js'
@@ -37,7 +37,7 @@ export interface CleanMember extends CleanBasicMember {
fairySouls: FairySouls
inventories?: Inventories
objectives: Objective[]
- skills: Skill[]
+ skills: Skills
zones: Zone[]
collections: Collection[]
slayers: SlayerData
@@ -50,7 +50,7 @@ export interface CleanMember extends CleanBasicMember {
}
export async function cleanSkyBlockProfileMemberResponseBasic(member: typedHypixelApi.SkyBlockProfileMember & { uuid: string }): Promise<CleanBasicMember | null> {
- const player = await cached.fetchPlayer(member.uuid)
+ const player = await cached.fetchPlayer(member.uuid, false)
if (!player) return null
return {
uuid: member.uuid,
@@ -64,7 +64,7 @@ export async function cleanSkyBlockProfileMemberResponseBasic(member: typedHypix
/** Cleans up a member (from skyblock/profile) */
export async function cleanSkyBlockProfileMemberResponse(member: typedHypixelApi.SkyBlockProfileMember & { uuid: string }, profileId?: string, included: Included[] | undefined = undefined): Promise<CleanMember | null> {
const inventoriesIncluded = included === undefined || included.includes('inventories')
- const player = await cached.fetchPlayer(member.uuid)
+ const player = await cached.fetchPlayer(member.uuid, true)
if (!player) return null
const fairySouls = await cleanFairySouls(member)
@@ -74,7 +74,7 @@ export async function cleanSkyBlockProfileMemberResponse(member: typedHypixelApi
const coopInvitationPromise = cleanCoopInvitation(member, member.uuid)
const minionsPromise = cleanMinions(member)
- const skillsPromise = cleanSkills(member)
+ const skillsPromise = cleanSkills(member, player)
const zonesPromise = cleanVisitedZones(member)
const petsPromise = cleanPets(member)
const harpPromise = cleanHarp(member)
@@ -100,7 +100,9 @@ export async function cleanSkyBlockProfileMemberResponse(member: typedHypixelApi
fairySouls: fairySouls,
inventories: inventoriesPromise ? await inventoriesPromise : undefined,
objectives: cleanObjectives(member),
+
skills: await skillsPromise,
+
zones: await zonesPromise,
collections: cleanCollections(member),
slayers: cleanSlayers(member),
@@ -126,7 +128,7 @@ export interface CleanMemberProfilePlayer extends CleanPlayer {
fairySouls: FairySouls
inventories?: Inventories
objectives: Objective[]
- skills: Skill[]
+ skills: Skills
zones: Zone[]
collections: Collection[]
slayers: SlayerData
diff --git a/src/cleaners/skyblock/skills.ts b/src/cleaners/skyblock/skills.ts
index d035a96..8d0f16d 100644
--- a/src/cleaners/skyblock/skills.ts
+++ b/src/cleaners/skyblock/skills.ts
@@ -2,9 +2,10 @@ import typedHypixelApi from 'typed-hypixel-api'
import { fetchSkills } from '../../constants.js'
import { levelFromXpTable } from '../../util.js'
import * as constants from '../../constants.js'
+import { CleanFullPlayer } from '../player.js'
export interface Skill {
- name: string
+ id: string
xp: number
level: number
@@ -14,6 +15,16 @@ export interface Skill {
levelXpRequired: number
}
+export interface Skills {
+ list: Skill[]
+ /**
+ * Whether the player has their skills API enabled. If this is off, that
+ * means the data doesn't include xp and is per-player. You should show a
+ * warning to the user.
+ */
+ apiEnabled: boolean
+}
+
// the highest level you can have in each skill
// numbers taken from https://hypixel-skyblock.fandom.com/wiki/Skills
const skillsMaxLevel: { [key: string]: number } = {
@@ -137,7 +148,39 @@ export function levelForSkillXp(xp: number, maxLevel: number) {
return levelFromXpTable(xp, xpTable)
}
-export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember): Promise<Skill[]> {
+function skillFromLevel(id: string, level: number): Skill {
+ const maxLevel = skillsMaxLevel[id] ?? skillsDefaultMaxLevel
+ const xpTable = (maxLevel <= 25 ? skillXpTableEasier : skillXpTable).slice(0, maxLevel)
+ const xp = level > 0 ? xpTable[level - 1] ?? 0 : 0
+
+ return {
+ id,
+ level,
+ levelXp: 0,
+ levelXpRequired: xpTable[level],
+ maxLevel: maxLevel,
+ xp
+ }
+}
+
+function skillsFromSkyBlockAchievements(achievements: CleanFullPlayer['achievements']['skyblock']): Skills {
+ return {
+ apiEnabled: false,
+ list: [
+ skillFromLevel('fishing', achievements['angler']),
+ skillFromLevel('enchanting', achievements['augmentation']),
+ skillFromLevel('combat', achievements['combat']),
+ skillFromLevel('alchemy', achievements['concoctor']),
+ skillFromLevel('taming', achievements['domesticator']),
+ skillFromLevel('dungeoneering', achievements['dungeoneer']),
+ skillFromLevel('mining', achievements['excavator']),
+ skillFromLevel('foraging', achievements['gatherer']),
+ skillFromLevel('farming', achievements['harvester'])
+ ]
+ }
+}
+
+export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember, player: CleanFullPlayer): Promise<Skills> {
const allSkillNames = await fetchSkills()
const skills: Skill[] = []
@@ -168,7 +211,7 @@ export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember):
const skillLevelXpRequired = xpTable[skillLevel] - previousLevelXp
skills.push({
- name: skillName,
+ id: skillName,
xp: skillXp,
level: skillLevel,
maxLevel: skillMaxLevel,
@@ -178,16 +221,22 @@ export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember):
}
}
+ // if the player has no skills but has kills, we can assume they have the skills api off
+ // (we check kills to know whether the profile is actually used, this is kinda arbitrary)
+ if (skills.length === 0 && Object.keys(data.stats).includes('kills')) {
+ return skillsFromSkyBlockAchievements(player.achievements.skyblock)
+ }
+
constants.addSkills(skillNamesFound)
// add missing skills
- const missingSkillNames = allSkillNames.filter(skillName => !skills.some(skill => skill.name === skillName))
+ const missingSkillNames = allSkillNames.filter(skillName => !skills.some(skill => skill.id === skillName))
for (const skillName of missingSkillNames) {
const skillMaxLevel = skillsMaxLevel[skillName] ?? skillsDefaultMaxLevel
const xpTable = (skillMaxLevel <= 25 ? skillXpTableEasier : skillXpTable).slice(0, skillMaxLevel)
skills.push({
- name: skillName,
+ id: skillName,
xp: 0,
level: 0,
maxLevel: skillMaxLevel,
@@ -197,7 +246,10 @@ export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember):
}
// sort skills by name
- skills.sort((a, b) => a.name.localeCompare(b.name))
+ skills.sort((a, b) => a.id.localeCompare(b.id))
- return skills
+ return {
+ apiEnabled: true,
+ list: skills,
+ }
}