hypixel-api-reborn 9.0.3 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/API/getAPIStatus.js +2 -1
  4. package/src/API/getBoosters.js +1 -0
  5. package/src/API/getFriends.js +1 -0
  6. package/src/API/getGameCounts.js +1 -0
  7. package/src/API/getGuild.js +1 -0
  8. package/src/API/getKeyInfo.js +1 -0
  9. package/src/API/getLeaderboards.js +1 -0
  10. package/src/API/getPlayer.js +2 -1
  11. package/src/API/getRankedSkyWars.js +1 -0
  12. package/src/API/getRecentGames.js +1 -0
  13. package/src/API/getStatus.js +1 -0
  14. package/src/API/getWatchdogStats.js +1 -0
  15. package/src/API/index.js +23 -9
  16. package/src/API/skyblock/getEndedSkyblockAuctions.js +1 -0
  17. package/src/API/skyblock/getSkyblockAuctionsByPlayer.js +1 -0
  18. package/src/API/skyblock/getSkyblockBazaar.js +1 -0
  19. package/src/API/skyblock/getSkyblockMember.js +1 -0
  20. package/src/API/skyblock/getSkyblockNews.js +1 -0
  21. package/src/API/skyblock/getSkyblockProfiles.js +1 -0
  22. package/src/Client.js +34 -14
  23. package/src/Errors.js +2 -1
  24. package/src/Private/defaultCache.js +78 -0
  25. package/src/Private/requests.js +24 -9
  26. package/src/Private/updater.js +4 -1
  27. package/src/Private/validate.js +3 -3
  28. package/src/structures/MiniGames/BedWars.js +22 -0
  29. package/src/structures/MiniGames/Duels.js +216 -46
  30. package/src/structures/MiniGames/TurboKartRacers.js +105 -0
  31. package/src/structures/Player.js +4 -8
  32. package/src/structures/ServerInfo.js +1 -1
  33. package/src/structures/SkyBlock/News/SkyblockNews.js +4 -4
  34. package/src/structures/SkyBlock/SkyblockInventoryItem.js +29 -1
  35. package/src/structures/SkyBlock/SkyblockMember.js +25 -13
  36. package/src/utils/Constants.js +14 -0
  37. package/src/utils/index.js +13 -9
  38. package/src/utils/rgbToHexColor.js +8 -0
  39. package/src/utils/romanize.js +13 -0
  40. package/typings/index.d.ts +375 -356
package/README.md CHANGED
@@ -47,7 +47,7 @@ hypixel.getGuild('name', 'The Foundation').then(guild => {
47
47
  ```
48
48
  For more examples go to our [documentation](https://hypixel.stavzdev.me/).
49
49
  ## Changelog
50
- [v9.0.3](https://github.com/Hypixel-API-Reborn/hypixel-api-reborn/releases/tag/9.0.3)
50
+ [v10.0.0](https://github.com/Hypixel-API-Reborn/hypixel-api-reborn/releases/tag/10.0.0)
51
51
 
52
52
  ### Try it now
53
53
  **[Code Sandbox](https://codesandbox.io/s/clever-babbage-xqmfw?file=/src/index.js)**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypixel-api-reborn",
3
- "version": "9.0.3",
3
+ "version": "10.0.0",
4
4
  "description": "Feature-rich Hypixel API wrapper for Node.js",
5
5
  "main": "./src/index.js",
6
6
  "types": "./typings/index.d.ts",
@@ -1,7 +1,8 @@
1
1
  const Rss = require('rss-parser');
2
2
  const Parser = new Rss();
3
- module.exports = async function () {
3
+ module.exports = async function (options) {
4
4
  const Status = require('../structures/APIStatus.js');
5
5
  const parsed = await Parser.parseURL('https://status.hypixel.net/history.rss');
6
+ if (options.raw) return parsed;
6
7
  return new Status(parsed);
7
8
  };
@@ -1,5 +1,6 @@
1
1
  module.exports = async function () {
2
2
  const Booster = require('../structures/Boosters/Booster');
3
3
  const res = await this._makeRequest('/boosters');
4
+ if (res.raw) return res;
4
5
  return res.boosters.length ? res.boosters.map((b) => new Booster(b)).reverse() : [];
5
6
  };
@@ -5,6 +5,7 @@ module.exports = async function (query) {
5
5
  const Friend = require('../structures/Friend');
6
6
  query = await toUuid(query);
7
7
  const res = await this._makeRequest(`/friends?uuid=${query}`);
8
+ if (res.raw) return res;
8
9
  if (res.records.length && res.records.length > 0) {
9
10
  return res.records.map((f) => new Friend(f, query));
10
11
  } else {
@@ -1,5 +1,6 @@
1
1
  const GameCounts = require('../structures/GameCounts');
2
2
  module.exports = async function () {
3
3
  const res = await this._makeRequest('/counts');
4
+ if (res.raw) return res;
4
5
  return new GameCounts(res);
5
6
  };
@@ -9,6 +9,7 @@ module.exports = async function (searchParameter, query) {
9
9
  if (isPlayerQuery) query = await toUuid(query);
10
10
  if (!['id', 'name', 'player'].includes(searchParameter)) throw new Error(Errors.INVALID_GUILD_SEARCH_PARAMETER);
11
11
  const res = await this._makeRequest(`/guild?${searchParameter}=${encodeURI(query)}`);
12
+ if (res.raw) return res;
12
13
  if (!res.guild && searchParameter !== 'player') {
13
14
  throw new Error(Errors.GUILD_DOES_NOT_EXIST);
14
15
  }
@@ -2,6 +2,7 @@ const Errors = require('../Errors');
2
2
  module.exports = async function () {
3
3
  const KeyInfo = require('../structures/KeyInfo');
4
4
  const res = await this._makeRequest('/key');
5
+ if (res.raw) return res;
5
6
  if (!res.success) {
6
7
  throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.cause));
7
8
  }
@@ -2,6 +2,7 @@ const Errors = require('../Errors');
2
2
  module.exports = async function () {
3
3
  const Leaderboard = require('../structures/Leaderboard');
4
4
  const res = await this._makeRequest('/leaderboards');
5
+ if (res.raw) return res;
5
6
  if (!res.leaderboards) throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, 'Try again.'));
6
7
  const lbnames = Object.create(require('../utils/Constants').leaderboardNames);
7
8
  // eslint-disable-next-line guard-for-in
@@ -8,6 +8,7 @@ module.exports = async function (query, options = { guild: false, recentGames: f
8
8
  const Player = require('../structures/Player');
9
9
  query = await toUuid(query);
10
10
  const res = await this._makeRequest(`/player?uuid=${query}`);
11
+ if (res.raw) return res;
11
12
  if (query && !res.player) throw new Error(Errors.PLAYER_HAS_NEVER_LOGGED);
12
13
  let guild = null;
13
14
  let recentGames = null;
@@ -22,5 +23,5 @@ module.exports = async function (query, options = { guild: false, recentGames: f
22
23
  rankedSW = getRankedSkyWars.call(this, query);
23
24
  }
24
25
  [guild, recentGames, rankedSW] = await Promise.all([guild, recentGames, rankedSW]);
25
- return new Player(res.player, {guild, recentGames, rankedSW});
26
+ return new Player(res.player, { guild, recentGames, rankedSW });
26
27
  };
@@ -5,6 +5,7 @@ module.exports = async function (query) {
5
5
  const SkyWarsRanked = require('../structures/MiniGames/SkyWarsRanked');
6
6
  query = await toUuid(query);
7
7
  const res = await this._makeRequest(`/player/ranked/skywars?uuid=${query}`);
8
+ if (res.raw) return res;
8
9
  if (!res.result) return null;
9
10
  return new SkyWarsRanked(res.result);
10
11
  };
@@ -8,6 +8,7 @@ module.exports = async function (query, playerData) {
8
8
  query = await toUuid(query);
9
9
 
10
10
  const res = await this._makeRequest(`/recentgames?uuid=${query}`);
11
+ if (res.raw) return res;
11
12
  if (res.games === []) {
12
13
  if (!playerData) throw new Error(Errors.PLAYER_IS_INACTIVE);
13
14
  if (Date.now() - playerData.lastLogoutTimestamp < day3) throw new Error(Errors.PLAYER_DISABLED_ENDPOINT);
@@ -3,5 +3,6 @@ module.exports = async function (query) {
3
3
  const Status = require('../structures/Status');
4
4
  query = await toUuid(query);
5
5
  const res = await this._makeRequest(`/status?uuid=${query}`);
6
+ if (res.raw) return res;
6
7
  return new Status(res.session);
7
8
  };
@@ -1,5 +1,6 @@
1
1
  module.exports = async function () {
2
2
  const WatchdogStats = require('../structures/Watchdog/Stats');
3
3
  const res = await this._makeRequest('/punishmentstats');
4
+ if (res.raw) return res;
4
5
  return new WatchdogStats(res);
5
6
  };
package/src/API/index.js CHANGED
@@ -1,9 +1,23 @@
1
- /* eslint-disable no-extend-native */
2
- const fs = require('fs');
3
- // eslint-disable-next-line no-path-concat
4
- const curDir = __dirname + '/';
5
- module.exports = Array.from(fs.readdirSync(curDir, { withFileTypes: true }))
6
- .filter((x) => x.name !== 'index.js')
7
- .map((x) => x.isDirectory() ? Array.from(fs.readdirSync(curDir + x.name)).map((y) => ([y.split('.')[0], x.name + '/' + y])) : [[x.name.split('.')[0], x.name]])
8
- .flat(1)
9
- .reduce((pV, cV) => Object.assign(pV, { [cV[0]]: require(curDir + cV[1]) }), {});
1
+ module.exports = {
2
+ getAPIStatus: require('./getAPIStatus'),
3
+ getBoosters: require('./getBoosters'),
4
+ getFriends: require('./getFriends'),
5
+ getGameCounts: require('./getGameCounts'),
6
+ getGuild: require('./getGuild'),
7
+ getKeyInfo: require('./getKeyInfo'),
8
+ getLeaderboards: require('./getLeaderboards'),
9
+ getPlayer: require('./getPlayer'),
10
+ getRankedSkyWars: require('./getRankedSkyWars'),
11
+ getRecentGames: require('./getRecentGames'),
12
+ getServerInfo: require('./getServerInfo'),
13
+ getStatus: require('./getStatus'),
14
+ getWatchdogStats: require('./getWatchdogStats'),
15
+
16
+ getEndedSkyblockAuctions: require('./skyblock/getEndedSkyblockAuctions'),
17
+ getSkyblockAuctions: require('./skyblock/getSkyblockAuctions'),
18
+ getSkyblockAuctionsByPlayer: require('./skyblock/getSkyblockAuctionsByPlayer'),
19
+ getSkyblockBazaar: require('./skyblock/getSkyblockBazaar'),
20
+ getSkyblockMember: require('./skyblock/getSkyblockMember'),
21
+ getSkyblockNews: require('./skyblock/getSkyblockNews'),
22
+ getSkyblockProfiles: require('./skyblock/getSkyblockProfiles')
23
+ };
@@ -2,6 +2,7 @@ const PartialAuction = require('../../structures/SkyBlock/Auctions/PartialAuctio
2
2
  const AuctionInfo = require('../../structures/SkyBlock/Auctions/AuctionInfo');
3
3
  module.exports = async function (includeItemBytes = false) {
4
4
  const res = await this._makeRequest('/skyblock/auctions_ended', false);
5
+ if (res.raw) return res;
5
6
  return {
6
7
  info: new AuctionInfo({ ...res, totalAuctions: res.auctions.length, totalPages: 1 }),
7
8
  auctions: res.auctions.length ? res.auctions.map((a) => new PartialAuction(a, includeItemBytes)) : []
@@ -5,6 +5,7 @@ module.exports = async function (query, includeItemBytes = false) {
5
5
  const Auction = require('../../structures/SkyBlock/Auctions/Auction');
6
6
  query = await toUuid(query);
7
7
  const res = await this._makeRequest(`/skyblock/auction?player=${query}`);
8
+ if (res.raw) return res;
8
9
 
9
10
  return res.auctions.length ? res.auctions.map((a) => new Auction(a, includeItemBytes)) : [];
10
11
  };
@@ -2,6 +2,7 @@ module.exports = async function () {
2
2
  const Product = require('../../structures/SkyBlock/Bazzar/Product');
3
3
 
4
4
  const res = await this._makeRequest('/skyblock/bazaar');
5
+ if (res.raw) return res;
5
6
 
6
7
  const productsKeys = Object.keys(res.products);
7
8
 
@@ -6,6 +6,7 @@ module.exports = async function (query, options = { fetchPlayer: false }) {
6
6
  if (!query) throw new Error(Errors.NO_NICKNAME_UUID);
7
7
  query = await toUuid(query);
8
8
  const res = await this._makeRequest(`/skyblock/profiles?uuid=${query}`);
9
+ if (res.raw) return res;
9
10
  if (!res.profiles || !res.profiles.length) {
10
11
  return new Map();
11
12
  }
@@ -1,5 +1,6 @@
1
1
  const SkyblockNews = require('../../structures/SkyBlock/News/SkyblockNews');
2
2
  module.exports = async function () {
3
3
  const res = await this._makeRequest('/skyblock/news');
4
+ if (res.raw) return res;
4
5
  return res.items.map((i) => new SkyblockNews(i));
5
6
  };
@@ -6,6 +6,7 @@ module.exports = async function (query, options = { fetchPlayer: false }) {
6
6
  if (!query) throw new Error(Errors.NO_NICKNAME_UUID);
7
7
  query = await toUuid(query);
8
8
  const res = await this._makeRequest(`/skyblock/profiles?uuid=${query}`);
9
+ if (res.raw) return res;
9
10
 
10
11
  if (!res.profiles || !res.profiles.length) {
11
12
  return [];
package/src/Client.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable max-len */
3
3
  const validate = new (require('./Private/validate'))();
4
4
  const rateLimit = new (require('./Private/rateLimit'))();
5
- const requests = new (require('./Private/requests'))();
5
+ const Requests = require('./Private/requests');
6
6
  const updater = new (require('./Private/updater'))();
7
7
  const Errors = require('./Errors');
8
8
  const API = require('./API/index');
@@ -18,6 +18,7 @@ class Client extends EventEmitter {
18
18
  */
19
19
  constructor (key, options = {}) {
20
20
  super();
21
+ this.requests = new Requests(this, options.cacheHandler);
21
22
  // eslint-disable-next-line no-console
22
23
  if (options && !options.silent) this.on('warn', console.warn);
23
24
  // Test to check for multiple instances of client
@@ -29,18 +30,27 @@ class Client extends EventEmitter {
29
30
  this.key = validate.validateKey(key);
30
31
  this.options = validate.parseOptions(options);
31
32
  validate.validateOptions(this.options);
32
- // eslint-disable-next-line no-return-assign
33
- Object.keys(API).forEach((func) => Client.prototype[func] = function (...args) {
34
- return API[func].apply({ _makeRequest: this._makeRequest.bind(this, { ...(validate.cacheSuboptions(args[args.length - 1]) ? args[args.length - 1] : {}) }), ...this }, args);
35
- });
36
- if (this.options.checkForUpdates) {
37
- updater.checkForUpdates();
33
+ // eslint-disable-next-line guard-for-in
34
+ for (const func in API) {
35
+ Client.prototype[func] = function (...args) {
36
+ const lastArg = args[args.length - 1];
37
+ return API[func].apply(
38
+ {
39
+ _makeRequest: this._makeRequest.bind(this, { ...(validate.cacheSuboptions(lastArg) ? lastArg : {}) }),
40
+ ...this
41
+ },
42
+ args);
43
+ };
44
+
45
+ if (this.options.checkForUpdates) {
46
+ updater.checkForUpdates();
47
+ }
38
48
  }
39
49
  /**
40
50
  * All cache entries
41
51
  * @type {Map<string,object>}
42
52
  */
43
- this.cache = requests.cache;
53
+ this.cache = this.requests.cache;
44
54
  clients.push(this);
45
55
  rateLimit.init(this.getKeyInfo(), this.options, this).then(() => this.emit('ready'));
46
56
  }
@@ -54,10 +64,10 @@ class Client extends EventEmitter {
54
64
  */
55
65
  async _makeRequest (options, url, useRateLimitManager = true) {
56
66
  if (!url) return;
57
- if (url !== '/key' && !options.noCacheCheck && requests.cache.has(url)) return requests.cache.get(url);
67
+ if (url !== '/key' && !options.noCacheCheck && await this.requests.cache.has(url)) return Object.assign(await this.requests.cache.get(url), { raw: !!options.raw });
58
68
  if (useRateLimitManager) await rateLimit.rateLimitManager();
59
69
  this.emit('outgoingRequest', url, { ...options, headers: { ...options.headers, ...this.options.headers } });
60
- const result = await requests.request.call(this, url, { ...options, headers: { ...options.headers, ...this.options.headers } });
70
+ const result = await this.requests.request.call(this.requests, url, { ...options, headers: { ...options.headers, ...this.options.headers } });
61
71
  if (this.options.syncWithHeaders) rateLimit.sync(result._headers);
62
72
  return result;
63
73
  }
@@ -76,8 +86,7 @@ class Client extends EventEmitter {
76
86
  * // This example gets the first 100 friends of a player and gets their stats.
77
87
  * hypixel.once('ready',()=>{
78
88
  * hypixel.getFriends('StavZDev')
79
- * .then(friends => friends.map(x=>x.uuid).slice(0, 100))
80
- * .then(hypixel.getPlayer)
89
+ * .then(friends => friends.map(x=>x.uuid).slice(0, 100).map(hypixel.getPlayer))
81
90
  * .catch(console.log);
82
91
  * })
83
92
  */
@@ -355,7 +364,7 @@ class Client extends EventEmitter {
355
364
  * .catch(console.log)
356
365
  */
357
366
  /**
358
- * Allows you to get Ranked SkyWars data of a player
367
+ * Allows you to get Ranked SkyWars data for current season of a player
359
368
  * @method
360
369
  * @name Client#getRankedSkyWars
361
370
  * @param {string} query Player nickname or uuid
@@ -377,13 +386,14 @@ class Client extends EventEmitter {
377
386
  * @return {Promise<void|boolean[]>}
378
387
  */
379
388
  sweepCache (amount) {
380
- return requests.sweepCache(amount);
389
+ return this.requests.sweepCache(amount);
381
390
  }
382
391
  }
383
392
  /**
384
393
  * @typedef {object} ClientOptions
385
394
  * @prop {boolean} [cache=false] Enable/Disable request caching.
386
395
  * @prop {number} [cacheTime=60] Amount of time in seconds to cache the requests.
396
+ * @prop {CacheHandler} [cacheHandler] Custom Cache Handler
387
397
  * @prop {AUTO|HARD|NONE} [rateLimit='AUTO'] Rate limit mode.
388
398
  * @prop {boolean} [syncWithHeaders=false] Sync with headers rate limit information. Usually not necessary nor recommended ( because of latency )
389
399
  * @prop {number} [keyLimit=120] Key limit of your key.
@@ -392,14 +402,23 @@ class Client extends EventEmitter {
392
402
  * @prop {object} [headers={}] Extra Headers ( like User-Agent ) to add to request.
393
403
  * @prop {boolean} [checkForUpdates=false] Enable/Disable check for new version of hypixel-api-reborn.
394
404
  */
405
+ const defaultCache = require('./Private/defaultCache.js');
406
+ /**
407
+ * @typedef {defaultCache} Cache
408
+ */
409
+ /**
410
+ * @typedef {Cache} CacheHandler
411
+ */
395
412
  /**
396
413
  * @typedef {object} MethodOptions
414
+ * @property {boolean} [raw=false] Raw data
397
415
  * @property {boolean} [noCacheCheck=false] Disable/Enable cache checking
398
416
  * @property {boolean} [noCaching=false] Disable/Enable writing to cache
399
417
  * @prop {object} [headers={}] Extra Headers ( like User-Agent ) to add to request. Overrides the headers globally provided.
400
418
  */
401
419
  /**
402
420
  * @typedef {object} PlayerMethodOptions
421
+ * @property {boolean} [raw=false] Raw data
403
422
  * @property {boolean} [noCacheCheck=false] Disable/Enable cache checking
404
423
  * @property {boolean} [noCaching=false] Disable/Enable writing to cache
405
424
  * @property {boolean} [guild=false] Disable/Enable request for player's guild
@@ -409,6 +428,7 @@ class Client extends EventEmitter {
409
428
  */
410
429
  /**
411
430
  * @typedef {object} SkyblockMethodOptions
431
+ * @property {boolean} [raw=false] Raw data
412
432
  * @property {?boolean} [noCacheCheck=false] Disable/Enable cache checking
413
433
  * @property {?boolean} [noCaching=false] Disable/Enable writing to cache
414
434
  * @property {?boolean} [fetchPlayer=false] Disable/Enable player profile request for each member
package/src/Errors.js CHANGED
@@ -34,5 +34,6 @@ module.exports = {
34
34
  CONNECTION_ERROR: '[hypixel-api-reborn] Failed to connect.',
35
35
  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.',
36
36
  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.',
37
- INVALID_HEADERS: '[hypixel-api-reborn] Invalid Headers are provided in ClientOptions. For help join our Discord Server https://discord.gg/NSEBNMM'
37
+ INVALID_HEADERS: '[hypixel-api-reborn] Invalid Headers are provided in ClientOptions. For help join our Discord Server https://discord.gg/NSEBNMM',
38
+ INVALID_CACHE_HANDLER: '[hypixel-api-reborn] An invalid cache handler is provideed. For help join our Discord Server https://discord.gg/NSEBNMM'
38
39
  };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * This is the default cache implementation, using a Map.
3
+ * All cache implementations must have these methods below, they can be async :
4
+ * set(key, value) : Sets key to value
5
+ * has(key) : Whether there is an entry to this key. (can be an alias to get)
6
+ * get(key) : Gets by key (nullish value if not found)
7
+ * delete(key) : Deletes by key
8
+ * keys() : Array of keys, ordered by time of creation. To help you, the key will be deleted and set in case of an update
9
+ * size(): Size of cache (number of keys)
10
+ * clear(): Deletes all cache entries
11
+ * See JSDoc for more info
12
+ */
13
+ class Cache {
14
+ /**
15
+ * Constructor
16
+ */
17
+ constructor() {
18
+ this.storage = new Map();
19
+ }
20
+ /**
21
+ * Sets an entry
22
+ * @param {string} key String key
23
+ * @param {*} value Any value
24
+ * @return {boolean}
25
+ */
26
+ set(key, value) {
27
+ return this.storage.set(key, value);
28
+ }
29
+ /**
30
+ * Check if there's an entry in the cache that has this key
31
+ * This doesn't have to return boolean, just a truthy/falsy value
32
+ * @param {string} key String key
33
+ * @return {boolean} Whether this key exists
34
+ */
35
+ has(key) {
36
+ return this.storage.has(key);
37
+ }
38
+ /**
39
+ * Gets an entry, return a nullish value if not found
40
+ * @param {string} key String key
41
+ * @return {*}
42
+ */
43
+ get(key) {
44
+ return this.storage.get(key);
45
+ }
46
+ /**
47
+ * Deletes an entry
48
+ * @param {string} key String key
49
+ * @return {boolean} Preferably, returns a boolean to check if the deletion is actually successful
50
+ */
51
+ delete(key) {
52
+ return this.storage.delete(key);
53
+ }
54
+ /**
55
+ * Returns Array of string (not an iterator preferably, it can break)
56
+ * @return {string[]}
57
+ */
58
+ keys() {
59
+ return Array.from(this.storage.keys());
60
+ }
61
+ /**
62
+ * Returns size of cache
63
+ * @return {number}
64
+ */
65
+ size() {
66
+ return this.storage.size;
67
+ }
68
+ /**
69
+ * Clears cache
70
+ * @return {void}
71
+ */
72
+ clear() {
73
+ this.storage.clear();
74
+ }
75
+ }
76
+
77
+ module.exports = Cache;
78
+
@@ -2,10 +2,19 @@
2
2
  const fetch = require('node-fetch');
3
3
  const BASE_URL = 'https://api.hypixel.net';
4
4
  const Errors = require('../Errors');
5
- const cached = new Map();
5
+ const Cache = require('./defaultCache');
6
+
6
7
  module.exports = class Requests {
8
+ constructor(client, cache) {
9
+ if (cache && !this.validateCustomCache()) throw new Error(Errors.INVALID_CACHE_HANDLER);
10
+ /**
11
+ * @type {Cache}
12
+ */
13
+ this.cached = cache || new Cache();
14
+ this.client = client;
15
+ }
7
16
  async request (endpoint, options = {}) {
8
- options.headers = {'API-Key': this.key, ...options.headers};
17
+ options.headers = {'API-Key': this.client.key, ...options.headers};
9
18
  const res = await fetch(BASE_URL + endpoint, options);
10
19
  if (res.status >= 500 && res.status < 528) throw new Error(Errors.ERROR_STATUSTEXT.replace(/{statustext}/, `Server Error : ${res.status} ${res.statusText}`));
11
20
  const parsedRes = await res.json().catch(() => {
@@ -18,22 +27,28 @@ module.exports = class Requests {
18
27
  throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.cause));
19
28
  }
20
29
  parsedRes._headers = res.headers;
30
+ parsedRes.raw = !!options.raw;
21
31
  if (options.noCaching) return parsedRes;
22
32
  // split by question mark : first part is /path, remove /
23
- if (this.options.cache && this.options.cacheFilter(endpoint.split('?')[0].slice(1))) {
24
- if (this.options.cacheSize < cached.size) cached.delete(cached.keys().next().value); // Map and its special "iterators"
25
- cached.set(endpoint, parsedRes);
26
- if (this.options.cacheTime >= 0) setTimeout(() => cached.delete(endpoint), 1000 * this.options.cacheTime);
33
+ if (this.client.options.cache && this.client.options.cacheFilter(endpoint.split('?')[0].slice(1))) {
34
+ if (this.client.options.cacheSize < await this.cached.size()) await this.cached.delete(Array.from(await this.cached.keys())[0]);
35
+ await this.cached.delete(endpoint);
36
+ await this.cached.set(endpoint, parsedRes);
37
+ if (this.client.options.cacheTime >= 0) setTimeout(() => this.cached.delete(endpoint), 1000 * this.client.options.cacheTime);
27
38
  }
28
39
  return parsedRes;
29
40
  }
30
41
 
31
42
  get cache () {
32
- return cached;
43
+ return this.cached;
33
44
  }
34
45
 
35
46
  async sweepCache (amount) {
36
- if (!amount || amount >= cached.size) return cached.clear();
37
- return Array.from(cached.keys()).slice(cached.size - amount).map((x) => cached.delete(x));
47
+ if (!amount || amount >= await this.cached.size()) return await this.cached.clear();
48
+ return await Promise.all(Array.from(await this.cached.keys()).slice(await this.cached.size() - amount).map((x) => this.cached.delete(x)));
49
+ }
50
+
51
+ validateCustomCache(cache) {
52
+ return !!(cache.set && cache.get && cache.delete && cache.keys);
38
53
  }
39
54
  };
@@ -20,8 +20,11 @@ class Updater {
20
20
  New version of hypixel-api-reborn is available!
21
21
 
22
22
  v${newVersion}
23
+ Changelog: https://github.com/Hypixel-API-Reborn/hypixel-api-reborn/releases/tag/${newVersion}
23
24
 
24
- npm i hypixel-api-reborn@${newVersion}.
25
+ \x1b[33mnpm i hypixel-api-reborn@${newVersion}\x1b[0m
26
+ or
27
+ \x1b[33myarn add hypixel-api-reborn@${newVersion}\x1b[0m
25
28
 
26
29
  `);
27
30
  }
@@ -62,7 +62,7 @@ class Validation {
62
62
  */
63
63
  cacheSuboptions (input) {
64
64
  if (typeof input !== 'object' || input === null) return false;
65
- if (!input.noCacheCheck && !input.noCaching) return false;
65
+ if (!input.noCacheCheck && !input.noCaching && !input.raw) return false;
66
66
  return true;
67
67
  }
68
68
 
@@ -89,9 +89,9 @@ class Validation {
89
89
  * @returns {void}
90
90
  * @private
91
91
  */
92
- validateNodeVersion() {
92
+ validateNodeVersion () {
93
93
  const nodeVersion = parseInt(process.version.match(/v(\d{2})\.\d{1,}\.\d+/)[1], 10);
94
- if (nodeVersion < 12 ) throw new Error(Errors.NODE_VERSION_ERR);
94
+ if (nodeVersion < 12) throw new Error(Errors.NODE_VERSION_ERR);
95
95
  }
96
96
  }
97
97
  module.exports = Validation;
@@ -105,6 +105,19 @@ class BedWars {
105
105
  diamond: data.diamond_resources_collected_bedwars || 0,
106
106
  emerald: data.emerald_resources_collected_bedwars || 0
107
107
  };
108
+ /**
109
+ * Loot chests
110
+ * @type {BedWarsLootChests}
111
+ */
112
+ this.lootChests = {
113
+ christmas: data.bedwars_christmas_boxes || 0,
114
+ lunar: data.bedwars_lunar_boxes || 0,
115
+ normal: data.bedwars_boxes || 0,
116
+ easter: data.bedwars_easter_boxes || 0,
117
+ halloween: data.bedwars_halloween_boxes || 0,
118
+ golden: data.bedwars_golden_boxes || 0,
119
+ total: (data.bedwars_christmas_boxes + data.bedwars_lunar_boxes + data.bedwars_boxes + data.bedwars_easter_boxes + data.bedwars_halloween_boxes + data.bedwars_golden_boxes) || 0
120
+ };
108
121
  /**
109
122
  * Beds lost/broken/BL Ratio
110
123
  * @type {BedWarsBeds}
@@ -291,6 +304,15 @@ function getLevelForExp (exp) {
291
304
  * @property {number} diamond Diamond
292
305
  * @property {number} emerald Emerald
293
306
  */
307
+ /**
308
+ * @typedef {object} BedWarsLootChests
309
+ * @property {number} christmas Christmas chests
310
+ * @property {number} halloween Halloween chests
311
+ * @property {number} easter Easter chests
312
+ * @property {number} christmas Christmas chests
313
+ * @property {number} golden Golden chests
314
+ * @property {number} normal Normal chests
315
+ */
294
316
  /**
295
317
  * @typedef {object} BedWarsBeds
296
318
  * @property {number} lost Beds lost