diff options
Diffstat (limited to 'src/cleaners')
-rw-r--r-- | src/cleaners/achievements.ts | 18 | ||||
-rw-r--r-- | src/cleaners/player.ts | 12 | ||||
-rw-r--r-- | src/cleaners/skyblock/member.ts | 14 | ||||
-rw-r--r-- | src/cleaners/skyblock/skills.ts | 66 |
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, + } } |