diff --git a/API/getSkyblockAuctions.ts b/API/getSkyblockAuctions.ts deleted file mode 100644 index e115a5b0..00000000 --- a/API/getSkyblockAuctions.ts +++ /dev/null @@ -1,85 +0,0 @@ -import AuctionInfo from '../src/structures/SkyBlock/Auctions/AuctionInfo'; -import Auction from '../src/structures/SkyBlock/Auctions/Auction'; -import Errors from '../src/Errors'; -async function getPage(this: any, page: any = 0, options: any = {}) { - // eslint-disable-next-line no-underscore-dangle - const content = await this._makeRequest(`/skyblock/auctions?page=${page}`, false); - const result: any = {}; - if (!options.noInfo) result.info = new AuctionInfo(content); - if (options.raw) result.auctions = content.auctions; - else if (options.noAuctions) result.auctions = []; - else result.auctions = content.auctions.map((x: any) => new Auction(x, options.includeItemBytes)); - return result; -} -async function noReject(promise: any, args: any = [], retries: any = 3, cooldown: any = 100) { - try { - const result = await promise.call(null, ...args); - return result; - } catch { - if (retries) { - await new Promise((resolve) => setTimeout(resolve, cooldown)); - return await noReject(promise, args, retries - 1, cooldown); - } - return null; - } -} - -import Endpoint from '../src/Private/Endpoint'; -import Client from '../src/Client'; -export default class getSkyblockAuctions extends Endpoint { - readonly client: Client; - readonly name: string; - constructor(client: Client) { - super(client); - this.client = client; - this.name = 'getSkyblockAuctions'; - } - - async execute(range: any, options: any) { - options.retries ||= 3; - options.cooldown ||= 100; - if (null === range || '*' === range) range = [0, (await getPage(0, { noAuctions: true })).info.totalPages]; - if (!Array.isArray(range)) range = [parseInt(range), parseInt(range)]; - if (isNaN(range[0])) throw new Error(Errors.PAGE_INDEX_ERROR); - if (parseInt(options.retries) !== options.retries || 10 < options.retries || 0 > options.retries) { - throw new Error(Errors.INVALID_OPTION_VALUE); - } - if (parseInt(options.cooldown) !== options.cooldown || 3000 < options.cooldown || 0 > options.cooldown) { - throw new Error(Errors.INVALID_OPTION_VALUE); - } - range = range.sort(); - const result: any = { auctions: [] }; - const fetches = []; - const failedPages = []; - if (options.noAuctions) { - return { info: options.noInfo ? null : (await getPage(range[1], { noAuctions: true })).info }; - } - for (let i = range[0]; i <= range[1]; i++) { - if (options.race) { - fetches.push(noReject(getPage, [i, options], options.retries, options.cooldown)); - } else { - const resp = await noReject(getPage, [i, options], options.retries, options.cooldown); - if (resp) { - result.auctions = result.auctions.concat(resp.auctions); - if (resp.info) result.info = resp.info; - } else { - failedPages.push(i); - } - } - } - if (fetches.length) { - result.auctions = (await Promise.all(fetches)).reduce((pV, cV, index) => { - if (!cV) { - failedPages.push(index + range[0]); - return pV; - } - if (cV.info) result.info = cV.info; - if (cV.auctions.length) return pV.concat(cV.auctions); - return pV; - }, []); - } - // eslint-disable-next-line no-underscore-dangle - result.info = result.info ? result.info._extend('failedPages', failedPages) : { failedPages }; - return result; - } -} diff --git a/src/API/getGuild.ts b/src/API/getGuild.ts index 15c5cec8..e2c4c5eb 100644 --- a/src/API/getGuild.ts +++ b/src/API/getGuild.ts @@ -2,7 +2,6 @@ import Guild from '../structures/Guild/Guild'; import isGuildID from '../utils/isGuildID'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getGuild extends Endpoint { @@ -13,15 +12,17 @@ export default class getGuild extends Endpoint { } async execute(searchParameter: 'id' | 'name' | 'player', query: string): Promise { - if (!query) throw new Error(Errors.NO_GUILD_QUERY); - if ('id' === searchParameter && !isGuildID(query)) throw new Error(Errors.INVALID_GUILD_ID); + if (!query) throw new Error(this.client.errors.NO_GUILD_QUERY); + if ('id' === searchParameter && !isGuildID(query)) throw new Error(this.client.errors.INVALID_GUILD_ID); const isPlayerQuery = 'player' === searchParameter; if (isPlayerQuery) query = await toUuid(query); - if (!['id', 'name', 'player'].includes(searchParameter)) throw new Error(Errors.INVALID_GUILD_SEARCH_PARAMETER); + if (!['id', 'name', 'player'].includes(searchParameter)) { + throw new Error(this.client.errors.INVALID_GUILD_SEARCH_PARAMETER); + } const res = await this.client.requests.request(`/guild?${searchParameter}=${encodeURI(query)}`); if (res.raw) return res; if (!res.guild && 'player' !== searchParameter) { - throw new Error(Errors.GUILD_DOES_NOT_EXIST); + throw new Error(this.client.errors.GUILD_DOES_NOT_EXIST); } return res.guild ? new Guild(res.guild, isPlayerQuery ? query : undefined) : null; diff --git a/src/API/getHouse.ts b/src/API/getHouse.ts index 1e7fabc5..7830dce9 100644 --- a/src/API/getHouse.ts +++ b/src/API/getHouse.ts @@ -1,6 +1,5 @@ import Endpoint from '../Private/Endpoint'; import House from '../structures/House'; -import Errors from '../Errors'; import Client from '../Client'; export default class getHouse extends Endpoint { @@ -11,7 +10,7 @@ export default class getHouse extends Endpoint { } async execute(query: string): Promise { - if (!query) throw new Error(Errors.NO_UUID); + if (!query) throw new Error(this.client.errors.NO_UUID); const res = await this.client.requests.request(`/housing/house?house=${query}`); if (res.raw) return res; return new House(res); diff --git a/src/API/getLeaderboards.ts b/src/API/getLeaderboards.ts index 11f757ca..aac8d0ee 100644 --- a/src/API/getLeaderboards.ts +++ b/src/API/getLeaderboards.ts @@ -1,7 +1,6 @@ import Leaderboard from '../structures/Leaderboard'; import Constants from '../utils/Constants'; import Endpoint from '../Private/Endpoint'; -import Errors from '../Errors'; import Client from '../Client'; export default class getLeaderboards extends Endpoint { @@ -14,7 +13,7 @@ export default class getLeaderboards extends Endpoint { async execute(): Promise { const res = await this.client.requests.request('/leaderboards'); if (res.raw) return res; - if (!res.leaderboards) throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, 'Try again.')); + if (!res.leaderboards) throw new Error(this.client.errors.SOMETHING_WENT_WRONG.replace(/{cause}/, 'Try again.')); const lbnames = Object.create(Constants.leaderboardNames); for (const name in lbnames) { lbnames[name] = res.leaderboards[lbnames[name]].length diff --git a/src/API/getPlayer.ts b/src/API/getPlayer.ts index 2651af23..a6b08583 100644 --- a/src/API/getPlayer.ts +++ b/src/API/getPlayer.ts @@ -1,7 +1,6 @@ import Endpoint from '../Private/Endpoint'; import Player from '../structures/Player'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getPlayer extends Endpoint { @@ -12,11 +11,11 @@ export default class getPlayer extends Endpoint { } async execute(query: string): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/player?uuid=${query}`); if (res.raw) return res; - if (query && !res.player) throw new Error(Errors.PLAYER_HAS_NEVER_LOGGED); + if (query && !res.player) throw new Error(this.client.errors.PLAYER_HAS_NEVER_LOGGED); return new Player(res.player); } } diff --git a/src/API/getPlayerHouses.ts b/src/API/getPlayerHouses.ts index fa8cd275..a9bbe18c 100644 --- a/src/API/getPlayerHouses.ts +++ b/src/API/getPlayerHouses.ts @@ -1,7 +1,6 @@ import Endpoint from '../Private/Endpoint'; import House from '../structures/House'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getPlayerHouses extends Endpoint { @@ -12,7 +11,7 @@ export default class getPlayerHouses extends Endpoint { } async execute(query: string): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/housing/houses?player=${query}`); if (res.raw) return res; diff --git a/src/API/getRecentGames.ts b/src/API/getRecentGames.ts index 6ea63eb7..89fb5f4c 100644 --- a/src/API/getRecentGames.ts +++ b/src/API/getRecentGames.ts @@ -1,7 +1,6 @@ import RecentGame from '../structures/RecentGame'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getRecentGames extends Endpoint { @@ -12,7 +11,7 @@ export default class getRecentGames extends Endpoint { } async execute(query: string): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/recentgames?uuid=${query}`); if (res.raw) return res; diff --git a/src/API/getSkyblockAuction.ts b/src/API/getSkyblockAuction.ts index e7c9a735..9d396ecd 100644 --- a/src/API/getSkyblockAuction.ts +++ b/src/API/getSkyblockAuction.ts @@ -1,7 +1,6 @@ import Auction from '../structures/SkyBlock/Auctions/Auction'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getSkyblockAction extends Endpoint { @@ -16,7 +15,7 @@ export default class getSkyblockAction extends Endpoint { type: 'PROFILE' | 'PLAYER' | 'AUCTION', includeItemBytes: boolean = false ): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); let filter; if ('PROFILE' === type) { filter = 'profile'; @@ -26,7 +25,7 @@ export default class getSkyblockAction extends Endpoint { } else if ('AUCTION' === type) { filter = 'uuid'; } else { - throw new Error(Errors.BAD_AUCTION_FILTER); + throw new Error(this.client.errors.BAD_AUCTION_FILTER); } const res = await this.client.requests.request(`/skyblock/auction?${filter}=${query}`); if (res.raw) return res; diff --git a/src/API/getSkyblockAuctions.ts b/src/API/getSkyblockAuctions.ts new file mode 100644 index 00000000..8c8cbe87 --- /dev/null +++ b/src/API/getSkyblockAuctions.ts @@ -0,0 +1,85 @@ +import AuctionInfo from '../structures/SkyBlock/Auctions/AuctionInfo'; +import Auction from '../structures/SkyBlock/Auctions/Auction'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; + +export default class getSkyblockAuctions extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockAuctions'; + } + + async execute(range: any, options: any) { + options.retries ||= 3; + options.cooldown ||= 100; + if (null === range || '*' === range) range = [0, (await this.getPage(0, { noAuctions: true })).info.totalPages]; + if (!Array.isArray(range)) range = [parseInt(range), parseInt(range)]; + if (isNaN(range[0])) throw new Error(this.client.errors.PAGE_INDEX_ERROR); + if (parseInt(options.retries) !== options.retries || 10 < options.retries || 0 > options.retries) { + throw new Error(this.client.errors.INVALID_OPTION_VALUE); + } + if (parseInt(options.cooldown) !== options.cooldown || 3000 < options.cooldown || 0 > options.cooldown) { + throw new Error(this.client.errors.INVALID_OPTION_VALUE); + } + range = range.sort(); + const result: any = { auctions: [] }; + const fetches = []; + const failedPages = []; + if (options.noAuctions) { + return { info: options.noInfo ? null : (await this.getPage(range[1], { noAuctions: true })).info }; + } + for (let i = range[0]; i <= range[1]; i++) { + if (options.race) { + fetches.push(this.noReject(this.getPage, [i, options], options.retries, options.cooldown)); + } else { + const resp = await this.noReject(this.getPage, [i, options], options.retries, options.cooldown); + if (resp) { + result.auctions = result.auctions.concat(resp.auctions); + if (resp.info) result.info = resp.info; + } else { + failedPages.push(i); + } + } + } + if (fetches.length) { + result.auctions = (await Promise.all(fetches)).reduce((pV, cV, index) => { + if (!cV) { + failedPages.push(index + range[0]); + return pV; + } + if (cV.info) result.info = cV.info; + if (cV.auctions.length) return pV.concat(cV.auctions); + return pV; + }, []); + } + // eslint-disable-next-line no-underscore-dangle + result.info = result.info ? result.info._extend('failedPages', failedPages) : { failedPages }; + return result; + } + + async getPage(page: any = 0, options: any = {}): Promise { + const content = await this.client.requests.request(`/skyblock/auctions?page=${page}`); + const result: any = {}; + if (!options.noInfo) result.info = new AuctionInfo(content); + if (options.raw) result.auctions = content.auctions; + else if (options.noAuctions) result.auctions = []; + else result.auctions = content.auctions.map((x: any) => new Auction(x, options.includeItemBytes)); + return result; + } + + async noReject(promise: any, args: any = [], retries: any = 3, cooldown: any = 100): Promise { + try { + const result = await promise.call(null, ...args); + return result; + } catch { + if (retries) { + await new Promise((resolve) => setTimeout(resolve, cooldown)); + return await this.noReject(promise, args, retries - 1, cooldown); + } + return null; + } + } +} diff --git a/src/API/getSkyblockAuctionsByPlayer.ts b/src/API/getSkyblockAuctionsByPlayer.ts index 7939cf6f..1ab22e93 100644 --- a/src/API/getSkyblockAuctionsByPlayer.ts +++ b/src/API/getSkyblockAuctionsByPlayer.ts @@ -1,7 +1,6 @@ import Auction from '../structures/SkyBlock/Auctions/Auction'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getSkyblockActionsByPlayer extends Endpoint { @@ -12,7 +11,7 @@ export default class getSkyblockActionsByPlayer extends Endpoint { } async execute(query: string, includeItemBytes: boolean): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/skyblock/auction?player=${query}`); if (res.raw) return res; diff --git a/src/API/getSkyblockBingoByPlayer.ts b/src/API/getSkyblockBingoByPlayer.ts index 421d4434..24375c64 100644 --- a/src/API/getSkyblockBingoByPlayer.ts +++ b/src/API/getSkyblockBingoByPlayer.ts @@ -1,7 +1,6 @@ import PlayerBingo from '../structures/SkyBlock/PlayerBingo'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getBingoByPlayer extends Endpoint { @@ -12,7 +11,7 @@ export default class getBingoByPlayer extends Endpoint { } async execute(query: string): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/skyblock/uuid?player=${query}`); if (res.raw) return res; diff --git a/src/API/getSkyblockMember.ts b/src/API/getSkyblockMember.ts index efa813b0..c911ac6b 100644 --- a/src/API/getSkyblockMember.ts +++ b/src/API/getSkyblockMember.ts @@ -1,7 +1,6 @@ import SkyblockMember from '../structures/SkyBlock/SkyblockMember'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getSkyblockMember extends Endpoint { @@ -12,11 +11,11 @@ export default class getSkyblockMember extends Endpoint { } async execute(query: string): Promise> { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/skyblock/profiles?uuid=${query}`); if (res.raw) return res; - if (!res.profiles || !res.profiles.length) throw new Error(Errors.NO_SKYBLOCK_PROFILES); + if (!res.profiles || !res.profiles.length) throw new Error(this.client.errors.NO_SKYBLOCK_PROFILES); const memberByProfileName = new Map(); for (const profile of res.profiles) { memberByProfileName.set( diff --git a/src/API/getSkyblockMuseum.ts b/src/API/getSkyblockMuseum.ts index b2633521..148f0056 100644 --- a/src/API/getSkyblockMuseum.ts +++ b/src/API/getSkyblockMuseum.ts @@ -1,7 +1,6 @@ import SkyblockMuseum from '../structures/SkyBlock/SkyblockMuseum'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getSkyblockMuseum extends Endpoint { @@ -12,7 +11,7 @@ export default class getSkyblockMuseum extends Endpoint { } async execute(query: string, profileId: string): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/skyblock/museum?uuid=${query}&profile=${profileId}`); if (res.raw) return res; diff --git a/src/API/getSkyblockProfiles.ts b/src/API/getSkyblockProfiles.ts index d524ff11..b9eee05b 100644 --- a/src/API/getSkyblockProfiles.ts +++ b/src/API/getSkyblockProfiles.ts @@ -1,7 +1,6 @@ import SkyblockProfile from '../structures/SkyBlock/SkyblockProfile'; import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; -import Errors from '../Errors'; import Client from '../Client'; export default class getSkyblockProfiles extends Endpoint { readonly client: Client; @@ -11,11 +10,11 @@ export default class getSkyblockProfiles extends Endpoint { } async execute(query: string): Promise { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + if (!query) throw new Error(this.client.errors.NO_NICKNAME_UUID); query = await toUuid(query); const res = await this.client.requests.request(`/skyblock/profiles?uuid=${query}`); if (res.raw) return res; - if (!res.profiles || !res.profiles.length) throw new Error(Errors.NO_SKYBLOCK_PROFILES); + if (!res.profiles || !res.profiles.length) throw new Error(this.client.errors.NO_SKYBLOCK_PROFILES); const profiles = []; for (let i = 0; i < res.profiles.length; i++) { diff --git a/src/Client.ts b/src/Client.ts index 434ab368..f6309106 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -13,6 +13,7 @@ class Client { declare requests: Requests; declare cacheHandler: CacheHandler; declare updater: Updater; + declare errors: Errors; declare options: ClientOptions; @@ -22,7 +23,8 @@ class Client { this.options = this.parasOptions(options); this.requests = new Requests(this); this.cacheHandler = new CacheHandler(this); - this.updater = new Updater(); + this.updater = new Updater(this); + this.errors = new Errors(); for (const func in API) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -35,7 +37,7 @@ class Client { if (clients.find((x) => x.key === key)) { // eslint-disable-next-line no-console - console.warn(Errors.MULTIPLE_INSTANCES); + console.warn(this.errors.MULTIPLE_INSTANCES); const found = clients.find((x) => x.key === key); if (found) return found; } diff --git a/src/Errors.ts b/src/Errors.ts index fbe9cf2d..a07c6ef2 100644 --- a/src/Errors.ts +++ b/src/Errors.ts @@ -1,66 +1,74 @@ /* eslint-disable max-len */ -export default { - INVALID_API_KEY: '[Hypixel-API-Reborn] Invalid API Key! For help join our Discord Server https://discord.gg/NSEBNMM', - NO_API_KEY: '[Hypixel-API-Reborn] No API Key specified! For help join our Discord Server https://discord.gg/NSEBNMM', - ERROR_CODE_CAUSE: - '[Hypixel-API-Reborn] Code: {code} - {cause}! For help join our Discord Server https://discord.gg/NSEBNMM', - ERROR_STATUSTEXT: '[Hypixel-API-Reborn] {statustext}! For help join our Discord Server https://discord.gg/NSEBNMM', - KEY_MUST_BE_A_STRING: - '[Hypixel-API-Reborn] Specified API Key must be a string! For help join our Discord Server https://discord.gg/NSEBNMM', - OPTIONS_MUST_BE_AN_OBJECT: - '[Hypixel-API-Reborn] Options must be an object! For help join our Discord Server https://discord.gg/NSEBNMM', - CACHE_TIME_MUST_BE_A_NUMBER: - '[Hypixel-API-Reborn] Cache Time must be a number! For help join our Discord Server https://discord.gg/NSEBNMM', - CACHE_LIMIT_MUST_BE_A_NUMBER: - '[Hypixel-API-Reborn] Cache Limit must be a number! For help join our Discord Server https://discord.gg/NSEBNMM', - CACHE_FILTER_INVALID: - '[Hypixel-API-Reborn] Cache Filter must be a function returning a boolean, an object, an array, or a string!', - NO_NICKNAME_UUID: '[Hypixel-API-Reborn] No nickname or uuid specified.', - NO_UUID: '[Hypixel-API-Reborn] No uuid specified.', - UUID_NICKNAME_MUST_BE_A_STRING: '[Hypixel-API-Reborn] Nickname or uuid must be a string.', - MALFORMED_UUID: '[Hypixel-API-Reborn] Malformed UUID!', - PLAYER_DOES_NOT_EXIST: '[Hypixel-API-Reborn] Player does not exist.', - PLAYER_HAS_NEVER_LOGGED: '[Hypixel-API-Reborn] Player has never logged into Hypixel.', - PLAYER_IS_INACTIVE: - "[Hypixel-API-Reborn] No records of recent games because player hasn't been online for more than 3 days or is lacking data to determine the cause of an empty response", - PLAYER_DISABLED_ENDPOINT: '[Hypixel-API-Reborn] Player has disabled this endpoint.', - NO_GUILD_QUERY: '[Hypixel-API-Reborn] No guild search query specified.', - INVALID_GUILD_ID: '[Hypixel-API-Reborn] Specified Guild ID is invalid.', - INVALID_GUILD_SEARCH_PARAMETER: "[Hypixel-API-Reborn] getGuild() searchParameter must be 'id', 'guild' or 'player'.", - SOMETHING_WENT_WRONG: '[Hypixel-API-Reborn] Something went wrong. {cause}', - GUILD_DOES_NOT_EXIST: '[Hypixel-API-Reborn] Guild does not exist.', - PAGE_INDEX_ERROR: - '[Hypixel-API-Reborn] Invalid page index. Must be an integer, an array of 2 integers, or a keyword. For help join our Discord Server https://discord.gg/NSEBNMM', - INVALID_OPTION_VALUE: - '[Hypixel-API-Reborn] Invalid option value! For help join our Discord Server https://discord.gg/NSEBNMM', - INVALID_RESPONSE_BODY: - '[Hypixel-API-Reborn] An error occurred while converting to JSON. Perhaps this is due to an update or maintenance. For help join our Discord Server https://discord.gg/NSEBNMM', - INVALID_RATE_LIMIT_OPTION: - "[Hypixel-API-Reborn] Rate Limit provided in Client options must be 'HARD', 'AUTO', or 'NONE'. For help join our Discord Server https://discord.gg/NSEBNMM", - INVALID_KEY_LIMIT_OPTION: - '[Hypixel-API-Reborn] Key Limit provided in Client options must be an integer representing the amount of requests possible in one minute with your key.', - INVALID_HEADER_SYNC_OPTION: '[Hypixel-API-Reborn] Invalid Value for maxSyncHeaders : must be a boolean', - INVALID_BURST_OPTION: '[Hypixel-API-Reborn] maxBurstRequests provided in Client options must be a number', - NODE_VERSION_ERR: - "[Hypixel-API-Reborn] You are using a version of Nodejs that doesn't support certain features we use. Please upgrade to version 14 or above.", - UPDATER_REQUEST_NOT_OK: '[Hypixel-API-Reborn] Something went wrong while checking for updates.', - CONNECTION_ERROR: '[Hypixel-API-Reborn] Failed to connect.', - RATE_LIMIT_INIT_ERROR: - '[Hypixel-API-Reborn] An error happened whilst initializing rate limit. We strongly recommend restarting the code as this can lead to desynchronization.', - MULTIPLE_INSTANCES: - '[Hypixel-API-Reborn] Multiple instances of hypixel-api-reborn are found so we merged them for you. Please refrain from spawning multiple instances in the future. For more information, join our Discord Server https://discord.gg/NSEBNMM.', - INVALID_HEADERS: - '[Hypixel-API-Reborn] Invalid Headers are provided in ClientOptions. For help join our Discord Server https://discord.gg/NSEBNMM', - INVALID_CACHE_HANDLER: - '[Hypixel-API-Reborn] An invalid cache handler is provideed. For help join our Discord Server https://discord.gg/NSEBNMM', - UNEXPECTED_ERROR: - "[Hypixel-API-Reborn] The data provided to hypixel API is malformed and thus not recognized by hypixel, but this shouldn't be your fault. Please report this error in our Discord Server https://discord.gg/NSEBNMM or GitHub. ", - RATE_LIMIT_EXCEEDED: - "[Hypixel-API-Reborn] The rate limitations on your API Key has been exceeded. There might be an outage (Check Hypixel's status page), or you simply did too many requests in a short time. Hint: Enable rate limit options! They can help you avoid this error! For help join our Discord Server https://discord.gg/NSEBNMM", - NO_SKYBLOCK_PROFILES: '[Hypixel-API-Reborn] The player has no skyblock profiles.', - INVALID_SILENT_OPTION: '[Hypixel-API-Reborn] Invalid Value for silent : must be a boolean', - INVALID_UPDATE_OPTION: '[Hypixel-API-Reborn] Invalid Value for update : must be a boolean', - INVALID_THIRD_PARTY_API_OPTION: '[Hypixel-API-Reborn] Invalid Third Party API option : must be a boolean or string', - BAD_AUCTION_FILTER: - '[Hypixel-API-Reborn] Unexpected filter for Client#getSkyblockAuction. Expected one of "PLAYER", "AUCTION", "PROFILE", but got something else.' -}; + +class Errors { + INVALID_API_KEY: string = + '[Hypixel-API-Reborn] Invalid API Key! For help join our Discord Server https://discord.gg/NSEBNMM'; + NO_API_KEY: string = + '[Hypixel-API-Reborn] No API Key specified! For help join our Discord Server https://discord.gg/NSEBNMM'; + ERROR_CODE_CAUSE: string = + '[Hypixel-API-Reborn] Code: {code} - {cause}! For help join our Discord Server https://discord.gg/NSEBNMM'; + ERROR_STATUSTEXT: string = + '[Hypixel-API-Reborn] {statustext}! For help join our Discord Server https://discord.gg/NSEBNMM'; + KEY_MUST_BE_A_STRING: string = + '[Hypixel-API-Reborn] Specified API Key must be a string! For help join our Discord Server https://discord.gg/NSEBNMM'; + OPTIONS_MUST_BE_AN_OBJECT: string = + '[Hypixel-API-Reborn] Options must be an object! For help join our Discord Server https://discord.gg/NSEBNMM'; + CACHE_TIME_MUST_BE_A_NUMBER: string = + '[Hypixel-API-Reborn] Cache Time must be a number! For help join our Discord Server https://discord.gg/NSEBNMM'; + CACHE_LIMIT_MUST_BE_A_NUMBER: string = + '[Hypixel-API-Reborn] Cache Limit must be a number! For help join our Discord Server https://discord.gg/NSEBNMM'; + CACHE_FILTER_INVALID: string = + '[Hypixel-API-Reborn] Cache Filter must be a function returning a boolean, an object, an array, or a string!'; + NO_NICKNAME_UUID: string = '[Hypixel-API-Reborn] No nickname or uuid specified.'; + NO_UUID: string = '[Hypixel-API-Reborn] No uuid specified.'; + UUID_NICKNAME_MUST_BE_A_STRING: string = '[Hypixel-API-Reborn] Nickname or uuid must be a string.'; + MALFORMED_UUID: string = '[Hypixel-API-Reborn] Malformed UUID!'; + PLAYER_DOES_NOT_EXIST: string = '[Hypixel-API-Reborn] Player does not exist.'; + PLAYER_HAS_NEVER_LOGGED: string = '[Hypixel-API-Reborn] Player has never logged into Hypixel.'; + PLAYER_IS_INACTIVE: string = + "[Hypixel-API-Reborn] No records of recent games because player hasn't been online for more than 3 days or is lacking data to determine the cause of an empty response"; + PLAYER_DISABLED_ENDPOINT: string = '[Hypixel-API-Reborn] Player has disabled this endpoint.'; + NO_GUILD_QUERY: string = '[Hypixel-API-Reborn] No guild search query specified.'; + INVALID_GUILD_ID: string = '[Hypixel-API-Reborn] Specified Guild ID is invalid.'; + INVALID_GUILD_SEARCH_PARAMETER: string = + "[Hypixel-API-Reborn] getGuild() searchParameter must be 'id'; 'guild' or 'player'."; + SOMETHING_WENT_WRONG: string = '[Hypixel-API-Reborn] Something went wrong. {cause}'; + GUILD_DOES_NOT_EXIST: string = '[Hypixel-API-Reborn] Guild does not exist.'; + PAGE_INDEX_ERROR: string = + '[Hypixel-API-Reborn] Invalid page index. Must be an integer, an array of 2 integers, or a keyword. For help join our Discord Server https://discord.gg/NSEBNMM'; + INVALID_OPTION_VALUE: string = + '[Hypixel-API-Reborn] Invalid option value! For help join our Discord Server https://discord.gg/NSEBNMM'; + INVALID_RESPONSE_BODY: string = + '[Hypixel-API-Reborn] An error occurred while converting to JSON. Perhaps this is due to an update or maintenance. For help join our Discord Server https://discord.gg/NSEBNMM'; + INVALID_RATE_LIMIT_OPTION: string = + "[Hypixel-API-Reborn] Rate Limit provided in Client options must be 'HARD'; 'AUTO'; or 'NONE'. For help join our Discord Server https://discord.gg/NSEBNMM"; + INVALID_KEY_LIMIT_OPTION: string = + '[Hypixel-API-Reborn] Key Limit provided in Client options must be an integer representing the amount of requests possible in one minute with your key.'; + INVALID_HEADER_SYNC_OPTION: string = '[Hypixel-API-Reborn] Invalid Value for maxSyncHeaders : must be a boolean'; + INVALID_BURST_OPTION: string = '[Hypixel-API-Reborn] maxBurstRequests provided in Client options must be a number'; + NODE_VERSION_ERR: string = + "[Hypixel-API-Reborn] You are using a version of Nodejs that doesn't support certain features we use. Please upgrade to version 14 or above."; + UPDATER_REQUEST_NOT_OK: string = '[Hypixel-API-Reborn] Something went wrong while checking for updates.'; + CONNECTION_ERROR: string = '[Hypixel-API-Reborn] Failed to connect.'; + RATE_LIMIT_INIT_ERROR: string = + '[Hypixel-API-Reborn] An error happened whilst initializing rate limit. We strongly recommend restarting the code as this can lead to desynchronization.'; + MULTIPLE_INSTANCES: string = + '[Hypixel-API-Reborn] Multiple instances of hypixel-api-reborn are found so we merged them for you. Please refrain from spawning multiple instances in the future. For more information, join our Discord Server https://discord.gg/NSEBNMM.'; + INVALID_HEADERS: string = + '[Hypixel-API-Reborn] Invalid Headers are provided in ClientOptions. For help join our Discord Server https://discord.gg/NSEBNMM'; + INVALID_CACHE_HANDLER: string = + '[Hypixel-API-Reborn] An invalid cache handler is provideed. For help join our Discord Server https://discord.gg/NSEBNMM'; + UNEXPECTED_ERROR: string = + "[Hypixel-API-Reborn] The data provided to hypixel API is malformed and thus not recognized by hypixel, but this shouldn't be your fault. Please report this error in our Discord Server https://discord.gg/NSEBNMM or GitHub. "; + RATE_LIMIT_EXCEEDED: string = + "[Hypixel-API-Reborn] The rate limitations on your API Key has been exceeded. There might be an outage (Check Hypixel's status page), or you simply did too many requests in a short time. Hint: Enable rate limit options! They can help you avoid this error! For help join our Discord Server https://discord.gg/NSEBNMM"; + NO_SKYBLOCK_PROFILES: string = '[Hypixel-API-Reborn] The player has no skyblock profiles.'; + INVALID_SILENT_OPTION: string = '[Hypixel-API-Reborn] Invalid Value for silent : must be a boolean'; + INVALID_UPDATE_OPTION: string = '[Hypixel-API-Reborn] Invalid Value for update : must be a boolean'; + INVALID_THIRD_PARTY_API_OPTION: string = + '[Hypixel-API-Reborn] Invalid Third Party API option : must be a boolean or string'; + BAD_AUCTION_FILTER: string = + '[Hypixel-API-Reborn] Unexpected filter for Client#getSkyblockAuction. Expected one of "PLAYER", "AUCTION", "PROFILE", but got something else.'; +} + +export default Errors; diff --git a/src/Private/Requests.ts b/src/Private/Requests.ts index c38a6327..f60cfd68 100644 --- a/src/Private/Requests.ts +++ b/src/Private/Requests.ts @@ -1,6 +1,5 @@ const BASE_URL = 'https://api.hypixel.net/v2'; import Client from '../Client'; -import Errors from '../Errors'; import axios from 'axios'; export interface RequestOptions { @@ -25,21 +24,26 @@ class Requests { const res = await axios.get(BASE_URL + endpoint, { headers: { 'API-Key': this.client.key } }); if (500 <= res.status && 528 > res.status) { throw new Error( - Errors.ERROR_STATUSTEXT.replace(/{statustext}/, `Server Error : ${res.status} ${res.statusText}`) + this.client.errors.ERROR_STATUSTEXT.replace(/{statustext}/, `Server Error : ${res.status} ${res.statusText}`) ); } const parsedRes = await res.data; if (400 === res.status) { throw new Error( - Errors.ERROR_CODE_CAUSE.replace(/{code}/, '400 Bad Request').replace(/{cause}/, parsedRes.cause || '') + this.client.errors.ERROR_CODE_CAUSE.replace(/{code}/, '400 Bad Request').replace( + /{cause}/, + parsedRes.cause || '' + ) ); } - if (403 === res.status) throw new Error(Errors.INVALID_API_KEY); - if (422 === res.status) throw new Error(Errors.UNEXPECTED_ERROR); - if (429 === res.status) throw new Error(Errors.RATE_LIMIT_EXCEEDED); - if (200 !== res.status) throw new Error(Errors.ERROR_STATUSTEXT.replace(/{statustext}/, res.statusText)); + if (403 === res.status) throw new Error(this.client.errors.INVALID_API_KEY); + if (422 === res.status) throw new Error(this.client.errors.UNEXPECTED_ERROR); + if (429 === res.status) throw new Error(this.client.errors.RATE_LIMIT_EXCEEDED); + if (200 !== res.status) { + throw new Error(this.client.errors.ERROR_STATUSTEXT.replace(/{statustext}/, res.statusText)); + } if (!parsedRes.success && !endpoint.startsWith('/housing')) { - throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.statusText)); + throw new Error(this.client.errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.statusText)); } // eslint-disable-next-line no-underscore-dangle diff --git a/src/Private/Updater.ts b/src/Private/Updater.ts index 682e26b1..1fc60d3d 100644 --- a/src/Private/Updater.ts +++ b/src/Private/Updater.ts @@ -1,12 +1,14 @@ /* eslint-disable no-console */ import { version } from '../../package.json'; -import Errors from '../Errors'; +import Client from '../Client'; import axios from 'axios'; class Updater { + readonly client: Client; currentVersion: string; latestVersion: string; - constructor() { + constructor(client: Client) { + this.client = client; this.currentVersion = version; this.latestVersion = '0.0.0'; } @@ -26,7 +28,7 @@ class Updater { async getLatestVersion(): Promise { const request = await axios.get('https://registry.npmjs.org/hypixel-api-reborn'); if (200 !== request.status) { - console.log(Errors.UPDATER_REQUEST_NOT_OK); + console.log(this.client.errors.UPDATER_REQUEST_NOT_OK); return; } const metadata = await request.data; diff --git a/src/utils/toUuid.ts b/src/utils/toUuid.ts index eced4780..d3884ba1 100644 --- a/src/utils/toUuid.ts +++ b/src/utils/toUuid.ts @@ -2,22 +2,24 @@ import fetch from '../Private/uuidCache'; import Errors from '../Errors'; import isUUID from './isUUID'; +const errors = new Errors(); + export default async function (input: string, cacheTime: number = 600, useThirdPartyAPI: string = ''): Promise { - if (!input) throw new Error(Errors.NO_NICKNAME_UUID); - if ('string' !== typeof input) throw new Error(Errors.UUID_NICKNAME_MUST_BE_A_STRING); + if (!input) throw new Error(errors.NO_NICKNAME_UUID); + if ('string' !== typeof input) throw new Error(errors.UUID_NICKNAME_MUST_BE_A_STRING); if (isUUID(input)) return input.replace(/-/g, ''); try { const customUrl = useThirdPartyAPI ? 'https://api.minetools.eu/uuid/' : useThirdPartyAPI; const url = useThirdPartyAPI ? `${customUrl}${input}` : `https://mowojang.matdoes.dev/${input}`; const res = await fetch(url, input, cacheTime); if (404 === res.status) { - return Promise.reject(new Error(Errors.PLAYER_DOES_NOT_EXIST)); + return Promise.reject(new Error(errors.PLAYER_DOES_NOT_EXIST)); } else if (200 !== res.status) { throw new Error('Unknown Error whilst retrieving player information'); } - if (!res.id) throw new Error(Errors.PLAYER_DOES_NOT_EXIST); + if (!res.id) throw new Error(errors.PLAYER_DOES_NOT_EXIST); return res.id; } catch { - throw new Error(Errors.PLAYER_DOES_NOT_EXIST); + throw new Error(errors.PLAYER_DOES_NOT_EXIST); } }