aboutsummaryrefslogtreecommitdiff
path: root/cleaners
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2021-02-13 13:56:19 -0600
committermat <27899617+mat-1@users.noreply.github.com>2021-02-13 13:56:19 -0600
commita23103ec24128f2e24b93ad101ade6dfdd4758c3 (patch)
treec4d543a2003062a7c213d37f5d06a826c2a88798 /cleaners
parentd7b9d1fc5cfc8c648604eb1d178091873ea698a6 (diff)
downloadskyblock-api-a23103ec24128f2e24b93ad101ade6dfdd4758c3.tar.gz
skyblock-api-a23103ec24128f2e24b93ad101ade6dfdd4758c3.tar.bz2
skyblock-api-a23103ec24128f2e24b93ad101ade6dfdd4758c3.zip
Basic profile stats
Diffstat (limited to 'cleaners')
-rw-r--r--cleaners/player.ts28
-rw-r--r--cleaners/rank.ts66
-rw-r--r--cleaners/skyblock/minions.ts70
-rw-r--r--cleaners/skyblock/stats.ts73
-rw-r--r--cleaners/socialmedia.ts14
5 files changed, 251 insertions, 0 deletions
diff --git a/cleaners/player.ts b/cleaners/player.ts
new file mode 100644
index 0000000..c3afd6f
--- /dev/null
+++ b/cleaners/player.ts
@@ -0,0 +1,28 @@
+import { CleanBasicProfile, cleanPlayerSkyblockProfiles, Included } from '../hypixel'
+import { CleanSocialMedia, parseSocialMedia } from './socialmedia'
+import { CleanRank, parseRank } from './rank'
+import { HypixelPlayer } from '../hypixelApi'
+import { undashUuid } from '../util'
+
+export interface CleanBasicPlayer {
+ uuid: string
+ username: string
+}
+
+export interface CleanPlayer extends CleanBasicPlayer {
+ rank: CleanRank
+ socials: CleanSocialMedia
+ profiles?: CleanBasicProfile[]
+}
+
+export async function cleanPlayerResponse(data: HypixelPlayer): Promise<CleanPlayer> {
+ // Cleans up a 'player' api response
+ console.log('cleanPlayerResponse', data.stats.SkyBlock.profiles)
+ return {
+ uuid: undashUuid(data.uuid),
+ username: data.displayname,
+ rank: parseRank(data),
+ socials: parseSocialMedia(data.socialMedia),
+ profiles: cleanPlayerSkyblockProfiles(data.stats.SkyBlock.profiles)
+ }
+}
diff --git a/cleaners/rank.ts b/cleaners/rank.ts
new file mode 100644
index 0000000..928373a
--- /dev/null
+++ b/cleaners/rank.ts
@@ -0,0 +1,66 @@
+import { HypixelPlayer } from '../hypixelApi'
+import { colorCodeFromName, minecraftColorCodes } from '../util'
+
+const rankColors: { [ name: string ]: string } = {
+ 'NONE': '7',
+ 'VIP': 'a',
+ 'VIP+': 'a',
+ 'MVP': 'b',
+ 'MVP+': 'b',
+ 'MVP++': '6',
+ 'YOUTUBE': 'c',
+ 'HELPER': '9',
+ 'MODERATOR': '2',
+ 'ADMIN': 'c'
+}
+
+export interface CleanRank {
+ name: string,
+ color: string | null,
+ colored: string | null,
+}
+
+/** Response cleaning (reformatting to be nicer) */
+export function parseRank({
+ packageRank,
+ newPackageRank,
+ monthlyPackageRank,
+ rankPlusColor,
+ rank,
+ prefix
+}: HypixelPlayer): CleanRank {
+ let name
+ let color
+ let colored
+ if (prefix) { // derive values from prefix
+ colored = prefix
+ color = minecraftColorCodes[colored.match(/§./)[0][1]]
+ name = colored.replace(/§./g, '').replace(/[\[\]]/g, '')
+ } else {
+ name = rank
+ || newPackageRank.replace('_PLUS', '+')
+ || packageRank.replace('_PLUS', '+')
+ || monthlyPackageRank
+
+ // MVP++ is called Superstar for some reason
+ if (name === 'SUPERSTAR') name = 'MVP++'
+ // YouTube rank is called YouTuber, change this to the proper name
+ else if (name === 'YOUTUBER') name = 'YOUTUBE'
+
+ const plusColor = colorCodeFromName(rankPlusColor)
+ color = minecraftColorCodes[rankColors[name]]
+ const rankColorPrefix = rankColors[name] ? '§' + rankColors[name] : ''
+ const nameWithoutPlus = name.split('+')[0]
+ const plusesInName = '+'.repeat(name.split('+').length - 1)
+ console.log(plusColor, nameWithoutPlus, plusesInName)
+ if (plusColor && plusesInName.length >= 1)
+ colored = `${rankColorPrefix}[${nameWithoutPlus}§${plusColor}${plusesInName}${rankColorPrefix}]`
+ else
+ colored = `${rankColorPrefix}[${name}]`
+ }
+ return {
+ name,
+ color,
+ colored
+ }
+}
diff --git a/cleaners/skyblock/minions.ts b/cleaners/skyblock/minions.ts
new file mode 100644
index 0000000..da69634
--- /dev/null
+++ b/cleaners/skyblock/minions.ts
@@ -0,0 +1,70 @@
+import { maxMinion } from '../../hypixel'
+
+export interface CleanMinion {
+ name: string,
+ levels: boolean[]
+}
+
+
+/**
+ * Clean the minions provided by Hypixel
+ * @param minionsRaw The minion data provided by the Hypixel API
+ */
+export function cleanMinions(minionsRaw: string[]): CleanMinion[] {
+ const minions: CleanMinion[] = []
+ for (const minionRaw of minionsRaw ?? []) {
+ // do some regex magic to get the minion name and level
+ // examples of potential minion names: CLAY_11, PIG_1, MAGMA_CUBE_4
+ const minionName = minionRaw.split(/_\d/)[0].toLowerCase()
+ const minionLevel = parseInt(minionRaw.split(/\D*_/)[1])
+ let matchingMinion = minions.find(m => m.name === minionName)
+ if (!matchingMinion) {
+ // if the minion doesnt already exist in the minions array, then create it
+ matchingMinion = {
+ name: minionName,
+ levels: new Array(maxMinion).fill(false)
+ }
+ minions.push(matchingMinion)
+ }
+ while (minionLevel > matchingMinion.levels.length)
+ // if hypixel increases the minion level, this will increase with it
+ matchingMinion.levels.push(false)
+
+ // set the minion at that level to true
+ matchingMinion.levels[minionLevel - 1] = true
+ }
+ return minions
+}
+
+/**
+ * Combine multiple arrays of minions into one, useful when getting the minions for members
+ * @param minions An array of arrays of minions
+ */
+export function combineMinionArrays(minions: CleanMinion[][]): CleanMinion[] {
+ const resultMinions: CleanMinion[] = []
+
+ for (const memberMinions of minions) {
+ for (const minion of memberMinions) {
+ // this is a reference, so we can directly modify the attributes for matchingMinionReference
+ // and they'll be in the resultMinions array
+ const matchingMinionReference = resultMinions.find(m => m.name === minion.name)
+ if (!matchingMinionReference) {
+ // if the minion name isn't already in the array, add it!
+ resultMinions.push(minion)
+ } else {
+
+ // This should never happen, but in case the length of `minion.levels` is longer than
+ // `matchingMinionReference.levels`, then it should be extended to be equal length
+ while (matchingMinionReference.levels.length < minion.levels.length)
+ matchingMinionReference.levels.push(null)
+
+ for (let i = 0; i < minion.levels.length; i++) {
+ if (minion.levels[i])
+ matchingMinionReference.levels[i] = true
+ }
+ }
+ }
+ }
+
+ return resultMinions
+} \ No newline at end of file
diff --git a/cleaners/skyblock/stats.ts b/cleaners/skyblock/stats.ts
new file mode 100644
index 0000000..07d9133
--- /dev/null
+++ b/cleaners/skyblock/stats.ts
@@ -0,0 +1,73 @@
+const statCategories: { [ key: string ]: string[] | null } = { // sorted in order of importance
+ 'deaths': ['deaths_', 'deaths'],
+ 'kills': ['kills_', 'kills'],
+ 'fishing': ['items_fished_', 'items_fished'],
+ 'auctions': ['auctions_'],
+ 'races': ['_best_time'],
+ 'misc': null // everything else goes here
+}
+
+interface statCategory {
+ category: string,
+ name: string
+}
+
+function categorizeStat(statNameRaw: string): statCategory {
+ // 'deaths_void'
+ for (const statCategory in statCategories) {
+ // 'deaths'
+ const statCategoryMatchers = statCategories[statCategory]
+ if (statCategoryMatchers == null) {
+ // If it's null, just go with this. Can only ever be 'misc'
+ return {
+ category: statCategory,
+ name: statNameRaw
+ }
+ }
+ for (const categoryMatch of statCategoryMatchers) {
+ // ['deaths_']
+ let trailingEnd = categoryMatch[0] == '_'
+ let trailingStart = categoryMatch.substr(-1) == '_'
+ if (trailingStart && statNameRaw.startsWith(categoryMatch)) {
+ return {
+ category: statCategory,
+ name: statNameRaw.substr(categoryMatch.length)
+ }
+ } else if (trailingEnd && statNameRaw.endsWith(categoryMatch)) {
+ return {
+ category: statCategory,
+ name: statNameRaw.substr(0, categoryMatch.length)
+ }
+ } else if (statNameRaw == categoryMatch) {
+ // if it matches exactly, we don't know the name. will be defaulted to category later on
+ return {
+ category: statCategory,
+ name: null
+ }
+ }
+ }
+ }
+ // this should never happen, as it'll default to misc and return if nothing is found
+ return {
+ category: null,
+ name: statNameRaw
+ }
+}
+
+export interface CleanProfileStats {
+ [ category: string ]: {
+ [ stat: string ]: any
+ total?: any
+ }
+}
+
+export function cleanProfileStats(statsRaw): CleanProfileStats {
+ // TODO: add type for statsRaw (probably in hypixelApi.ts since its coming from there)
+ const stats: CleanProfileStats = {}
+ for (let statNameRaw in statsRaw) {
+ let { category: statCategory, name: statName } = categorizeStat(statNameRaw)
+ if (!stats[statCategory]) stats[statCategory] = {}
+ stats[statCategory][statName || 'total'] = statsRaw[statNameRaw]
+ }
+ return stats
+}
diff --git a/cleaners/socialmedia.ts b/cleaners/socialmedia.ts
new file mode 100644
index 0000000..c1f9551
--- /dev/null
+++ b/cleaners/socialmedia.ts
@@ -0,0 +1,14 @@
+import { HypixelPlayerSocialMedia } from "../hypixelApi";
+
+export interface CleanSocialMedia {
+ discord: string | null
+ forums: string | null
+}
+
+export function parseSocialMedia(socialMedia: HypixelPlayerSocialMedia): CleanSocialMedia {
+ return {
+ discord: socialMedia?.links?.DISCORD || null,
+ forums: socialMedia?.links?.HYPIXEL || null
+ }
+}
+