diff --git a/API/getSkyblockAuctions.ts b/API/getSkyblockAuctions.ts new file mode 100644 index 0000000..e115a5b --- /dev/null +++ b/API/getSkyblockAuctions.ts @@ -0,0 +1,85 @@ +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/getAPIStatus.ts b/src/API/getAPIStatus.ts deleted file mode 100644 index 574d605..0000000 --- a/src/API/getAPIStatus.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Status from '../structures/APIStatus.js'; -import Rss from 'rss-parser'; -const Parser = new Rss(); -export default async function (options: any) { - const parsed = await Parser.parseURL('https://status.hypixel.net/history.rss'); - if (options && options.raw) return parsed; - return new Status(parsed); -} diff --git a/src/API/getAchievements.ts b/src/API/getAchievements.ts index 9ee6d25..6e6d42b 100644 --- a/src/API/getAchievements.ts +++ b/src/API/getAchievements.ts @@ -1,7 +1,18 @@ import Achievements from '../structures/Static/Achievements'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/resources/achievements'); - if (res.raw) return res; - return new Achievements(res); +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getAchievements extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getAchievements'; + } + + async execute() { + const res = await this.client.requests.request('/resources/achievements'); + if (res.raw) return res; + return new Achievements(res); + } } diff --git a/src/API/getActiveHouses.ts b/src/API/getActiveHouses.ts new file mode 100644 index 0000000..ba67d7a --- /dev/null +++ b/src/API/getActiveHouses.ts @@ -0,0 +1,18 @@ +import Endpoint from '../Private/Endpoint'; +import House from '../structures/House'; +import Client from '../Client'; +export default class getActiveHouses extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getActiveHouses'; + } + + async execute() { + const res = await this.client.requests.request('/housing/active'); + if (res.raw) return res; + return res.length ? res.map((b: any) => new House(b)) : []; + } +} diff --git a/src/API/getBoosters.ts b/src/API/getBoosters.ts index 0fd6c9f..df119b1 100644 --- a/src/API/getBoosters.ts +++ b/src/API/getBoosters.ts @@ -1,7 +1,18 @@ import Booster from '../structures/Boosters/Booster'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/boosters'); - if (res.raw) return res; - return res.boosters.length ? res.boosters.map((b: any) => new Booster(b)).reverse() : []; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getBoosters extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getBoosters'; + } + + async execute() { + const res = await this.client.requests.request('/boosters'); + if (res.raw) return res; + return res.boosters.length ? res.boosters.map((b: any) => new Booster(b)).reverse() : []; + } } diff --git a/src/API/getChallenges.ts b/src/API/getChallenges.ts index e300e3a..e12b288 100644 --- a/src/API/getChallenges.ts +++ b/src/API/getChallenges.ts @@ -1,7 +1,18 @@ import Challenges from '../structures/Static/Challenges'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/resources/challenges'); - if (res.raw) return res; - return new Challenges(res); +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getChallenges extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getChallenges'; + } + + async execute() { + const res = await this.client.requests.request('/resources/challenges'); + if (res.raw) return res; + return new Challenges(res); + } } diff --git a/src/API/getGameCounts.ts b/src/API/getGameCounts.ts index f0a3233..e7c7a50 100644 --- a/src/API/getGameCounts.ts +++ b/src/API/getGameCounts.ts @@ -1,7 +1,18 @@ import GameCounts from '../structures/GameCounts'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/counts'); - if (res.raw) return res; - return new GameCounts(res); +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getGameCounts extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getGameCounts'; + } + + async execute() { + const res = await this.client.requests.request('/counts'); + if (res.raw) return res; + return new GameCounts(res); + } } diff --git a/src/API/getGuild.ts b/src/API/getGuild.ts index ddc09d4..aa5a0c9 100644 --- a/src/API/getGuild.ts +++ b/src/API/getGuild.ts @@ -1,20 +1,30 @@ -import { GuildSearchParameter } from '../typings'; 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'; -export default async function (this: any, searchParameter: GuildSearchParameter, query: string) { - if (!query) throw new Error(Errors.NO_GUILD_QUERY); - if ('id' === searchParameter && !isGuildID(query)) throw new Error(Errors.INVALID_GUILD_ID); - const isPlayerQuery = 'player' === searchParameter; - if (isPlayerQuery) query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - if (!['id', 'name', 'player'].includes(searchParameter)) throw new Error(Errors.INVALID_GUILD_SEARCH_PARAMETER); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/guild?${searchParameter}=${encodeURI(query)}`); - if (res.raw) return res; - if (!res.guild && 'player' !== searchParameter) { - throw new Error(Errors.GUILD_DOES_NOT_EXIST); +import Client from '../Client'; +export default class getGuild extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getGuild'; } - return res.guild ? new Guild(res.guild, isPlayerQuery ? query : undefined) : null; + async execute(searchParameter: 'id' | 'name' | 'player', query: string) { + if (!query) throw new Error(Errors.NO_GUILD_QUERY); + if ('id' === searchParameter && !isGuildID(query)) throw new Error(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); + 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); + } + + return res.guild ? new Guild(res.guild, isPlayerQuery ? query : undefined) : null; + } } diff --git a/src/API/getGuildAchievements.ts b/src/API/getGuildAchievements.ts index dc8f0c0..7e81c80 100644 --- a/src/API/getGuildAchievements.ts +++ b/src/API/getGuildAchievements.ts @@ -1,7 +1,18 @@ import GuildAchievements from '../structures/Static/GuildAchievements'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/resources/guilds/achievements'); - if (res.raw) return res; - return new GuildAchievements(res); +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getGuildAchievements extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getGuildAchievements'; + } + + async execute() { + const res = await this.client.requests.request('/resources/guilds/achievements'); + if (res.raw) return res; + return new GuildAchievements(res); + } } diff --git a/src/API/getHouse.ts b/src/API/getHouse.ts new file mode 100644 index 0000000..ee3c8a2 --- /dev/null +++ b/src/API/getHouse.ts @@ -0,0 +1,20 @@ +import Endpoint from '../Private/Endpoint'; +import House from '../structures/House'; +import Errors from '../Errors'; +import Client from '../Client'; +export default class getHouse extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getHouse'; + } + + async execute(query: string) { + if (!query) throw new Error(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 411de5e..b6fd3de 100644 --- a/src/API/getLeaderboards.ts +++ b/src/API/getLeaderboards.ts @@ -1,16 +1,27 @@ import Leaderboard from '../structures/Leaderboard'; import Constants from '../utils/Constants'; +import Endpoint from '../Private/Endpoint'; import Errors from '../Errors'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/leaderboards'); - if (res.raw) return res; - if (!res.leaderboards) throw new Error(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 - ? res.leaderboards[lbnames[name]].map((lb: any) => new Leaderboard(lb)) - : []; +import Client from '../Client'; +export default class getLeaderboards extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getLeaderboards'; + } + + async execute() { + 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.')); + const lbnames = Object.create(Constants.leaderboardNames); + for (const name in lbnames) { + lbnames[name] = res.leaderboards[lbnames[name]].length + ? res.leaderboards[lbnames[name]].map((lb: any) => new Leaderboard(lb)) + : []; + } + return lbnames; } - return lbnames; } diff --git a/src/API/getPlayer.ts b/src/API/getPlayer.ts index bf5405f..0fd708a 100644 --- a/src/API/getPlayer.ts +++ b/src/API/getPlayer.ts @@ -1,23 +1,23 @@ -import Errors from '../Errors'; -import toUuid from '../utils/toUuid'; -import getGuild from './getGuild'; -import getRecentGames from './getRecentGames'; +import Endpoint from '../Private/Endpoint'; import Player from '../structures/Player'; -export default async function (this: any, query: string, options = { guild: false, recentGames: false }) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/player?uuid=${query}`); - if (res.raw) return res; - if (query && !res.player) throw new Error(Errors.PLAYER_HAS_NEVER_LOGGED); - let guild = null; - let recentGames = null; - if (options.guild) { - guild = getGuild.call(this, 'player', query); +import toUuid from '../utils/toUuid'; +import Errors from '../Errors'; +import Client from '../Client'; +export default class getPlayer extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getPlayer'; } - if (options.recentGames) { - recentGames = getRecentGames.call(this, query); + + async execute(query: string) { + if (!query) throw new Error(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); + return new Player(res.player); } - [guild, recentGames] = await Promise.all([guild, recentGames]); - return new Player(res.player, { guild, recentGames }); } diff --git a/src/API/getPlayerHouses.ts b/src/API/getPlayerHouses.ts new file mode 100644 index 0000000..22fe9c4 --- /dev/null +++ b/src/API/getPlayerHouses.ts @@ -0,0 +1,22 @@ +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 { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getPlayerHouses'; + } + + async execute(query: string) { + if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + query = await toUuid(query); + const res = await this.client.requests.request(`/housing/houses?player=${query}`); + if (res.raw) return res; + return res.length ? res.map((h: any) => new House(h)) : []; + } +} diff --git a/src/API/getQuests.ts b/src/API/getQuests.ts index 1135abc..b8d836f 100644 --- a/src/API/getQuests.ts +++ b/src/API/getQuests.ts @@ -1,7 +1,18 @@ import Quests from '../structures/Static/Quests'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/resources/quests'); - if (res.raw) return res; - return new Quests(res); +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getQuests extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getQuests'; + } + + async execute() { + const res = await this.client.requests.request('/resources/quests'); + if (res.raw) return res; + return new Quests(res); + } } diff --git a/src/API/getRecentGames.ts b/src/API/getRecentGames.ts index 7f92d5e..0c6e529 100644 --- a/src/API/getRecentGames.ts +++ b/src/API/getRecentGames.ts @@ -1,14 +1,25 @@ import RecentGame from '../structures/RecentGame'; +import Endpoint from '../Private/Endpoint'; import toUuid from '../utils/toUuid'; import Errors from '../Errors'; -export default async function (this: any, query: string) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/recentgames?uuid=${query}`); - if (res.raw) return res; - if (0 === res.games.length) { - return []; +import Client from '../Client'; +export default class getRecentGames extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getRecentGames'; + } + + async execute(query: string) { + if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + query = await toUuid(query); + const res = await this.client.requests.request(`/recentgames?uuid=${query}`); + if (res.raw) return res; + if (0 === res.games.length) { + return []; + } + return res.games.map((x: any) => new RecentGame(x)); } - return res.games.map((x: any) => new RecentGame(x)); } diff --git a/src/API/getSkyblockAuction.ts b/src/API/getSkyblockAuction.ts new file mode 100644 index 0000000..52a6bcb --- /dev/null +++ b/src/API/getSkyblockAuction.ts @@ -0,0 +1,32 @@ +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 { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockAction'; + } + + async execute(query: string, type: 'PROFILE' | 'PLAYER' | 'AUCTION', includeItemBytes: boolean = false) { + if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + let filter; + if ('PROFILE' === type) { + filter = 'profile'; + } else if ('PLAYER' === type) { + query = await toUuid(query); + filter = 'player'; + } else if ('AUCTION' === type) { + filter = 'uuid'; + } else { + throw new Error(Errors.BAD_AUCTION_FILTER); + } + const res = await this.client.requests.request(`/skyblock/auction?${filter}=${query}`); + if (res.raw) return res; + return res.auctions.length ? res.auctions.map((a: any) => new Auction(a, includeItemBytes)) : []; + } +} diff --git a/src/API/getSkyblockAuctionsByPlayer.ts b/src/API/getSkyblockAuctionsByPlayer.ts new file mode 100644 index 0000000..3075032 --- /dev/null +++ b/src/API/getSkyblockAuctionsByPlayer.ts @@ -0,0 +1,22 @@ +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 { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockActionsByPlayer'; + } + + async execute(query: string, includeItemBytes: boolean) { + if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + query = await toUuid(query); + const res = await this.client.requests.request(`/skyblock/auction?player=${query}`); + if (res.raw) return res; + return res.auctions.length ? res.auctions.map((a: any) => new Auction(a, includeItemBytes)) : []; + } +} diff --git a/src/API/getSkyblockBazaar.ts b/src/API/getSkyblockBazaar.ts new file mode 100644 index 0000000..e2de073 --- /dev/null +++ b/src/API/getSkyblockBazaar.ts @@ -0,0 +1,19 @@ +import Product from '../structures/SkyBlock/Bazzar/Product'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getSkyblockBazaar extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockBazaar'; + } + + async execute() { + const res = await this.client.requests.request('/skyblock/bazaar'); + if (res.raw) return res; + const productsKeys = Object.keys(res.products); + return productsKeys.map((x) => new Product(res.products[x])); + } +} diff --git a/src/API/getSkyblockBingo.ts b/src/API/getSkyblockBingo.ts new file mode 100644 index 0000000..5cfcf2f --- /dev/null +++ b/src/API/getSkyblockBingo.ts @@ -0,0 +1,18 @@ +import BingoData from '../structures/SkyBlock/Static/BingoData'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getSkyblockBingo extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockBingo'; + } + + async execute() { + const res = await this.client.requests.request('/resources/skyblock/bingo'); + if (res.raw) return res; + return new BingoData(res); + } +} diff --git a/src/API/getSkyblockBingoByPlayer.ts b/src/API/getSkyblockBingoByPlayer.ts new file mode 100644 index 0000000..cec180d --- /dev/null +++ b/src/API/getSkyblockBingoByPlayer.ts @@ -0,0 +1,22 @@ +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 { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getBingoByPlayer'; + } + + async execute(query: string) { + if (!query) throw new Error(Errors.NO_NICKNAME_UUID); + query = await toUuid(query); + const res = await this.client.requests.request(`/skyblock/uuid?player=${query}`); + if (res.raw) return res; + return new PlayerBingo(res); + } +} diff --git a/src/API/getSkyblockEndedAuctions.ts b/src/API/getSkyblockEndedAuctions.ts new file mode 100644 index 0000000..263d734 --- /dev/null +++ b/src/API/getSkyblockEndedAuctions.ts @@ -0,0 +1,22 @@ +import PartialAuction from '../structures/SkyBlock/Auctions/PartialAuction'; +import AuctionInfo from '../structures/SkyBlock/Auctions/AuctionInfo'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getSkyblockEndedAuctions extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockEndedAuctions'; + } + + async execute(includeItemBytes: any): Promise { + const res = await this.client.requests.request('/skyblock/auctions_ended'); + if (res.raw) return res; + return { + info: new AuctionInfo({ ...res, totalAuctions: res.auctions.length, totalPages: 1 }), + auctions: res.auctions.length ? res.auctions.map((a: any) => new PartialAuction(a, includeItemBytes)) : [] + }; + } +} diff --git a/src/API/getSkyblockFireSales.ts b/src/API/getSkyblockFireSales.ts new file mode 100644 index 0000000..f553dd3 --- /dev/null +++ b/src/API/getSkyblockFireSales.ts @@ -0,0 +1,18 @@ +import FireSale from '../structures/SkyBlock/Static/FireSale'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getSkyblockFireSales extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockFireSales'; + } + + async execute() { + const res = await this.client.requests.request('/skyblock/firesales'); + if (res.raw) return res; + return res.sales.length ? res.sales.map((a: any) => new FireSale(a)) : []; + } +} diff --git a/src/API/getSkyblockGarden.ts b/src/API/getSkyblockGarden.ts new file mode 100644 index 0000000..9a16ce1 --- /dev/null +++ b/src/API/getSkyblockGarden.ts @@ -0,0 +1,18 @@ +import SkyblockGarden from '../structures/SkyBlock/SkyblockGarden'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getSkyblockGarden extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockGarden'; + } + + async execute(profileId: string) { + const res = await this.client.requests.request(`/skyblock/garden?profile=${profileId}`); + if (res.raw) return res; + return new SkyblockGarden(res); + } +} diff --git a/src/API/getSkyblockGovernment.ts b/src/API/getSkyblockGovernment.ts new file mode 100644 index 0000000..63bae09 --- /dev/null +++ b/src/API/getSkyblockGovernment.ts @@ -0,0 +1,18 @@ +import GovernmentData from '../structures/SkyBlock/Static/Government.js'; +import Endpoint from '../Private/Endpoint.js'; +import Client from '../Client.js'; +export default class getSkyblockGovernment extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockGovernment'; + } + + async execute() { + const res = await this.client.requests.request('/resources/skyblock/election'); + if (res.raw) return res; + return new GovernmentData(res); + } +} diff --git a/src/API/getSkyblockMember.ts b/src/API/getSkyblockMember.ts new file mode 100644 index 0000000..02db934 --- /dev/null +++ b/src/API/getSkyblockMember.ts @@ -0,0 +1,40 @@ +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 { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockMember'; + } + + async execute(query: string) { + if (!query) throw new Error(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); + const memberByProfileName = new Map(); + for (const profile of res.profiles) { + memberByProfileName.set( + profile.cute_name, + new SkyblockMember({ + uuid: query, + profileId: profile.profile_id, + profileName: profile.cute_name, + gameMode: profile.game_mode || null, + m: profile.members[query], + banking: profile.banking, + communityUpgrades: profile.community_upgrades, + selected: profile.selected + }) + ); + } + return memberByProfileName; + } +} diff --git a/src/API/getSkyblockMuseum.ts b/src/API/getSkyblockMuseum.ts new file mode 100644 index 0000000..93d968b --- /dev/null +++ b/src/API/getSkyblockMuseum.ts @@ -0,0 +1,26 @@ +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 { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockMuseum'; + } + + async execute(query: string, profileId: string) { + if (!query) throw new Error(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; + return new SkyblockMuseum({ + uuid: query, + m: res, + profileId: profileId + }); + } +} diff --git a/src/API/getSkyblockNews.ts b/src/API/getSkyblockNews.ts new file mode 100644 index 0000000..3716de9 --- /dev/null +++ b/src/API/getSkyblockNews.ts @@ -0,0 +1,18 @@ +import SkyblockNews from '../structures/SkyBlock/News/SkyblockNews'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; +export default class getSkyblockNews extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockNews'; + } + + async execute() { + const res = await this.client.requests.request('/skyblock/news'); + if (res.raw) return res; + return res.items.map((i: any) => new SkyblockNews(i)); + } +} diff --git a/src/API/getSkyblockProfiles.ts b/src/API/getSkyblockProfiles.ts new file mode 100644 index 0000000..538b6c2 --- /dev/null +++ b/src/API/getSkyblockProfiles.ts @@ -0,0 +1,41 @@ +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; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getSkyblockProfiles'; + } + + async execute(query: string) { + if (!query) throw new Error(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); + + const profiles = []; + for (let i = 0; i < res.profiles.length; i++) { + profiles.push({ + uuid: query, + profileId: res.profiles[i].profile_id, + profileName: res.profiles[i].cute_name, + gameMode: res.profiles[i].game_mode || null, + m: res.profiles[i].members[query], + banking: res.profiles[i].banking, + communityUpgrades: res.profiles[i].community_upgrades, + museum: null, + garden: null, + selected: res.profiles[i].selected, + members: res.profiles[i].members + }); + } + + return profiles.map((p) => new SkyblockProfile(p)); + } +} diff --git a/src/API/getStatus.ts b/src/API/getStatus.ts index e64ca94..a187c1d 100644 --- a/src/API/getStatus.ts +++ b/src/API/getStatus.ts @@ -1,9 +1,20 @@ +import Endpoint from '../Private/Endpoint'; import Status from '../structures/Status'; import toUuid from '../utils/toUuid'; -export default async function (this: any, query: string) { - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/status?uuid=${query}`); - if (res.raw) return res; - return new Status(res.session); +import Client from '../Client'; +export default class getStatus extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getStatus'; + } + + async execute(query: string) { + query = await toUuid(query); + const res = await this.client.requests.request(`/status?uuid=${query}`); + if (res.raw) return res; + return new Status(res.session); + } } diff --git a/src/API/getWatchdogStats.ts b/src/API/getWatchdogStats.ts index df6579f..e83247b 100644 --- a/src/API/getWatchdogStats.ts +++ b/src/API/getWatchdogStats.ts @@ -1,8 +1,19 @@ import WatchdogStats from '../structures/Watchdog/Stats'; +import Endpoint from '../Private/Endpoint'; +import Client from '../Client'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/punishmentstats'); - if (res.raw) return res; - return new WatchdogStats(res); +export default class getWatchdogStatsEndpoint extends Endpoint { + readonly client: Client; + readonly name: string; + constructor(client: Client) { + super(client); + this.client = client; + this.name = 'getWatchdogStats'; + } + + async execute() { + const res = await this.client.requests.request('/punishmentstats'); + if (res.raw) return res; + return new WatchdogStats(res); + } } diff --git a/src/API/housing/getActiveHouses.ts b/src/API/housing/getActiveHouses.ts deleted file mode 100644 index ab8e348..0000000 --- a/src/API/housing/getActiveHouses.ts +++ /dev/null @@ -1,7 +0,0 @@ -import House from '../../structures/House'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/housing/active'); - if (res.raw) return res; - return res.length ? res.map((b: any) => new House(b)) : []; -} diff --git a/src/API/housing/getHouse.ts b/src/API/housing/getHouse.ts deleted file mode 100644 index 2b2a310..0000000 --- a/src/API/housing/getHouse.ts +++ /dev/null @@ -1,9 +0,0 @@ -import House from '../../structures/House'; -import Errors from '../../Errors'; -export default async function (this: any, query: string) { - if (!query) throw new Error(Errors.NO_UUID); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/housing/house?house=${query}`); - if (res.raw) return res; - return new House(res); -} diff --git a/src/API/housing/getPlayerHouses.ts b/src/API/housing/getPlayerHouses.ts deleted file mode 100644 index 7aa777e..0000000 --- a/src/API/housing/getPlayerHouses.ts +++ /dev/null @@ -1,11 +0,0 @@ -import House from '../../structures/House'; -import toUuid from '../../utils/toUuid'; -import Errors from '../../Errors'; -export default async function (this: any, query: string) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/housing/houses?player=${query}`); - if (res.raw) return res; - return res.length ? res.map((h: any) => new House(h)) : []; -} diff --git a/src/API/index.ts b/src/API/index.ts deleted file mode 100644 index 465b9df..0000000 --- a/src/API/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -import getAchievements from './getAchievements'; -import getAPIStatus from './getAPIStatus'; -import getBoosters from './getBoosters'; -import getChallenges from './getChallenges'; -import getGameCounts from './getGameCounts'; -import getGuild from './getGuild'; -import getGuildAchievements from './getGuildAchievements'; -import getLeaderboards from './getLeaderboards'; -import getPlayer from './getPlayer'; -import getQuests from './getQuests'; -import getRecentGames from './getRecentGames'; -import getStatus from './getStatus'; -import getWatchdogStats from './getWatchdogStats'; - -import getSkyblockAuction from './skyblock/getAuction'; -import getSkyblockAuctions from './skyblock/getAuctions'; -import getSkyblockAuctionsByPlayer from './skyblock/getAuctionsByPlayer'; -import getSkyblockBazaar from './skyblock/getBazaar'; -import getSkyblockBingo from './skyblock/getBingo'; -import getSkyblockBingoByPlayer from './skyblock/getBingoByPlayer'; -import getSkyblockEndedAuctions from './skyblock/getEndedAuctions'; -import getSkyblockFireSales from './skyblock/getFireSales'; -import getSkyblockGarden from './skyblock/getGarden'; -import getSkyblockGovernment from './skyblock/getGovernment'; -import getSkyblockMember from './skyblock/getMember'; -import getSkyblockMuseum from './skyblock/getMuseum'; -import getSkyblockNews from './skyblock/getNews'; -import getSkyblockProfiles from './skyblock/getProfiles'; - -import getActiveHouses from './housing/getActiveHouses'; -import getPlayerHouses from './housing/getPlayerHouses'; -import getHouse from './housing/getHouse'; - -export default { - getAchievements, - getAPIStatus, - getBoosters, - getChallenges, - getGameCounts, - getGuild, - getGuildAchievements, - getLeaderboards, - getPlayer, - getQuests, - getRecentGames, - getStatus, - getWatchdogStats, - - getSkyblockAuction, - getSkyblockAuctions, - getSkyblockAuctionsByPlayer, - getSkyblockBazaar, - getSkyblockBingo, - getSkyblockBingoByPlayer, - getSkyblockEndedAuctions, - getSkyblockFireSales, - getSkyblockGarden, - getSkyblockGovernment, - getSkyblockMember, - getSkyblockMuseum, - getSkyblockNews, - getSkyblockProfiles, - - getActiveHouses, - getPlayerHouses, - getHouse -}; diff --git a/src/API/skyblock/getAuction.ts b/src/API/skyblock/getAuction.ts deleted file mode 100644 index 2e34b5e..0000000 --- a/src/API/skyblock/getAuction.ts +++ /dev/null @@ -1,23 +0,0 @@ -import Auction from '../../structures/SkyBlock/Auctions/Auction'; -import { ActionFilterType } from '../../typings'; -import toUuid from '../../utils/toUuid'; -import Errors from '../../Errors'; - -export default async function (this: any, type: ActionFilterType, query: string, includeItemBytes = false) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - let filter; - if ('PROFILE' === type) { - filter = 'profile'; - } else if ('PLAYER' === type) { - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - filter = 'player'; - } else if ('AUCTION' === type) { - filter = 'uuid'; - } else { - throw new Error(Errors.BAD_AUCTION_FILTER); - } - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/skyblock/auction?${filter}=${query}`); - if (res.raw) return res; - return res.auctions.length ? res.auctions.map((a: any) => new Auction(a, includeItemBytes)) : []; -} diff --git a/src/API/skyblock/getAuctions.ts b/src/API/skyblock/getAuctions.ts deleted file mode 100644 index 91d7875..0000000 --- a/src/API/skyblock/getAuctions.ts +++ /dev/null @@ -1,71 +0,0 @@ -import AuctionInfo from '../../structures/SkyBlock/Auctions/AuctionInfo'; -import Auction from '../../structures/SkyBlock/Auctions/Auction'; -import Errors from '../../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; - } -} - -export default async function (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/skyblock/getAuctionsByPlayer.ts b/src/API/skyblock/getAuctionsByPlayer.ts deleted file mode 100644 index 80930c9..0000000 --- a/src/API/skyblock/getAuctionsByPlayer.ts +++ /dev/null @@ -1,11 +0,0 @@ -import Auction from '../../structures/SkyBlock/Auctions/Auction'; -import toUuid from '../../utils/toUuid'; -import Errors from '../../Errors'; -export default async function (this: any, query: string, includeItemBytes = false) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/skyblock/auction?player=${query}`); - if (res.raw) return res; - return res.auctions.length ? res.auctions.map((a: any) => new Auction(a, includeItemBytes)) : []; -} diff --git a/src/API/skyblock/getBazaar.ts b/src/API/skyblock/getBazaar.ts deleted file mode 100644 index 2595812..0000000 --- a/src/API/skyblock/getBazaar.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Product from '../../structures/SkyBlock/Bazzar/Product'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/skyblock/bazaar'); - if (res.raw) return res; - const productsKeys = Object.keys(res.products); - return productsKeys.map((x) => new Product(res.products[x])); -} diff --git a/src/API/skyblock/getBingo.ts b/src/API/skyblock/getBingo.ts deleted file mode 100644 index 10432a7..0000000 --- a/src/API/skyblock/getBingo.ts +++ /dev/null @@ -1,7 +0,0 @@ -import BingoData from '../../structures/SkyBlock/Static/BingoData'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/resources/skyblock/bingo'); - if (res.raw) return res; - return new BingoData(res); -} diff --git a/src/API/skyblock/getBingoByPlayer.ts b/src/API/skyblock/getBingoByPlayer.ts deleted file mode 100644 index fde7f0c..0000000 --- a/src/API/skyblock/getBingoByPlayer.ts +++ /dev/null @@ -1,14 +0,0 @@ -import PlayerBingo from '../../structures/SkyBlock/PlayerBingo'; -import toUuid from '../../utils/toUuid'; -import getBingo from './getBingo'; -import Errors from '../../Errors'; -export default async function (this: any, query: string, { fetchBingoData = false }) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/skyblock/uuid?player=${query}`); - if (res.raw) return res; - let bingoData = null; - if (fetchBingoData) bingoData = await getBingo.call(this); - return new PlayerBingo(res, bingoData); -} diff --git a/src/API/skyblock/getEndedAuctions.ts b/src/API/skyblock/getEndedAuctions.ts deleted file mode 100644 index b473f23..0000000 --- a/src/API/skyblock/getEndedAuctions.ts +++ /dev/null @@ -1,11 +0,0 @@ -import PartialAuction from '../../structures/SkyBlock/Auctions/PartialAuction'; -import AuctionInfo from '../../structures/SkyBlock/Auctions/AuctionInfo'; -export default async function (this: any, includeItemBytes = false) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/skyblock/auctions_ended', false); - if (res.raw) return res; - return { - info: new AuctionInfo({ ...res, totalAuctions: res.auctions.length, totalPages: 1 }), - auctions: res.auctions.length ? res.auctions.map((a: any) => new PartialAuction(a, includeItemBytes)) : [] - }; -} diff --git a/src/API/skyblock/getFireSales.ts b/src/API/skyblock/getFireSales.ts deleted file mode 100644 index 681c3d9..0000000 --- a/src/API/skyblock/getFireSales.ts +++ /dev/null @@ -1,7 +0,0 @@ -import FireSale from '../../structures/SkyBlock/Static/FireSale'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/skyblock/firesales'); - if (res.raw) return res; - return res.sales.length ? res.sales.map((a: any) => new FireSale(a)) : []; -} diff --git a/src/API/skyblock/getGarden.ts b/src/API/skyblock/getGarden.ts deleted file mode 100644 index c2b6acf..0000000 --- a/src/API/skyblock/getGarden.ts +++ /dev/null @@ -1,7 +0,0 @@ -import SkyblockGarden from '../../structures/SkyBlock/SkyblockGarden'; -export default async function (this: any, profileId: string) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/skyblock/garden?profile=${profileId}`); - if (res.raw) return res; - return new SkyblockGarden(res); -} diff --git a/src/API/skyblock/getGovernment.ts b/src/API/skyblock/getGovernment.ts deleted file mode 100644 index bcb6e2d..0000000 --- a/src/API/skyblock/getGovernment.ts +++ /dev/null @@ -1,7 +0,0 @@ -import GovernmentData from '../../structures/SkyBlock/Static/Government.js'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/resources/skyblock/election'); - if (res.raw) return res; - return new GovernmentData(res); -} diff --git a/src/API/skyblock/getMember.ts b/src/API/skyblock/getMember.ts deleted file mode 100644 index 0f9e198..0000000 --- a/src/API/skyblock/getMember.ts +++ /dev/null @@ -1,39 +0,0 @@ -import SkyblockMember from '../../structures/SkyBlock/SkyblockMember'; -import getSkyblockMuseum from './getMuseum'; -import getSkyblockGarden from './getGarden'; -import toUuid from '../../utils/toUuid'; -import getPlayer from '../getPlayer'; -import Errors from '../../Errors'; -export default async function ( - this: any, - query: string, - options = { guild: false, recentGames: false, fetchPlayer: false, getMuseum: false, getGarden: false } -) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/skyblock/profiles?uuid=${query}`); - if (res.raw) return res; - if (!res.profiles || !res.profiles.length) throw new Error(Errors.NO_SKYBLOCK_PROFILES); - const player = options.fetchPlayer ? await getPlayer.call(this, query, options) : null; - const memberByProfileName = new Map(); - for (const profile of res.profiles) { - profile.members[query].player = player; - memberByProfileName.set( - profile.cute_name, - new SkyblockMember({ - uuid: query, - profileId: profile.profile_id, - profileName: profile.cute_name, - gameMode: profile.game_mode || null, - m: profile.members[query], - banking: profile.banking, - communityUpgrades: profile.community_upgrades, - museum: options.getMuseum ? await getSkyblockMuseum.call(this, query, profile.profile_id) : null, - garden: options.getGarden ? await getSkyblockGarden.call(this, profile.profile_id) : null, - selected: profile.selected - }) - ); - } - return memberByProfileName; -} diff --git a/src/API/skyblock/getMuseum.ts b/src/API/skyblock/getMuseum.ts deleted file mode 100644 index f83824d..0000000 --- a/src/API/skyblock/getMuseum.ts +++ /dev/null @@ -1,15 +0,0 @@ -import SkyblockMuseum from '../../structures/SkyBlock/SkyblockMuseum'; -import toUuid from '../../utils/toUuid'; -import Errors from '../../Errors'; -export default async function (this: any, query: string, profileId: string) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/skyblock/museum?uuid=${query}&profile=${profileId}`); - if (res.raw) return res; - return new SkyblockMuseum({ - uuid: query, - m: res, - profileId: profileId - }); -} diff --git a/src/API/skyblock/getNews.ts b/src/API/skyblock/getNews.ts deleted file mode 100644 index af3d0db..0000000 --- a/src/API/skyblock/getNews.ts +++ /dev/null @@ -1,7 +0,0 @@ -import SkyblockNews from '../../structures/SkyBlock/News/SkyblockNews'; -export default async function (this: any) { - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest('/skyblock/news'); - if (res.raw) return res; - return res.items.map((i: any) => new SkyblockNews(i)); -} diff --git a/src/API/skyblock/getProfiles.ts b/src/API/skyblock/getProfiles.ts deleted file mode 100644 index 08c2fa6..0000000 --- a/src/API/skyblock/getProfiles.ts +++ /dev/null @@ -1,53 +0,0 @@ -import SkyblockProfile from '../../structures/SkyBlock/SkyblockProfile'; -import getSkyblockGarden from './getGarden'; -import getSkyblockMuseum from './getMuseum'; -import toUuid from '../../utils/toUuid'; -import getPlayer from '../getPlayer'; -import Errors from '../../Errors'; -export default async function ( - this: any, - query: string, - options = { fetchPlayer: false, getMuseum: false, getGarden: false } -) { - if (!query) throw new Error(Errors.NO_NICKNAME_UUID); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - // eslint-disable-next-line no-underscore-dangle - const res = await this._makeRequest(`/skyblock/profiles?uuid=${query}`); - if (res.raw) return res; - if (!res.profiles || !res.profiles.length) throw new Error(Errors.NO_SKYBLOCK_PROFILES); - const players = new Map(); - if (options.fetchPlayer) { - const uniqueUuids = [...new Set(res.profiles.map((profile: any) => Object.keys(profile.members)).flat())]; - await Promise.all( - uniqueUuids.map(async (uuid) => { - const player = await getPlayer.call(this, uuid as string, options as any); - players.set(uuid, player); - }) - ); - } - - const profiles = []; - for (let i = 0; i < res.profiles.length; i++) { - if (options.fetchPlayer) { - for (const memberUuid of Object.keys(res.profiles[i].members)) { - res.profiles[i].members[memberUuid].player = players.get(memberUuid); - } - } - - profiles.push({ - uuid: query, - profileId: res.profiles[i].profile_id, - profileName: res.profiles[i].cute_name, - gameMode: res.profiles[i].game_mode || null, - m: res.profiles[i].members[query], - banking: res.profiles[i].banking, - communityUpgrades: res.profiles[i].community_upgrades, - museum: options.getMuseum ? await getSkyblockMuseum.call(this, query, res.profiles[i].profile_id) : null, - garden: options.getGarden ? await getSkyblockGarden.call(this, res.profiles[i].profile_id) : null, - selected: res.profiles[i].selected, - members: res.profiles[i].members - }); - } - - return profiles.map((p) => new SkyblockProfile(p)); -} diff --git a/src/Client.ts b/src/Client.ts index feb4775..b233a46 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -1,95 +1,79 @@ -import { ClientOptions } from './typings/index'; -import rateLimit from './Private/rateLimit'; -import Cache from './Private/defaultCache'; -import Requests from './Private/requests'; -import validate from './Private/validate'; -import updater from './Private/updater'; -import EventEmitter from 'events'; -import API from './API/index'; +import CheckUpdates from './Private/CheckUpdates'; +import CacheHandler from './Private/CacheHandler'; +import Requests from './Private/Requests'; import Errors from './Errors'; +import fs from 'fs'; const clients: any[] = []; -function handleOptions(options: ClientOptions) { - if (!options.cache) options.cache = true; - if (!options.hypixelCacheTime) options.hypixelCacheTime = 60; - if (!options.mojangCacheTime) options.mojangCacheTime = 600; - if (!options.rateLimit) options.rateLimit = 'AUTO'; - if (!options.syncWithHeaders) options.syncWithHeaders = false; - if (!options.keyLimit) options.keyLimit = 60; - if (!options.cacheSize) options.cacheSize = -1; - if (!options.silent) options.silent = false; - if (!options.headers) options.headers = {}; - if (!options.checkForUpdates) options.checkForUpdates = true; - if (!options.useThirdPartyAPI) options.useThirdPartyAPI = false; - return options; +export interface ClientOptions { + cache?: boolean; + cacheTime?: number; + cacheMaxKeys?: number; + cacheCheckPeriod?: number; + rateLimit?: 'AUTO' | 'HARD' | 'NONE'; + silent?: boolean; + checkForUpdates?: boolean; } -class Client extends EventEmitter { - requests: any; - key: string | undefined; - options: ClientOptions | undefined; - cache: Cache | undefined; - constructor(key: string, options: ClientOptions) { - super(); - this.requests = new Requests(this, options.cacheHandler); - // eslint-disable-next-line no-console - if (options && !options.silent) this.on('warn', console.warn); - if (clients.find((x) => x.key === key)) { - this.emit('warn', Errors.MULTIPLE_INSTANCES); - return clients.find((x) => x.key === key); - } +export default class Client { + readonly key?: string; + + declare requests: Requests; + declare cacheHandler: CacheHandler; + + declare cache: boolean; + declare cacheTime: number; + declare cacheMaxKeys: number; + declare cacheCheckPeriod: number; + declare rateLimit?: 'AUTO' | 'HARD' | 'NONE'; + declare silent: boolean; + declare checkForUpdates: boolean; + declare endpoints: any; + + constructor(key: string, options?: ClientOptions) { + this.loadEndpoints(); this.key = key; - this.options = handleOptions(options); - for (const func in API) { - this[func] = (...args: string | any[]) => { - const lastArg = args[args.length - 1]; - return API[func].apply( - { - // eslint-disable-next-line no-underscore-dangle - _makeRequest: this._makeRequest.bind(this, validate.cacheSuboptions(lastArg) ? lastArg : {}), - ...this - }, - args - ); - }; + this.cache = options?.cache ?? true; + this.cacheTime = options?.cacheTime ?? 300; + this.cacheMaxKeys = options?.cacheMaxKeys ?? -1; + this.cacheCheckPeriod = options?.cacheCheckPeriod ?? 180; + this.rateLimit = options?.rateLimit ?? 'AUTO'; + this.silent = options?.silent ?? false; + this.checkForUpdates = options?.checkForUpdates ?? true; + + this.requests = new Requests(this); + this.cacheHandler = new CacheHandler(this); + + if (clients.find((x) => x.key === key)) { + // eslint-disable-next-line no-console + console.warn(Errors.MULTIPLE_INSTANCES); + return clients.find((x) => x.key === key); } - if (this.options.checkForUpdates) { - try { - updater.checkForUpdates(); - } catch (error) { - if (this.options && !this.options.silent) { - // eslint-disable-next-line no-console - console.warn('[hypixel-api-reborn] Error whilst checking for updates!'); - } - } + if (this.checkForUpdates) { + CheckUpdates().catch(() => { + // eslint-disable-next-line no-console + if (!this.silent) console.warn(Errors.UPDATER_REQUEST_NOT_OK); + }); } - this.cache = this.requests.cache; clients.push(this); - rateLimit.init(this.getGameCounts(), this.options, this).then(() => this.emit('ready')); - } - getGameCounts(): any { - throw new Error('Method not implemented.'); } - async _makeRequest(options: { noCacheCheck: any; raw: any; headers: any }, url: string, useRateLimitManager = true) { - if (!url) return; - if ('/key' !== url && !options.noCacheCheck && (await this.requests.cache.has(url))) { - return Object.assign(await this.requests.cache.get(url), { raw: Boolean(options.raw) }); + async loadEndpoints() { + const endpoints = fs.readdirSync('./src/API').filter((file) => file.endsWith('.ts')); + for (const endpoint of endpoints) { + const { default: EndpointClass } = await import(`./API/${endpoint}`); + const endpointInstance = new EndpointClass(this); + (this as any)[endpointInstance.name] = endpointInstance.execute.bind(endpointInstance); } - if (useRateLimitManager) await rateLimit.rateLimitManager(); - this.emit('outgoingRequest', url, { ...options, headers: { ...options.headers, ...this.options.headers } }); - const result = await this.requests.request.call(this.requests, url, { - ...options, - headers: { ...options.headers, ...this.options?.headers } - }); - // eslint-disable-next-line no-underscore-dangle - if (this.options && this.options.syncWithHeaders && result._headers) rateLimit.sync(result._headers); - return result; } } -export default Client; +export async function createClient(key: string, options?: ClientOptions): Promise { + const client = new Client(key, options); + await client.loadEndpoints(); + return client; +} diff --git a/src/Errors.ts b/src/Errors.ts index 499d3a3..fbe9cf2 100644 --- a/src/Errors.ts +++ b/src/Errors.ts @@ -1,66 +1,66 @@ /* 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', + 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', + '[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', + '[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', + '[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', + '[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', + '[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.', + '[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.', + "[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', + '[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', + '[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', + '[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", + "[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', + '[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] An error occurred checking for updates.', - CONNECTION_ERROR: '[hypixel-api-reborn] Failed to connect.', + "[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.', + '[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.', + '[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', + '[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', + '[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. ", + "[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', + "[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.' + '[Hypixel-API-Reborn] Unexpected filter for Client#getSkyblockAuction. Expected one of "PLAYER", "AUCTION", "PROFILE", but got something else.' }; diff --git a/src/Private/CacheHandler.ts b/src/Private/CacheHandler.ts new file mode 100644 index 0000000..49d0224 --- /dev/null +++ b/src/Private/CacheHandler.ts @@ -0,0 +1,41 @@ +import NodeCache from 'node-cache'; +import Client from '../Client'; + +class CacheHandler { + readonly client: Client; + declare cache: NodeCache; + constructor(client: Client) { + this.client = client; + this.cache = new NodeCache({ + stdTTL: this.client.cacheTime, + maxKeys: this.client.cacheMaxKeys, + checkperiod: this.client.cacheCheckPeriod + }); + } + + set(key: string, value: any): any { + return this.cache.set(key, value); + } + + has(key: string): boolean { + return this.cache.has(key); + } + + get(key: string): any { + return this.cache.get(key); + } + + keys(): string[] { + return this.cache.keys(); + } + + size(): number { + return this.cache.keys().length; + } + + clear(): void { + this.cache.flushAll(); + } +} + +export default CacheHandler; diff --git a/src/Private/CheckUpdates.ts b/src/Private/CheckUpdates.ts new file mode 100644 index 0000000..7630666 --- /dev/null +++ b/src/Private/CheckUpdates.ts @@ -0,0 +1,31 @@ +/* eslint-disable no-console */ +import { version } from '../../package.json'; +import Errors from '../Errors'; +import axios from 'axios'; + +function compareVersions(a: string, b: string): boolean { + const pa = a.split('.'); + const pb = b.split('.'); + for (let i = 0; 3 > i; i++) { + const na = Number(pa[i]); + const nb = Number(pb[i]); + if (na > nb) return false; + if (nb > na) return true; + if (!isNaN(na) && isNaN(nb)) return false; + if (isNaN(na) && !isNaN(nb)) return true; + } + return false; +} + +export default async function (): Promise { + const request = await axios.get('https://registry.npmjs.org/hypixel-api-reborn'); + if (200 !== request.status) return console.log(Errors.UPDATER_REQUEST_NOT_OK); + const metadata = await request.data; + const latest = metadata['dist-tags'].latest; + const compare = compareVersions(version, latest); + if (compare) { + console.log( + `New version of hypixel-api-reborn is available! Current version: ${version}, Latest version: ${latest}` + ); + } +} diff --git a/src/Private/Endpoint.ts b/src/Private/Endpoint.ts new file mode 100644 index 0000000..5963a9e --- /dev/null +++ b/src/Private/Endpoint.ts @@ -0,0 +1,14 @@ +import Client from '../Client'; + +class Endpoint { + readonly client: Client; + constructor(client: Client) { + this.client = client; + } + + execute(query?: string, range?: any, options?: any, includeItemBytes?: any): Promise | any { + throw new Error('Command execute method is not implemented yet!'); + } +} + +export default Endpoint; diff --git a/src/Private/Requests.ts b/src/Private/Requests.ts new file mode 100644 index 0000000..f44d0a6 --- /dev/null +++ b/src/Private/Requests.ts @@ -0,0 +1,57 @@ +const BASE_URL = 'https://api.hypixel.net/v2'; +import Client from '../Client'; +import Errors from '../Errors'; +import axios from 'axios'; + +export interface RequestOptions { + raw?: boolean; + noCache?: boolean; +} + +class Requests { + readonly client: Client; + constructor(client: Client) { + this.client = client; + } + + async request(endpoint: string, options?: RequestOptions): Promise { + const info = { + raw: options?.raw ?? false, + noCache: options?.noCache ?? false + }; + if (this.client.cacheHandler.has(endpoint)) { + return this.client.cacheHandler.get(endpoint); + } + 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}`) + ); + } + 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 || '') + ); + } + 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 (!parsedRes.success && !endpoint.startsWith('/housing')) { + throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.statusText)); + } + + // eslint-disable-next-line no-underscore-dangle + parsedRes._headers = res.headers; + parsedRes.raw = Boolean(info.raw); + if (info.noCache) return parsedRes; + if (this.client.cache && !info.raw) { + this.client.cacheHandler.set(endpoint, parsedRes); + } + + return parsedRes; + } +} + +export default Requests; diff --git a/src/Private/defaultCache.ts b/src/Private/defaultCache.ts deleted file mode 100644 index f5ddf5a..0000000 --- a/src/Private/defaultCache.ts +++ /dev/null @@ -1,36 +0,0 @@ -class Cache { - storage: Map; - constructor() { - this.storage = new Map(); - } - - set(key: string, value: any): void { - this.storage.set(key, value); - } - - get(key: string): any { - return this.storage.get(key); - } - - has(key: string): boolean { - return this.storage.has(key); - } - - delete(key: string): boolean { - return this.storage.delete(key); - } - - keys(): string[] { - return Array.from(this.storage.keys()); - } - - size(): number { - return this.storage.size; - } - - clear(): void { - this.storage.clear(); - } -} - -export default Cache; diff --git a/src/Private/rateLimit.ts b/src/Private/rateLimit.ts deleted file mode 100644 index 954af6b..0000000 --- a/src/Private/rateLimit.ts +++ /dev/null @@ -1,93 +0,0 @@ -import Errors from '../Errors'; - -class RateLimit { - initialized: number; - requests: any; - requestQueue: any; - options: any; - lastResetHappenedAt: any; - resetTimer: any; - cooldownTime: any; - client: any; - static options: any; - static requests: any; - static lastResetHappenedAt: number; - static reset: any; - constructor() { - this.initialized = 0; - } - - static async rateLimitManager() { - if (!this.initialized) return; - this.requests++; - this.requestQueue.unshift(Date.now()); - if ('NONE' === this.options.rateLimit || !this.requestQueue.length) return; - if ('AUTO' === this.options.rateLimit && this.requests <= this.options.keyLimit / 2) return; - const cooldown = this.computeCooldownTime(); - this.requestQueue[0] = Date.now() + cooldown; - return await new Promise((r) => setTimeout(r, cooldown)); - } - - static sync(data: any): void { - this.options.keyLimit = parseInt(data.get('ratelimit-limit'), 10) || this.options.keyLimit; - this.requests = parseInt(data.get('ratelimit-remaining'), 10) || this.requests; - if ( - data.get('ratelimit-reset') && - Math.round(Date.now() / 1000) - (300 - parseInt(data.get('ratelimit-reset'), 10)) !== - Math.round(this.lastResetHappenedAt / 1000) - ) { - clearTimeout(this.resetTimer); - this.resetTimer = setTimeout(this.reset.bind(this), parseInt(data.get('ratelimit-reset'), 10) * 1000); - } - } - static resetTimer(resetTimer: any) { - throw new Error('Method not implemented.'); - } - - computeCooldownTime() { - const overhead = this.requestQueue[1] <= Date.now() ? 0 : this.requestQueue[1] - Date.now(); - const multiplier = Math.floor(this.requests / this.options.keyLimit) + 1; - return ( - overhead + - (-overhead - Date.now() + 300000 * multiplier + this.lastResetHappenedAt) / - (this.options.keyLimit * multiplier - this.requests) - ); - } - - reset() { - this.requests = this.requests - this.options.keyLimit; - if (0 > this.requests) this.requests = 0; - this.lastResetHappenedAt = Date.now(); - this.resetTimer = setTimeout(this.reset.bind(this), 300000); - this.requestQueue = this.requestQueue.filter((x: any) => x >= Date.now()); - } - - rateLimitMonitor() { - this.resetTimer = setTimeout(this.reset.bind(this), 1000 * 300); - } - - init(keyInfo: any, options: any, client: any) { - this.options = options; - this.requests = 0; - this.cooldownTime = 300000 / this.options.keyLimit; - this.requestQueue = []; - this.client = client; - return keyInfo - .then((info: any) => { - this.requests = info.requestsInPastMin; - this.lastResetHappenedAt = Date.now() - (300 - info.resetsAfter) * 1000; - this.resetTimer = setTimeout(this.rateLimitMonitor.bind(this), 1000 * info.resetsAfter); - this.initialized = 1; - }) - .catch(() => { - client.emit('warn', Errors.RATE_LIMIT_INIT_ERROR); - this.requests = 0; - this.lastResetHappenedAt = Date.now(); - this.rateLimitMonitor(); - this.initialized = 1; - }); - // Still make the requests per min possible - } -} - -export default RateLimit; diff --git a/src/Private/requests.ts b/src/Private/requests.ts deleted file mode 100644 index 21ef146..0000000 --- a/src/Private/requests.ts +++ /dev/null @@ -1,73 +0,0 @@ -const BASE_URL = 'https://api.hypixel.net/v2'; -import Cache from './defaultCache'; -import Errors from '../Errors'; -import axios from 'axios'; - -function validateCustomCache(cache: any) { - return Boolean(cache.set && cache.get && cache.delete && cache.keys); -} - -class Requests { - cached: any; - client: any; - constructor(client: any, cache: any) { - if (cache && !validateCustomCache(cache)) throw new Error(Errors.INVALID_CACHE_HANDLER); - this.cached = cache || new Cache(); - this.client = client; - } - async request(endpoint: any, options: any = {}) { - options.headers = { 'API-Key': this.client.key, ...options.headers }; - const res = await axios.get(BASE_URL + endpoint, options); - if (500 <= res.status && 528 > res.status) { - throw new Error( - Errors.ERROR_STATUSTEXT.replace(/{statustext}/, `Server Error : ${res.status} ${res.statusText}`) - ); - } - const parsedRes = await res.data.json().catch(() => { - throw new Error(Errors.INVALID_RESPONSE_BODY); - }); - if (400 === res.status) { - throw new Error( - 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 (!parsedRes.success && !endpoint.startsWith('/housing')) { - throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.statusText)); - } - // eslint-disable-next-line no-underscore-dangle - parsedRes._headers = res.headers; - parsedRes.raw = Boolean(options.raw); - if (options.noCaching) return parsedRes; - // split by question mark : first part is /path, remove / - if (this.client.options.cache && this.client.options.cacheFilter(endpoint.split('?')[0].slice(1))) { - if (this.client.options.cacheSize < (await this.cached.size())) { - await this.cached.delete(Array.from(await this.cached.keys())[0]); - } - await this.cached.delete(endpoint); - await this.cached.set(endpoint, parsedRes); - if (0 <= this.client.options.hypixelCacheTime) { - setTimeout(() => this.cached.delete(endpoint), 1000 * this.client.options.hypixelCacheTime); - } - } - return parsedRes; - } - - get cache() { - return this.cached; - } - - async sweepCache(amount: any) { - if (!amount || amount >= (await this.cached.size())) return await this.cached.clear(); - return await Promise.all( - Array.from(await this.cached.keys()) - .slice((await this.cached.size()) - amount) - .map((x) => this.cached.delete(x)) - ); - } -} - -export default Requests; diff --git a/src/Private/updater.ts b/src/Private/updater.ts deleted file mode 100644 index 0b3f0c0..0000000 --- a/src/Private/updater.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { version } from '../../package.json'; -import { UpdateHandler } from '../typings'; -import Errors from '../Errors'; -import axios from 'axios'; - -class Updater implements UpdateHandler { - static checkForUpdates() { - throw new Error('Method not implemented.'); - } - async checkForUpdates() { - const request = await axios.get('https://registry.npmjs.org/hypixel-api-reborn'); - // eslint-disable-next-line no-console - if (200 !== request.status) return console.log(Errors.UPDATER_REQUEST_NOT_OK); - const metadata = await request.data; - const latest = metadata['dist-tags'].latest; - const compare = this.compare(version, latest); - if (-1 === compare) { - // eslint-disable-next-line no-console - console.log( - `New version of hypixel-api-reborn is available! Current version: ${version}, Latest version: ${latest}` - ); - } - } - - compare(a: string, b: string) { - const pa = a.split('.'); - const pb = b.split('.'); - for (let i = 0; 3 > i; i++) { - const na = Number(pa[i]); - const nb = Number(pb[i]); - if (na > nb) return 1; - if (nb > na) return -1; - if (!isNaN(na) && isNaN(nb)) return 1; - if (isNaN(na) && !isNaN(nb)) return -1; - } - return 0; - } -} - -export default Updater; diff --git a/src/Private/uuidCache.ts b/src/Private/uuidCache.ts index 05851d5..40222e9 100644 --- a/src/Private/uuidCache.ts +++ b/src/Private/uuidCache.ts @@ -11,7 +11,7 @@ export interface CacheData { export default async function (url: string, query: string, cacheTime: number): Promise { if (cache.has(query.toLowerCase())) return cache.get(query.toLowerCase()) as CacheData; const res = await axios.get(url); - const data = await res.data.json(); + const data = await res.data; // Don't cache 4xx if (400 <= res.status) { return { diff --git a/src/Private/validate.ts b/src/Private/validate.ts deleted file mode 100644 index 37a3eef..0000000 --- a/src/Private/validate.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ClientOptions } from '../typings'; -import Errors from '../Errors'; - -/** - * Validation Class, used internally to validate provided arguments - */ -class Validation { - static validateOptions(options: ClientOptions): void { - if ('number' !== typeof options.hypixelCacheTime) throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER); - if ('number' !== typeof options.mojangCacheTime) throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER); - if ('number' !== typeof options.cacheSize) throw new Error(Errors.CACHE_LIMIT_MUST_BE_A_NUMBER); - if ('string' !== typeof options.rateLimit || !['AUTO', 'HARD', 'NONE'].includes(options.rateLimit)) { - throw new Error(Errors.INVALID_RATE_LIMIT_OPTION); - } - if ('number' !== typeof options.keyLimit) throw new Error(Errors.INVALID_KEY_LIMIT_OPTION); - if ('boolean' !== typeof options.syncWithHeaders) throw new Error(Errors.INVALID_HEADER_SYNC_OPTION); - if ('object' !== typeof options.headers) throw new Error(Errors.INVALID_HEADERS); - if ('boolean' !== typeof options.silent) throw new Error(Errors.INVALID_SILENT_OPTION); - if ('boolean' !== typeof options.checkForUpdates) throw new Error(Errors.INVALID_UPDATE_OPTION); - if (!['boolean', 'string'].includes(typeof options.useThirdPartyAPI)) { - throw new Error(Errors.INVALID_THIRD_PARTY_API_OPTION); - } - } - - static parseOptions(options: ClientOptions): ClientOptions { - if ('object' !== typeof options || null === options) throw new Error(Errors.OPTIONS_MUST_BE_AN_OBJECT); - return { - cache: options.cache ?? true, - hypixelCacheTime: options.hypixelCacheTime ?? 60, - mojangCacheTime: options.mojangCacheTime ?? 600, - cacheSize: (-1 === options.cacheSize ? Infinity : options.cacheSize) || Infinity, - rateLimit: options.rateLimit ?? 'AUTO', - keyLimit: options.keyLimit ?? 60, - syncWithHeaders: Boolean(options.syncWithHeaders), - headers: options.headers ?? {}, - silent: Boolean(options.silent), - checkForUpdates: options.checkForUpdates ?? true, - useThirdPartyAPI: options.useThirdPartyAPI ?? false - }; - } - - static validateKey(key: string): string { - if (!key) throw new Error(Errors.NO_API_KEY); - if ('string' !== typeof key) throw new Error(Errors.KEY_MUST_BE_A_STRING); - return key; - } - - static cacheSuboptions(input: any): boolean { - if ('object' !== typeof input || null === input) return false; - if (!input.noCacheCheck && !input.noCaching && !input.raw) return false; - return true; - } - - static validateNodeVersion() { - const versionMatch = process.version.match(/v(\d{2})\.\d{1,}\.\d+/); - const nodeVersion = parseInt(versionMatch ? versionMatch[1] : '', 10); - if (12 > nodeVersion) throw new Error(Errors.NODE_VERSION_ERR); - } -} - -export default Validation; diff --git a/src/index.ts b/src/index.ts index 51fd956..046b70e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,63 +1,36 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import Client from './Client'; -import Errors from './Errors'; +export * from './Client'; +export * from './Errors'; -import APIStatus from './structures/APIStatus'; -import APIIncident from './structures/APIIncident'; -import Player from './structures/Player'; -import Game from './structures/Game'; -import Status from './structures/Status'; -import Color from './structures/Color'; -import Pet from './structures/Pet'; -import Pets from './structures/Pets'; -import PlayerCosmetics from './structures/PlayerCosmetics'; -import Challenges from './structures/Static/Challenges'; -import GameChallenges from './structures/Static/GameChallenges'; -import WatchdogStats from './structures/Watchdog/Stats'; -import Guild from './structures/Guild/GuildMember'; -import GuildMember from './structures/Guild/GuildMember'; -import GuildRank from './structures/Guild/GuildRank'; -import SkyblockProfile from './structures/SkyBlock/SkyblockProfile'; -import SkyblockMember from './structures/SkyBlock/SkyblockMember'; -import SkyblockGarden from './structures/SkyBlock/SkyblockGarden'; -import SkyblockInventoryItem from './structures/SkyBlock/SkyblockInventoryItem'; -import SkyblockPet from './structures/SkyBlock/SkyblockPet'; -import GovernmentData from './structures/SkyBlock/Static/Government'; -import Candidate from './structures/SkyBlock/Static/Candidate'; -import BingoData from './structures/SkyBlock/Static/BingoData'; -import Bingo from './structures/SkyBlock/Static/Bingo'; -import BaseAuction from './structures/SkyBlock/Auctions/BaseAuction'; -import PartialAuction from './structures/SkyBlock/Auctions/PartialAuction'; -import Auction from './structures/SkyBlock/Auctions/Auction'; -import AuctionInfo from './structures/SkyBlock/Auctions/AuctionInfo'; -import Bid from './structures/SkyBlock/Auctions/Bid'; -import FireSale from './structures/SkyBlock/Static/FireSale'; -import Product from './structures/SkyBlock/Bazzar/Product'; -import Order from './structures/SkyBlock/Bazzar/Order'; -import SkyblockNews from './structures/SkyBlock/News/SkyblockNews'; -import Booster from './structures/Boosters/Booster'; -import House from './structures/House'; -import Arcade from './structures/MiniGames/Arcade'; -import ArenaBrawl from './structures/MiniGames/ArenaBrawl'; -import BedWars from './structures/MiniGames/BedWars'; -import BlitzSurvivalGames from './structures/MiniGames/BlitzSurvivalGames'; -import BuildBattle from './structures/MiniGames/BuildBattle'; -import CopsAndCrims from './structures/MiniGames/CopsAndCrims'; -import Duels from './structures/MiniGames/Duels'; -import MegaWalls from './structures/MiniGames/MegaWalls'; -import MurderMystery from './structures/MiniGames/MurderMystery'; -import Paintball from './structures/MiniGames/Paintball'; -import Pit from './structures/MiniGames/Pit'; -import Quakecraft from './structures/MiniGames/Quakecraft'; -import SkyWars from './structures/MiniGames/SkyWars'; -import SmashHeroes from './structures/MiniGames/SmashHeroes'; -import SpeedUHC from './structures/MiniGames/SpeedUHC'; -import TNTGames from './structures/MiniGames/TNTGames'; -import TurboKartRacers from './structures/MiniGames/TurboKartRacers'; -import UHC from './structures/MiniGames/UHC'; -import VampireZ from './structures/MiniGames/VampireZ'; -import Walls from './structures/MiniGames/Walls'; -import Warlords from './structures/MiniGames/Warlords'; -import WoolWars from './structures/MiniGames/WoolWars'; -import Leaderboard from './structures/Leaderboard'; -import ServerInfo from './structures/ServerInfo'; +export * from './Private/CacheHandler'; +export * from './Private/CheckUpdates'; +export * from './Private/Endpoint'; +export * from './Private/Requests'; +export * from './Private/uuidCache'; + +export * from './API/getAchievements'; +export * from './API/getActiveHouses'; +export * from './API/getBoosters'; +export * from './API/getChallenges'; +export * from './API/getGameCounts'; +export * from './API/getGuild'; +export * from './API/getGuildAchievements'; +export * from './API/getHouse'; +export * from './API/getLeaderboards'; +export * from './API/getPlayer'; +export * from './API/getPlayerHouses'; +export * from './API/getQuests'; +export * from './API/getRecentGames'; +export * from './API/getSkyblockAuction'; +export * from './API/getSkyblockAuctionsByPlayer'; +export * from './API/getSkyblockBazaar'; +export * from './API/getSkyblockBingo'; +export * from './API/getSkyblockBingoByPlayer'; +export * from './API/getSkyblockEndedAuctions'; +export * from './API/getSkyblockFireSales'; +export * from './API/getSkyblockGarden'; +export * from './API/getSkyblockGovernment'; +export * from './API/getSkyblockMember'; +export * from './API/getSkyblockNews'; +export * from './API/getSkyblockProfiles'; +export * from './API/getStatus'; +export * from './API/getWatchdogStats'; diff --git a/src/structures/Game.ts b/src/structures/Game.ts index 52f9f19..13234fa 100644 --- a/src/structures/Game.ts +++ b/src/structures/Game.ts @@ -1,6 +1,116 @@ -import { GameCode, GameID, GameString } from '../typings'; import Constants from '../utils/Constants'; +export type GameString = + | 'Quake Craft' + | 'Walls' + | 'Paintball' + | 'Blitz Survival Games' + | 'The TNT Games' + | 'VampireZ' + | 'Mega Walls' + | 'Arcade' + | 'Arena Brawl' + | 'UHC Champions' + | 'Cops and Crims' + | 'Warlords' + | 'Smash Heroes' + | 'Turbo Kart Racers' + | 'Housing' + | 'SkyWars' + | 'Crazy Walls' + | 'Speed UHC' + | 'SkyClash' + | 'Classic Games' + | 'Prototype' + | 'Bed Wars' + | 'Murder Mystery' + | 'Build Battle' + | 'Duels' + | 'SkyBlock' + | 'The Pit' + | 'Replay' + | 'SMP' + | 'Wool Wars' + | 'Limbo' + | 'Queue' + | 'Main Lobby' + | 'Tournament Lobby' + | 'Idle'; + +export type GameCode = + | 'QUAKECRAFT' + | 'WALLS' + | 'PAINTBALL' + | 'SURVIVAL_GAMES' + | 'TNTGAMES' + | 'VAMPIREZ' + | 'WALLS3' + | 'ARCADE' + | 'ARENA' + | 'UHC' + | 'MCGO' + | 'BATTLEGROUND' + | 'SUPER_SMASH' + | 'GINGERBREAD' + | 'HOUSING' + | 'SKYWARS' + | 'TRUE_COMBAT' + | 'SPEED_UHC' + | 'SKYCLASH' + | 'LEGACY' + | 'PROTOTYPE' + | 'BEDWARS' + | 'MURDER_MYSTERY' + | 'BUILD_BATTLE' + | 'DUELS' + | 'SKYBLOCK' + | 'PIT' + | 'REPLAY' + | 'SMP' + | 'WOOL_GAMES' + | 'LIMBO' + | 'QUEUE' + | 'MAIN_LOBBY' + | 'TOURNAMENT_LOBBY' + | 'IDLE'; + +export type GameID = + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 13 + | 14 + | 17 + | 20 + | 21 + | 23 + | 24 + | 25 + | 26 + | 51 + | 52 + | 54 + | 55 + | 56 + | 57 + | 58 + | 59 + | 60 + | 61 + | 63 + | 64 + | 65 + | 67 + | 68 + | -2 + | -3 + | -4 + | -5 + | -6; + /** * Game class */ diff --git a/src/structures/Guild/Guild.ts b/src/structures/Guild/Guild.ts index ecbb719..73994a2 100644 --- a/src/structures/Guild/Guild.ts +++ b/src/structures/Guild/Guild.ts @@ -1,5 +1,4 @@ -import { calculateExpHistory, getGuildLevel, members, ranks, totalWeeklyGexp } from '../../utils/Guild'; -import { ExpHistory } from '../../typings'; +import { calculateExpHistory, ExpHistory, getGuildLevel, members, ranks, totalWeeklyGexp } from '../../utils/Guild'; import GuildMember from './GuildMember'; import GuildRank from './GuildRank'; import Color from '../Color'; diff --git a/src/structures/Guild/GuildMember.ts b/src/structures/Guild/GuildMember.ts index 6fa2543..a29c800 100644 --- a/src/structures/Guild/GuildMember.ts +++ b/src/structures/Guild/GuildMember.ts @@ -1,5 +1,4 @@ -import { parseHistory } from '../../utils/Guild'; -import { ExpHistory } from '../../typings'; +import { ExpHistory, parseHistory } from '../../utils/Guild'; class GuildMember { uuid: string; diff --git a/src/structures/MiniGames/BedWars.ts b/src/structures/MiniGames/BedWars.ts index a2a44ec..39b7214 100644 --- a/src/structures/MiniGames/BedWars.ts +++ b/src/structures/MiniGames/BedWars.ts @@ -1,14 +1,155 @@ -import { - BedWarsCollectedItems, - BedWarsPracticeStats, - BedwarsDreamStats, - BedWarsModeStats, - BedWarsPrestige, - BedWarsBeds, - BedWarsAvg -} from '../../typings'; import divide from '../../utils/divide'; +export type BedWarsPrestige = + | 'Stone' + | 'Iron' + | 'Gold' + | 'Diamond' + | 'Emerald' + | 'Sapphire' + | 'Ruby' + | 'Crystal' + | 'Opal' + | 'Amethyst' + | 'Rainbow' + | 'Iron Prime' + | 'Gold Prime' + | 'Diamond Prime' + | 'Emerald Prime' + | 'Sapphire Prime' + | 'Ruby Prime' + | 'Crystal Prime' + | 'Opal Prime' + | 'Amethyst Prime' + | 'Mirror' + | 'Light' + | 'Dawn' + | 'Dusk' + | 'Air' + | 'Wind' + | 'Nebula' + | 'Thunder' + | 'Earth' + | 'Water' + | 'Fire' + | 'Sunrise' + | 'Eclipse' + | 'Gamma' + | 'Majestic' + | 'Andesine' + | 'Marine' + | 'Element' + | 'Galaxy' + | 'Atomic' + | 'Sunset' + | 'Time' + | 'Winter' + | 'Obsidian' + | 'Spring' + | 'Ice' + | 'Summer' + | 'Spinel' + | 'Autumn' + | 'Mystic' + | 'Eternal'; + +export interface BedWarsCollectedItems { + iron: number; + gold: number; + diamond: number; + emerald: number; +} + +export interface BedWarsAvg { + kills: number; + finalKills: number; + bedsBroken: number; +} + +export interface BedWarsBeds { + lost: number; + broken: number; + BLRatio: number; +} + +export interface BedWarsModeStats { + winstreak: number; + playedGames: number; + kills: number; + deaths: number; + wins: number; + losses: number; + finalKills: number; + finalDeaths: number; + beds: BedWarsBeds; + avg: BedWarsAvg; + KDRatio: number; + WLRatio: number; + finalKDRatio: number; +} +export interface BedwarsDreamModeStats { + doubles: BedWarsModeStats; + fours: BedWarsModeStats; +} + +export interface BedwarsDreamStats { + ultimate: BedwarsDreamModeStats; + rush: BedwarsDreamModeStats; + armed: BedwarsDreamModeStats; + lucky: BedwarsDreamModeStats; + voidless: BedwarsDreamModeStats; +} + +export interface BedWarsPracticeAttempts { + failed: number; + successful: number; + total: number; +} + +export interface BedWarsPracticeElevation { + straight: number; + diagonal: number; +} + +export interface BedWarsPracticeElevations { + none: BedWarsPracticeElevation; + slight: BedWarsPracticeElevation; + staircase: BedWarsPracticeElevation; +} + +export interface BedWarsPracticeRecord { + elevation: BedWarsPracticeElevations; +} + +export interface BedWarsPracticeRecords { + blocks30: BedWarsPracticeRecord; + blocks50: BedWarsPracticeRecord; + blocks100: BedWarsPracticeRecord; +} + +export interface BedWarsPracticeBridging { + blocksPlaced: number; + attempts: BedWarsPracticeAttempts; + records: BedWarsPracticeRecords; +} + +export interface BedWarsPracticePearlClutching { + attempts: BedWarsPracticeAttempts; +} + +export interface BedWarsPracticeBase { + blocksPlaced: number; + attempts: BedWarsPracticeAttempts; +} + +export interface BedWarsPracticeStats { + selected: string; + bridging: BedWarsPracticeBridging; + fireballJumping: BedWarsPracticeBase; + pearlClutching: BedWarsPracticePearlClutching; + mlg: BedWarsPracticeBase; +} + function generateStatsForMode(data: Record, mode: string): BedWarsModeStats { return { winstreak: data[`${mode}_winstreak`] || 0, diff --git a/src/structures/MiniGames/BuildBattle.ts b/src/structures/MiniGames/BuildBattle.ts index 4c6ef23..474193b 100644 --- a/src/structures/MiniGames/BuildBattle.ts +++ b/src/structures/MiniGames/BuildBattle.ts @@ -1,5 +1,12 @@ -import { BuildBattleWins } from '../../typings'; import divide from '../../utils/divide'; + +export interface BuildBattleWins { + solo: number; + teams: number; + pro: number; + gtb: number; +} + /** * BuildBattle class */ diff --git a/src/structures/MiniGames/Pit.ts b/src/structures/MiniGames/Pit.ts index 9f40985..9740902 100644 --- a/src/structures/MiniGames/Pit.ts +++ b/src/structures/MiniGames/Pit.ts @@ -1,9 +1,14 @@ import { decode } from '../../utils/SkyblockUtils'; import PitInventoryItem from './PitInventoryItem'; import Constants from '../../utils/Constants'; -import { PitArmor } from '../../typings'; import divide from '../../utils/divide'; +export interface PitArmor { + helmet: PitInventoryItem | null; + chestplate: PitInventoryItem | null; + leggings: PitInventoryItem | null; + boots: PitInventoryItem | null; +} /** * Pit Class */ diff --git a/src/structures/MiniGames/SkyWars.ts b/src/structures/MiniGames/SkyWars.ts index 44b6af6..cee2206 100644 --- a/src/structures/MiniGames/SkyWars.ts +++ b/src/structures/MiniGames/SkyWars.ts @@ -1,7 +1,19 @@ import { removeSnakeCaseString } from '../../utils/removeSnakeCase'; -import { SkyWarsPrestige } from '../../typings'; import divide from '../../utils/divide'; +export type SkyWarsPrestige = + | 'Iron' + | 'Gold' + | 'Diamond' + | 'Emerald' + | 'Sapphire' + | 'Ruby' + | 'Crystal' + | 'Opal' + | 'Amethyst' + | 'Rainbow' + | 'Mythic'; + function getSkyWarsPrestige(level: number): SkyWarsPrestige { if (60 <= level) return 'Mythic'; return (['Iron', 'Iron', 'Gold', 'Diamond', 'Emerald', 'Sapphire', 'Ruby', 'Crystal', 'Opal', 'Amethyst', 'Rainbow'][ diff --git a/src/structures/MiniGames/WoolWars.ts b/src/structures/MiniGames/WoolWars.ts index c72cc6c..6dd403b 100644 --- a/src/structures/MiniGames/WoolWars.ts +++ b/src/structures/MiniGames/WoolWars.ts @@ -1,6 +1,27 @@ -import { WoolWarsPrivateGamesConfig, WoolWarsStats } from '../../typings'; import divide from '../../utils/divide'; +export interface WoolWarsStats { + wins: number; + gamesPlayed: number; + woolsPlaced: number; + blocksBroken: number; + placeBreakRatio: number; + kills: number; + deaths: number; + KDRatio: number; + assists: number; + powerups: number; +} +export interface WoolWarsPrivateGamesConfig { + one_hit_one_kil: boolean; + rainbow_wool: 'Enabled' | 'Disabled'; + health_buff: string; + game_speed: string; + speed: string; + no_class: 'Enabled' | 'Disabled'; + respawn_enable: boolean; +} + function convertXPToLevel(exp: number): number { const minimalExp = [0, 1e3, 3e3, 6e3, 1e4, 15e3]; const baseLevel = minimalExp.length; diff --git a/src/structures/Pets.ts b/src/structures/Pets.ts index c39c54e..66d311a 100644 --- a/src/structures/Pets.ts +++ b/src/structures/Pets.ts @@ -1,6 +1,35 @@ -import { PetConsumables } from '../typings'; import Pet from './Pet'; +export interface PetConsumables { + BAKED_POTATO: number; + COOKIE: number; + FEATHER: number; + HAY_BLOCK: number; + SLIME_BALL: number; + COOKED_BEEF: number; + RED_ROSE: number; + WATER_BUCKET: number; + MELON: number; + STICK: number; + WOOD_SWORD: number; + MILK_BUCKET: number; + GOLD_RECORD: number; + LEASH: number; + LAVA_BUCKET: number; + BONE: number; + MAGMA_CREAM: number; + WHEAT: number; + MUSHROOM_SOUP: number; + BREAD: number; + PUMPKIN_PIE: number; + APPLE: number; + CARROT_ITEM: number; + RAW_FISH: number; + PORK: number; + CAKE: number; + ROTTEN_FLESH: number; +} + class Pets { pets: Pet[]; lastJourneyTimestamp: number | null; diff --git a/src/structures/Player.ts b/src/structures/Player.ts index dcee746..a5efa38 100644 --- a/src/structures/Player.ts +++ b/src/structures/Player.ts @@ -1,33 +1,53 @@ import { getPlayerLevel, getRank, getSocialMedia, parseClaimedRewards, playerLevelProgress } from '../utils/Player'; -import { LevelProgress, PlayerRank, PlayerSocialMedia, RanksPurchaseTime } from '../typings'; -import { recursive } from '../utils/removeSnakeCase'; -import RecentGame from './RecentGame'; -import Guild from './Guild/Guild'; -import Color from './Color'; -import Game from './Game'; -import Arcade from './MiniGames/Arcade'; -import ArenaBrawl from './MiniGames/ArenaBrawl'; -import BedWars from './MiniGames/BedWars'; import BlitzSurvivalGames from './MiniGames/BlitzSurvivalGames'; -import BuildBattle from './MiniGames/BuildBattle'; +import TurboKartRacers from './MiniGames/TurboKartRacers'; +import MurderMystery from './MiniGames/MurderMystery'; +import { recursive } from '../utils/removeSnakeCase'; import CopsAndCrims from './MiniGames/CopsAndCrims'; -import Duels from './MiniGames/Duels'; +import BuildBattle from './MiniGames/BuildBattle'; +import SmashHeroes from './MiniGames/SmashHeroes'; +import PlayerCosmetics from './PlayerCosmetics'; +import Quakecraft from './MiniGames/Quakecraft'; +import ArenaBrawl from './MiniGames/ArenaBrawl'; import MegaWalls from './MiniGames/MegaWalls'; -import MurderMystery from './MiniGames/MurderMystery'; import Paintball from './MiniGames/Paintball'; -import Pit from './MiniGames/Pit'; -import Quakecraft from './MiniGames/Quakecraft'; -import SkyWars from './MiniGames/SkyWars'; -import SmashHeroes from './MiniGames/SmashHeroes'; import SpeedUHC from './MiniGames/SpeedUHC'; import TNTGames from './MiniGames/TNTGames'; -import TurboKartRacers from './MiniGames/TurboKartRacers'; -import UHC from './MiniGames/UHC'; import VampireZ from './MiniGames/VampireZ'; -import Walls from './MiniGames/Walls'; import Warlords from './MiniGames/Warlords'; import WoolWars from './MiniGames/WoolWars'; -import PlayerCosmetics from './PlayerCosmetics'; +import SkyWars from './MiniGames/SkyWars'; +import BedWars from './MiniGames/BedWars'; +import Arcade from './MiniGames/Arcade'; +import Walls from './MiniGames/Walls'; +import Duels from './MiniGames/Duels'; +import UHC from './MiniGames/UHC'; +import Pit from './MiniGames/Pit'; +import Color from './Color'; +import Game from './Game'; + +export interface LevelProgress { + xpToNext: number; + remainingXP: number; + currentXP: number; + percent: number; + percentRemaining: number; +} + +export interface PlayerSocialMedia { + name: string; + link: string; + id: string; +} + +export type PlayerRank = 'VIP' | 'VIP+' | 'MVP' | 'MVP+' | 'MVP++' | 'Game Master' | 'Admin' | 'YouTube'; + +export interface RanksPurchaseTime { + VIP: Date | null; + VIP_PLUS: Date | null; + MVP: Date | null; + MVP_PLUS: Date | null; +} class Player { nickname: string; @@ -61,15 +81,13 @@ class Player { rewardScore: number | null; rewardHighScore: number | null; levelProgress: LevelProgress; - guild: Guild | null; - recentGames: RecentGame[] | null; stats: any | null; userLanguage: string; claimedLevelingRewards: number[]; globalCosmetics: PlayerCosmetics | null; ranksPurchaseTime: RanksPurchaseTime; - constructor(data: Record, extraPayload: Record) { + constructor(data: Record) { this.nickname = data.displayname; this.uuid = data.uuid; this.rank = getRank(data); @@ -110,8 +128,6 @@ class Player { this.rewardScore = data.rewardScore || null; this.rewardHighScore = data.rewardHighScore || null; this.levelProgress = playerLevelProgress(data.networkExp); - this.guild = extraPayload?.guild || null; - this.recentGames = extraPayload?.recentGames || null; this.stats = data.stats ? { arcade: data.stats.Arcade ? new Arcade({ ...data.stats.Arcade, ...data.achievements }) : null, diff --git a/src/structures/ServerInfo.ts b/src/structures/ServerInfo.ts index fc6ea54..34cd2dc 100644 --- a/src/structures/ServerInfo.ts +++ b/src/structures/ServerInfo.ts @@ -1,4 +1,9 @@ -import { PlayerInfo } from '../typings'; +export interface PlayerInfo { + max: number; + online: number; + players: any[]; + toString(): string; +} class ServerInfo { protocolUsed: number; diff --git a/src/structures/SkyBlock/Auctions/Auction.ts b/src/structures/SkyBlock/Auctions/Auction.ts index 0905acd..b6ed60b 100644 --- a/src/structures/SkyBlock/Auctions/Auction.ts +++ b/src/structures/SkyBlock/Auctions/Auction.ts @@ -1,4 +1,4 @@ -import { SkyblockRarity } from '../../../typings'; +import { SkyblockRarity } from '../../../utils/SkyblockUtils'; import BaseAuction from './BaseAuction'; import Bid from './Bid'; diff --git a/src/structures/SkyBlock/Bazzar/Product.ts b/src/structures/SkyBlock/Bazzar/Product.ts index 82e4ccd..337be11 100644 --- a/src/structures/SkyBlock/Bazzar/Product.ts +++ b/src/structures/SkyBlock/Bazzar/Product.ts @@ -1,6 +1,16 @@ -import { ProductStatus } from '../../../typings'; import Order from './Order'; +export interface ProductStatus { + sellPrice: number; + buyPrice: number; + sellVolume: number; + buyVolume: number; + sellMovingWeek: number; + buyMovingWeek: number; + sellOrders: number; + buyOrders: number; +} + /** * Product class */ diff --git a/src/structures/SkyBlock/PlayerBingo.ts b/src/structures/SkyBlock/PlayerBingo.ts index 686328e..2661dec 100644 --- a/src/structures/SkyBlock/PlayerBingo.ts +++ b/src/structures/SkyBlock/PlayerBingo.ts @@ -1,24 +1,24 @@ -import { populateGoals } from '../../utils/SkyblockUtils'; -import { PlayerBingoDataPerEvent } from '../../typings'; -import BingoData from './Static/BingoData'; +import Bingo from './Static/Bingo'; +export interface PlayerBingoDataPerEvent { + eventId: number; + points: number; + goalsCompleted: Bingo[] | string[]; +} /** * Player Bingo Class */ class PlayerBingo { dataPerEvent: PlayerBingoDataPerEvent[]; - constructor(data: Record, bingoData: BingoData | null) { + constructor(data: Record) { const events = data.success && Array.isArray(data.events) ? data.events : []; this.dataPerEvent = events.map((eventData) => { let doneGoals = eventData.completed_goals; if (!Array.isArray(doneGoals)) doneGoals = []; - const enrichable = parseInt(eventData.key, 10) === bingoData?.id; - if (enrichable) doneGoals = populateGoals(doneGoals, bingoData.goals); return { eventId: parseInt(eventData.key, 10) || 0, points: parseInt(eventData.points, 10) || 0, - goalsCompleted: doneGoals, - enrichedGoals: enrichable + goalsCompleted: doneGoals }; }); } diff --git a/src/structures/SkyBlock/SkyblockGarden.ts b/src/structures/SkyBlock/SkyblockGarden.ts index b4279b9..a96391f 100644 --- a/src/structures/SkyBlock/SkyblockGarden.ts +++ b/src/structures/SkyBlock/SkyblockGarden.ts @@ -1,11 +1,57 @@ -import { - SkyblockGardenCropMilestones, - SkyblockGardenComposter, - SkyblockGardenVisitor, - SkyblockGarenCrops, - SkyblockSkillLevel -} from '../../typings'; -import { getLevelByXp } from '../../utils/SkyblockUtils'; +import { getLevelByXp, SkyblockSkillLevel } from '../../utils/SkyblockUtils'; + +export interface SkyblockGardenVisitorServed { + total: number; + unique: number; +} +export interface SkyblockGardenVisitor { + visited: Record; + completed: Record; + served: SkyblockGardenVisitorServed; +} + +export interface SkyblockGardenComposterUpgrades { + speed: number; + multiDrop: number; + fuelCap: number; + organicMatterCap: number; + costReduction: number; +} + +export interface SkyblockGardenComposter { + organicMatter: number; + fuelUnits: number; + compostUnits: number; + compostItems: number; + conversionTicks: number; + upgrades: SkyblockGardenComposterUpgrades; +} + +export interface SkyblockGarenCrops { + wheat: number; + carrot: number; + sugarCane: number; + potato: number; + pumpkin: number; + melon: number; + cactus: number; + cocoBeans: number; + mushroom: number; + netherWart: number; +} + +export interface SkyblockGardenCropMilestones { + wheat: SkyblockSkillLevel; + carrot: SkyblockSkillLevel; + sugarCane: SkyblockSkillLevel; + potato: SkyblockSkillLevel; + pumpkin: SkyblockSkillLevel; + melon: SkyblockSkillLevel; + cactus: SkyblockSkillLevel; + cocoBeans: SkyblockSkillLevel; + mushroom: SkyblockSkillLevel; + netherWart: SkyblockSkillLevel; +} /** * Skyblock Garden class diff --git a/src/structures/SkyBlock/SkyblockInventoryItem.ts b/src/structures/SkyBlock/SkyblockInventoryItem.ts index ee99c0c..8a8ae4b 100644 --- a/src/structures/SkyBlock/SkyblockInventoryItem.ts +++ b/src/structures/SkyBlock/SkyblockInventoryItem.ts @@ -1,5 +1,5 @@ +export type SkyblockGemstoneQuality = 'Rough' | 'Flawed' | 'Fine' | 'Flawless' | 'Perfect'; import { parseGearScore, parseRarity } from '../../utils/SkyblockUtils'; -import { SkyblockGemstoneQuality } from '../../typings'; class SkyblockGemstone { type: string; diff --git a/src/structures/SkyBlock/SkyblockMember.ts b/src/structures/SkyBlock/SkyblockMember.ts index 5fdcfed..c3cb952 100644 --- a/src/structures/SkyBlock/SkyblockMember.ts +++ b/src/structures/SkyBlock/SkyblockMember.ts @@ -1,44 +1,48 @@ -import { getNetworth, NetworthResult } from 'skyhelper-networth'; import { - SkyblockMemberArmor, SkyblockMemberChocolateFactoryData, - SkyblockMemberDungeons, - SkyblockMemberEquipment, + SkyblockMemberTrophyFishRank, SkyblockMemberJacobData, - SkyblockMemberSkills, + SkyblockMemberDungeons, SkyblockMemberSlayer, + SkyblockMemberSkills, SkyblockMemberStats, - SkyblockMemberTrophyFishRank, - SkyblockSkillLevel -} from '../../typings'; -import Constants from '../../utils/Constants'; -import { - decode, - getBestiaryLevel, getChocolateFactory, - getDungeons, + SkyblockSkillLevel, + getTrophyFishRank, + getBestiaryLevel, + getMemberStats, getJacobData, getLevelByXp, - getMemberStats, + getDungeons, getPetLevel, getSkills, getSlayer, - getTrophyFishRank + decode } from '../../utils/SkyblockUtils'; -import Player from '../Player'; -import SkyblockGarden from './SkyblockGarden'; +import { getNetworth, NetworthResult } from 'skyhelper-networth'; import SkyblockInventoryItem from './SkyblockInventoryItem'; -import SkyblockMuseum from './SkyblockMuseum'; +import Constants from '../../utils/Constants'; import SkyblockPet from './SkyblockPet'; +export interface SkyblockMemberEquipment { + gauntlet: SkyblockInventoryItem | null; + belt: SkyblockInventoryItem | null; + cloak: SkyblockInventoryItem | null; + necklace: SkyblockInventoryItem | null; +} + +export interface SkyblockMemberArmor { + helmet: SkyblockInventoryItem | null; + chestplate: SkyblockInventoryItem | null; + leggings: SkyblockInventoryItem | null; + boots: SkyblockInventoryItem | null; +} + /** * Skyblock member class */ class SkyblockMember { uuid: string; - player: Player | null; - museum: SkyblockMuseum | null; - garden: SkyblockGarden | null; gameMode: string | null; selected: boolean; profileName: string; @@ -73,9 +77,6 @@ class SkyblockMember { getNetworth: () => Promise; constructor(data: Record) { this.uuid = data.uuid; - this.player = data.m.player || null; - this.museum = data.museum || null; - this.garden = data.garden || null; this.gameMode = data.gameMode; this.selected = data.selected; this.profileName = data.profileName; diff --git a/src/structures/SkyBlock/SkyblockPet.ts b/src/structures/SkyBlock/SkyblockPet.ts index b5a51d7..1dfeccf 100644 --- a/src/structures/SkyBlock/SkyblockPet.ts +++ b/src/structures/SkyBlock/SkyblockPet.ts @@ -1,4 +1,4 @@ -import { SkyblockRarity } from '../../typings'; +import { SkyblockRarity } from '../../utils/SkyblockUtils'; import Constants from '../../utils/Constants'; /** diff --git a/src/structures/SkyBlock/SkyblockProfile.ts b/src/structures/SkyBlock/SkyblockProfile.ts index 1a29adb..9826d86 100644 --- a/src/structures/SkyBlock/SkyblockProfile.ts +++ b/src/structures/SkyBlock/SkyblockProfile.ts @@ -29,7 +29,6 @@ class SkyblockProfile { m: data.members[uuid], banking: this.banking, communityUpgrades: this.communityUpgrades, - museum: null, selected: this.selected }) ); diff --git a/src/structures/Static/Achievements.ts b/src/structures/Static/Achievements.ts index e4b6356..a668472 100644 --- a/src/structures/Static/Achievements.ts +++ b/src/structures/Static/Achievements.ts @@ -1,5 +1,5 @@ -import { StaticGameNames } from '../../typings'; import GameAchievements from './GameAchievements'; +import { StaticGameNames } from '../../typings'; /** * Achievement class diff --git a/src/structures/Static/GameChallenges.ts b/src/structures/Static/GameChallenges.ts index 4ebdfd0..ff894b9 100644 --- a/src/structures/Static/GameChallenges.ts +++ b/src/structures/Static/GameChallenges.ts @@ -1,5 +1,11 @@ -import { ChallengeData, StaticGameNames } from '../../typings'; +import { StaticGameNames } from '../../typings'; +export interface ChallengeData { + id: string; + name: string; + reward: number; + rewardType: string; +} /** * Game challenges class */ diff --git a/src/structures/Static/Quest.ts b/src/structures/Static/Quest.ts index 6cf8a87..7876dbf 100644 --- a/src/structures/Static/Quest.ts +++ b/src/structures/Static/Quest.ts @@ -1,4 +1,13 @@ -import { QuestObjective, QuestReward } from '../../typings'; +export interface QuestObjective { + id: string; + type: 'Integer' | 'Boolean'; + amountNeeded: number; +} + +export interface QuestReward { + type: string; + amount: number; +} /** * Quest Class diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index 210d59f..86e537e 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -1,595 +1,3 @@ -import SkyblockInventoryItem from '../structures/SkyBlock/SkyblockInventoryItem'; -import PitInventoryItem from '../structures/MiniGames/PitInventoryItem'; -import Cache from '../Private/defaultCache'; -import Arcade from '../structures/MiniGames/Arcade'; -import ArenaBrawl from '../structures/MiniGames/ArenaBrawl'; -import BedWars from '../structures/MiniGames/BedWars'; -import BlitzSurvivalGames from '../structures/MiniGames/BlitzSurvivalGames'; -import BuildBattle from '../structures/MiniGames/BuildBattle'; -import CopsAndCrims from '../structures/MiniGames/CopsAndCrims'; -import Duels from '../structures/MiniGames/Duels'; -import MegaWalls from '../structures/MiniGames/MegaWalls'; -import MurderMystery from '../structures/MiniGames/MurderMystery'; -import Paintball from '../structures/MiniGames/Paintball'; -import Pit from '../structures/MiniGames/Pit'; -import Quakecraft from '../structures/MiniGames/Quakecraft'; -import SkyWars from '../structures/MiniGames/SkyWars'; -import SmashHeroes from '../structures/MiniGames/SmashHeroes'; -import SpeedUHC from '../structures/MiniGames/SpeedUHC'; -import TNTGames from '../structures/MiniGames/TNTGames'; -import TurboKartRacers from '../structures/MiniGames/TurboKartRacers'; -import UHC from '../structures/MiniGames/UHC'; -import VampireZ from '../structures/MiniGames/VampireZ'; -import Walls from '../structures/MiniGames/Walls'; -import Warlords from '../structures/MiniGames/Warlords'; -import WoolWars from '../structures/MiniGames/WoolWars'; - -export type ActionFilterType = 'PROFILE' | 'PLAYER' | 'AUCTION'; -export type GuildSearchParameter = 'id' | 'name' | 'player'; -export type RatelimitOptions = 'AUTO' | 'HARD' | 'NONE'; -export interface ClientOptions { - cache?: boolean; - hypixelCacheTime?: number; - mojangCacheTime?: number; - cacheHandler?: Cache; - rateLimit?: RatelimitOptions; - syncWithHeaders?: boolean; - keyLimit?: number; - cacheSize?: number; - silent?: boolean; - headers?: object; - checkForUpdates?: boolean; - useThirdPartyAPI?: boolean | string; -} - -export interface UpdateHandler { - checkForUpdates(): void; - compare(a: string, b: string): number; -} - -export interface ExpHistory { - day: string; - date: Date | undefined; - exp: number; - totalExp: number; -} - -export type GameString = - | 'Quake Craft' - | 'Walls' - | 'Paintball' - | 'Blitz Survival Games' - | 'The TNT Games' - | 'VampireZ' - | 'Mega Walls' - | 'Arcade' - | 'Arena Brawl' - | 'UHC Champions' - | 'Cops and Crims' - | 'Warlords' - | 'Smash Heroes' - | 'Turbo Kart Racers' - | 'Housing' - | 'SkyWars' - | 'Crazy Walls' - | 'Speed UHC' - | 'SkyClash' - | 'Classic Games' - | 'Prototype' - | 'Bed Wars' - | 'Murder Mystery' - | 'Build Battle' - | 'Duels' - | 'SkyBlock' - | 'The Pit' - | 'Replay' - | 'SMP' - | 'Wool Wars' - | 'Limbo' - | 'Queue' - | 'Main Lobby' - | 'Tournament Lobby' - | 'Idle'; - -export type GameCode = - | 'QUAKECRAFT' - | 'WALLS' - | 'PAINTBALL' - | 'SURVIVAL_GAMES' - | 'TNTGAMES' - | 'VAMPIREZ' - | 'WALLS3' - | 'ARCADE' - | 'ARENA' - | 'UHC' - | 'MCGO' - | 'BATTLEGROUND' - | 'SUPER_SMASH' - | 'GINGERBREAD' - | 'HOUSING' - | 'SKYWARS' - | 'TRUE_COMBAT' - | 'SPEED_UHC' - | 'SKYCLASH' - | 'LEGACY' - | 'PROTOTYPE' - | 'BEDWARS' - | 'MURDER_MYSTERY' - | 'BUILD_BATTLE' - | 'DUELS' - | 'SKYBLOCK' - | 'PIT' - | 'REPLAY' - | 'SMP' - | 'WOOL_GAMES' - | 'LIMBO' - | 'QUEUE' - | 'MAIN_LOBBY' - | 'TOURNAMENT_LOBBY' - | 'IDLE'; - -export type GameID = - | 2 - | 3 - | 4 - | 5 - | 6 - | 7 - | 13 - | 14 - | 17 - | 20 - | 21 - | 23 - | 24 - | 25 - | 26 - | 51 - | 52 - | 54 - | 55 - | 56 - | 57 - | 58 - | 59 - | 60 - | 61 - | 63 - | 64 - | 65 - | 67 - | 68 - | -2 - | -3 - | -4 - | -5 - | -6; - -export interface LevelProgress { - xpToNext: number; - remainingXP: number; - currentXP: number; - percent: number; - percentRemaining: number; -} - -export interface PlayerSocialMedia { - name: string; - link: string; - id: string; -} - -export interface SkyblockSkillLevel { - xp: number; - level: number; - maxLevel: number; - xpCurrent: number; - xpForNext: number; - progress: number; - cosmetic: boolean; -} -export interface SkyblockMemberSkills { - combat: SkyblockSkillLevel; - farming: SkyblockSkillLevel; - fishing: SkyblockSkillLevel; - mining: SkyblockSkillLevel; - foraging: SkyblockSkillLevel; - enchanting: SkyblockSkillLevel; - alchemy: SkyblockSkillLevel; - carpentry: SkyblockSkillLevel; - runecrafting: SkyblockSkillLevel; - taming: SkyblockSkillLevel; - social: SkyblockSkillLevel; - average: number; -} - -export interface SkyblockMemberSlayerLevel { - xp: number; - tier1: number; - tier2: number; - tier3: number; - tier4: number; - tier5: number; - level: number; -} - -export interface SkyblockMemberSlayer { - zombie: SkyblockMemberSlayerLevel; - spider: SkyblockMemberSlayerLevel; - wolf: SkyblockMemberSlayerLevel; - enderman: SkyblockMemberSlayerLevel; - blaze: SkyblockMemberSlayerLevel; - vampire: SkyblockMemberSlayerLevel; -} - -export interface SkyblockMemberDungeonsTypes { - catacombs: SkyblockSkillLevel; -} - -export interface SkyblockMemberDungeonsClasses { - healer: SkyblockSkillLevel; - mage: SkyblockSkillLevel; - berserk: SkyblockSkillLevel; - archer: SkyblockSkillLevel; - tank: SkyblockSkillLevel; -} - -export interface SkyblockMemberDungeons { - types: SkyblockMemberDungeonsTypes; - classes: SkyblockMemberDungeonsClasses; -} - -export interface SkyblockMemberJacobDataMedals { - gold: number; - silver: number; - bronze: number; -} - -export interface SkyblockMemberJacobDataPerks { - doubleDrops: number; - farmingLevelCap: number; - personalBests: boolean; -} - -export interface SkyblockMemberJacobData { - medals: SkyblockMemberJacobDataMedals; - perks: SkyblockMemberJacobDataPerks; - contests: Record; -} - -export interface SkyblockMemberChocolateFactoryDataEmployees { - bro: number; - cousin: number; - sis: number; - father: number; - grandma: number; - dog: number; - uncle: number; -} - -export interface SkyblockMemberChocolateFactoryDataChocolate { - current: number; - total: number; - sincePrestige: number; -} - -export interface SkyblockMemberChocolateFactoryDataTimeTower { - charges: number; - level: number; -} - -export interface SkyblockMemberChocolateFactoryDataUpgrades { - click: number; - multiplier: number; - rabbitRarity: number; -} - -export interface SkyblockMemberChocolateFactoryDataGoldenClick { - amount: number; - year: number; -} - -export interface SkyblockMemberChocolateFactoryData { - employees: SkyblockMemberChocolateFactoryDataEmployees; - chocolate: SkyblockMemberChocolateFactoryDataChocolate; - timeTower: SkyblockMemberChocolateFactoryDataTimeTower; - upgrades: SkyblockMemberChocolateFactoryDataUpgrades; - goldenClick: SkyblockMemberChocolateFactoryDataGoldenClick; - barnCapacity: number; - prestige: number; -} - -export interface PlayerInfo { - max: number; - online: number; - players: any[]; - toString(): string; -} - -export type PlayerRank = 'VIP' | 'VIP+' | 'MVP' | 'MVP+' | 'MVP++' | 'Game Master' | 'Admin' | 'YouTube'; - -export interface RanksPurchaseTime { - VIP: Date | null; - VIP_PLUS: Date | null; - MVP: Date | null; - MVP_PLUS: Date | null; -} - -export interface PetConsumables { - BAKED_POTATO: number; - COOKIE: number; - FEATHER: number; - HAY_BLOCK: number; - SLIME_BALL: number; - COOKED_BEEF: number; - RED_ROSE: number; - WATER_BUCKET: number; - MELON: number; - STICK: number; - WOOD_SWORD: number; - MILK_BUCKET: number; - GOLD_RECORD: number; - LEASH: number; - LAVA_BUCKET: number; - BONE: number; - MAGMA_CREAM: number; - WHEAT: number; - MUSHROOM_SOUP: number; - BREAD: number; - PUMPKIN_PIE: number; - APPLE: number; - CARROT_ITEM: number; - RAW_FISH: number; - PORK: number; - CAKE: number; - ROTTEN_FLESH: number; -} - -export type BedWarsPrestige = - | 'Stone' - | 'Iron' - | 'Gold' - | 'Diamond' - | 'Emerald' - | 'Sapphire' - | 'Ruby' - | 'Crystal' - | 'Opal' - | 'Amethyst' - | 'Rainbow' - | 'Iron Prime' - | 'Gold Prime' - | 'Diamond Prime' - | 'Emerald Prime' - | 'Sapphire Prime' - | 'Ruby Prime' - | 'Crystal Prime' - | 'Opal Prime' - | 'Amethyst Prime' - | 'Mirror' - | 'Light' - | 'Dawn' - | 'Dusk' - | 'Air' - | 'Wind' - | 'Nebula' - | 'Thunder' - | 'Earth' - | 'Water' - | 'Fire' - | 'Sunrise' - | 'Eclipse' - | 'Gamma' - | 'Majestic' - | 'Andesine' - | 'Marine' - | 'Element' - | 'Galaxy' - | 'Atomic' - | 'Sunset' - | 'Time' - | 'Winter' - | 'Obsidian' - | 'Spring' - | 'Ice' - | 'Summer' - | 'Spinel' - | 'Autumn' - | 'Mystic' - | 'Eternal'; - -export interface BedWarsCollectedItems { - iron: number; - gold: number; - diamond: number; - emerald: number; -} - -export interface BedWarsAvg { - kills: number; - finalKills: number; - bedsBroken: number; -} - -export interface BedWarsBeds { - lost: number; - broken: number; - BLRatio: number; -} - -export interface BedWarsModeStats { - winstreak: number; - playedGames: number; - kills: number; - deaths: number; - wins: number; - losses: number; - finalKills: number; - finalDeaths: number; - beds: BedWarsBeds; - avg: BedWarsAvg; - KDRatio: number; - WLRatio: number; - finalKDRatio: number; -} -export interface BedwarsDreamModeStats { - doubles: BedWarsModeStats; - fours: BedWarsModeStats; -} - -export interface BedwarsDreamStats { - ultimate: BedwarsDreamModeStats; - rush: BedwarsDreamModeStats; - armed: BedwarsDreamModeStats; - lucky: BedwarsDreamModeStats; - voidless: BedwarsDreamModeStats; -} - -export interface BedWarsPracticeAttempts { - failed: number; - successful: number; - total: number; -} - -export interface BedWarsPracticeElevation { - straight: number; - diagonal: number; -} - -export interface BedWarsPracticeElevations { - none: BedWarsPracticeElevation; - slight: BedWarsPracticeElevation; - staircase: BedWarsPracticeElevation; -} - -export interface BedWarsPracticeRecord { - elevation: BedWarsPracticeElevations; -} - -export interface BedWarsPracticeRecords { - blocks30: BedWarsPracticeRecord; - blocks50: BedWarsPracticeRecord; - blocks100: BedWarsPracticeRecord; -} - -export interface BedWarsPracticeBridging { - blocksPlaced: number; - attempts: BedWarsPracticeAttempts; - records: BedWarsPracticeRecords; -} - -export interface BedWarsPracticePearlClutching { - attempts: BedWarsPracticeAttempts; -} - -export interface BedWarsPracticeBase { - blocksPlaced: number; - attempts: BedWarsPracticeAttempts; -} - -export interface BedWarsPracticeStats { - selected: string; - bridging: BedWarsPracticeBridging; - fireballJumping: BedWarsPracticeBase; - pearlClutching: BedWarsPracticePearlClutching; - mlg: BedWarsPracticeBase; -} - -export interface BuildBattleWins { - solo: number; - teams: number; - pro: number; - gtb: number; -} - -export interface PitArmor { - helmet: PitInventoryItem | null; - chestplate: PitInventoryItem | null; - leggings: PitInventoryItem | null; - boots: PitInventoryItem | null; -} - -export type SkyWarsPrestige = - | 'Iron' - | 'Gold' - | 'Diamond' - | 'Emerald' - | 'Sapphire' - | 'Ruby' - | 'Crystal' - | 'Opal' - | 'Amethyst' - | 'Rainbow' - | 'Mythic'; - -export type SkyWarsPrestigeIcons = - | '⋆' - | '★' - | '☆' - | '⁕' - | '✶' - | '✳' - | '✴' - | '✷' - | '❋' - | '✼' - | '❂' - | '❁' - | '☬' - | '✙' - | '❤️' - | '☠' - | '✦' - | '✌' - | '❦' - | '✵' - | '❣' - | '☯' - | '✺' - | 'ಠ_ಠ' - | '⚔'; - -export interface WoolWarsStats { - wins: number; - gamesPlayed: number; - woolsPlaced: number; - blocksBroken: number; - placeBreakRatio: number; - kills: number; - deaths: number; - KDRatio: number; - assists: number; - powerups: number; -} - -export interface WoolWarsPrivateGamesConfig { - one_hit_one_kil: boolean; - rainbow_wool: 'Enabled' | 'Disabled'; - health_buff: string; - game_speed: string; - speed: string; - no_class: 'Enabled' | 'Disabled'; - respawn_enable: boolean; -} - -export interface QuestObjective { - id: string; - type: 'Integer' | 'Boolean'; - amountNeeded: number; -} - -export interface QuestReward { - type: string; - amount: number; -} - -export interface ChallengeData { - id: string; - name: string; - reward: number; - rewardType: string; -} - export type StaticGameNames = | 'arcade' | 'arena' @@ -614,139 +22,3 @@ export type StaticGameNames = | 'walls' | 'battleground' | 'woolgames'; - -export type SkyblockGemstoneQuality = 'Rough' | 'Flawed' | 'Fine' | 'Flawless' | 'Perfect'; - -export type SkyblockRarity = - | 'COMMON' - | 'UNCOMMON' - | 'RARE' - | 'EPIC' - | 'LEGENDARY' - | 'MYTHIC' - | 'DIVINE' - | 'SPECIAL' - | 'VERY_SPECIAL'; - -export interface SkyblockGardenVisitorServed { - total: number; - unique: number; -} -export interface SkyblockGardenVisitor { - visited: Record; - completed: Record; - served: SkyblockGardenVisitorServed; -} - -export interface SkyblockGardenComposterUpgrades { - speed: number; - multiDrop: number; - fuelCap: number; - organicMatterCap: number; - costReduction: number; -} - -export interface SkyblockGardenComposter { - organicMatter: number; - fuelUnits: number; - compostUnits: number; - compostItems: number; - conversionTicks: number; - upgrades: SkyblockGardenComposterUpgrades; -} - -export interface SkyblockGarenCrops { - wheat: number; - carrot: number; - sugarCane: number; - potato: number; - pumpkin: number; - melon: number; - cactus: number; - cocoBeans: number; - mushroom: number; - netherWart: number; -} - -export interface SkyblockGardenCropMilestones { - wheat: SkyblockSkillLevel; - carrot: SkyblockSkillLevel; - sugarCane: SkyblockSkillLevel; - potato: SkyblockSkillLevel; - pumpkin: SkyblockSkillLevel; - melon: SkyblockSkillLevel; - cactus: SkyblockSkillLevel; - cocoBeans: SkyblockSkillLevel; - mushroom: SkyblockSkillLevel; - netherWart: SkyblockSkillLevel; -} - -export type SkyblockMemberTrophyFishRank = 'Bronze' | 'Silver' | 'Gold' | 'Diamond'; - -export interface SkyblockMemberEquipment { - gauntlet: SkyblockInventoryItem | null; - belt: SkyblockInventoryItem | null; - cloak: SkyblockInventoryItem | null; - necklace: SkyblockInventoryItem | null; -} - -export interface SkyblockMemberArmor { - helmet: SkyblockInventoryItem | null; - chestplate: SkyblockInventoryItem | null; - leggings: SkyblockInventoryItem | null; - boots: SkyblockInventoryItem | null; -} - -export interface SkyblockMemberStats { - kills: Record; - deaths: Record; -} - -export interface PlayerBingoDataPerEvent { - eventId: number; - points: number; - enrichedGoals: boolean; - goalsCompleted: Bingo[] | string[]; -} - -export interface ProductStatus { - sellPrice: number; - buyPrice: number; - sellVolume: number; - buyVolume: number; - sellMovingWeek: number; - buyMovingWeek: number; - sellOrders: number; - buyOrders: number; -} - -export interface PlayerStats { - arcade: Arcade; - arena: ArenaBrawl; - bedwars: BedWars; - blitzsg: BlitzSurvivalGames; - buildbattle: BuildBattle; - copsandcrims: CopsAndCrims; - duels: Duels; - megawalls: MegaWalls; - murdermystery: MurderMystery; - paintball: Paintball; - pit: Pit; - quakecraft: Quakecraft; - skywars: SkyWars; - smashheroes: SmashHeroes; - speeduhc: SpeedUHC; - tntgames: TNTGames; - turbokartracers: TurboKartRacers; - uhc: UHC; - vampirez: VampireZ; - walls: Walls; - warlords: Warlords; - woolwars: WoolWars; -} - -export interface RLOptions { - keyLimit: number; - ratelimit: RatelimitOptions; - syncWithHeaders: boolean; -} diff --git a/src/utils/Guild.ts b/src/utils/Guild.ts index a90d60f..995870c 100644 --- a/src/utils/Guild.ts +++ b/src/utils/Guild.ts @@ -1,6 +1,12 @@ import GuildMember from '../structures/Guild/GuildMember'; import GuildRank from '../structures/Guild/GuildRank'; -import { ExpHistory } from '../typings'; + +export interface ExpHistory { + day: string; + date: Date | undefined; + exp: number; + totalExp: number; +} const dateRegExp = /(\d{4})-(\d{2})-(\d{2})/; diff --git a/src/utils/Player.ts b/src/utils/Player.ts index 2d7f5e1..ad46ce1 100644 --- a/src/utils/Player.ts +++ b/src/utils/Player.ts @@ -1,4 +1,4 @@ -import { LevelProgress, PlayerRank, PlayerSocialMedia } from '../typings'; +import { LevelProgress, PlayerRank, PlayerSocialMedia } from '../structures/Player'; export function getRank(player: Record): PlayerRank { let rank; diff --git a/src/utils/SkyblockUtils.ts b/src/utils/SkyblockUtils.ts index deecb95..4a21cea 100644 --- a/src/utils/SkyblockUtils.ts +++ b/src/utils/SkyblockUtils.ts @@ -1,19 +1,144 @@ -import { promisify } from 'util'; -import { - SkyblockMemberChocolateFactoryData, - SkyblockMemberTrophyFishRank, - SkyblockMemberSlayerLevel, - SkyblockMemberJacobData, - SkyblockMemberDungeons, - SkyblockMemberSkills, - SkyblockMemberSlayer, - SkyblockSkillLevel, - SkyblockRarity, - SkyblockMemberStats -} from '../typings'; import Constants from './Constants'; +import { promisify } from 'util'; import nbt from 'prismarine-nbt'; +export type SkyblockRarity = + | 'COMMON' + | 'UNCOMMON' + | 'RARE' + | 'EPIC' + | 'LEGENDARY' + | 'MYTHIC' + | 'DIVINE' + | 'SPECIAL' + | 'VERY_SPECIAL'; + +export interface SkyblockMemberJacobDataMedals { + gold: number; + silver: number; + bronze: number; +} + +export interface SkyblockMemberJacobDataPerks { + doubleDrops: number; + farmingLevelCap: number; + personalBests: boolean; +} + +export interface SkyblockMemberJacobData { + medals: SkyblockMemberJacobDataMedals; + perks: SkyblockMemberJacobDataPerks; + contests: Record; +} + +export interface SkyblockMemberChocolateFactoryDataEmployees { + bro: number; + cousin: number; + sis: number; + father: number; + grandma: number; + dog: number; + uncle: number; +} + +export interface SkyblockMemberChocolateFactoryDataChocolate { + current: number; + total: number; + sincePrestige: number; +} + +export interface SkyblockMemberChocolateFactoryDataTimeTower { + charges: number; + level: number; +} + +export interface SkyblockMemberChocolateFactoryDataUpgrades { + click: number; + multiplier: number; + rabbitRarity: number; +} + +export interface SkyblockMemberChocolateFactoryDataGoldenClick { + amount: number; + year: number; +} + +export interface SkyblockMemberChocolateFactoryData { + employees: SkyblockMemberChocolateFactoryDataEmployees; + chocolate: SkyblockMemberChocolateFactoryDataChocolate; + timeTower: SkyblockMemberChocolateFactoryDataTimeTower; + upgrades: SkyblockMemberChocolateFactoryDataUpgrades; + goldenClick: SkyblockMemberChocolateFactoryDataGoldenClick; + barnCapacity: number; + prestige: number; +} + +export interface SkyblockMemberSlayerLevel { + xp: number; + tier1: number; + tier2: number; + tier3: number; + tier4: number; + tier5: number; + level: number; +} + +export interface SkyblockMemberSlayer { + zombie: SkyblockMemberSlayerLevel; + spider: SkyblockMemberSlayerLevel; + wolf: SkyblockMemberSlayerLevel; + enderman: SkyblockMemberSlayerLevel; + blaze: SkyblockMemberSlayerLevel; + vampire: SkyblockMemberSlayerLevel; +} +export type SkyblockMemberTrophyFishRank = 'Bronze' | 'Silver' | 'Gold' | 'Diamond'; +export interface SkyblockSkillLevel { + xp: number; + level: number; + maxLevel: number; + xpCurrent: number; + xpForNext: number; + progress: number; + cosmetic: boolean; +} + +export interface SkyblockMemberStats { + kills: Record; + deaths: Record; +} + +export interface SkyblockMemberSkills { + combat: SkyblockSkillLevel; + farming: SkyblockSkillLevel; + fishing: SkyblockSkillLevel; + mining: SkyblockSkillLevel; + foraging: SkyblockSkillLevel; + enchanting: SkyblockSkillLevel; + alchemy: SkyblockSkillLevel; + carpentry: SkyblockSkillLevel; + runecrafting: SkyblockSkillLevel; + taming: SkyblockSkillLevel; + social: SkyblockSkillLevel; + average: number; +} + +export interface SkyblockMemberDungeonsTypes { + catacombs: SkyblockSkillLevel; +} + +export interface SkyblockMemberDungeonsClasses { + healer: SkyblockSkillLevel; + mage: SkyblockSkillLevel; + berserk: SkyblockSkillLevel; + archer: SkyblockSkillLevel; + tank: SkyblockSkillLevel; +} + +export interface SkyblockMemberDungeons { + types: SkyblockMemberDungeonsTypes; + classes: SkyblockMemberDungeonsClasses; +} + export async function decode(base64: string | Buffer, isBuffer = false): Promise { const parseNbt = promisify(nbt.parse); const buffer = isBuffer ? base64 : Buffer.from(String(base64), 'base64'); diff --git a/src/utils/toUuid.ts b/src/utils/toUuid.ts index 3a141d5..6c47949 100644 --- a/src/utils/toUuid.ts +++ b/src/utils/toUuid.ts @@ -2,7 +2,7 @@ import fetch from '../Private/uuidCache'; import Errors from '../Errors'; import isUUID from './isUUID'; -export default async function (input: string, cacheTime: number = 600, useThirdPartyAPI: string = '') { +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 (isUUID(input)) return input.replace(/-/g, ''); @@ -15,10 +15,9 @@ export default async function (input: string, cacheTime: number = 600, useThirdP } 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); return res.id; - } catch { - // 2nd Try - if (!useThirdPartyAPI) return module.exports(input, cacheTime, true); + } catch (e) { throw new Error(Errors.PLAYER_DOES_NOT_EXIST); } } diff --git a/tsconfig.json b/tsconfig.json index 3c0e09a..50c8036 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,12 @@ "esModuleInterop": true, "skipLibCheck": true, "outDir": "./build", + "module": "ES2022", "target": "ES2022", "strict": true - } -} + }, + "include": [ + "src", + "API" + ], +} \ No newline at end of file