hypixel-api-reborn 11.2.0 → 11.2.1
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.
- package/README.md +1 -1
- package/eslint.config.mjs +71 -0
- package/package.json +11 -17
- package/src/API/getAchievements.js +1 -0
- package/src/API/getBoosters.js +1 -0
- package/src/API/getChallenges.js +1 -0
- package/src/API/getGameCounts.js +1 -0
- package/src/API/getGuild.js +4 -3
- package/src/API/getGuildAchievements.js +1 -0
- package/src/API/getLeaderboards.js +1 -1
- package/src/API/getPlayer.js +1 -0
- package/src/API/getQuests.js +1 -0
- package/src/API/getRecentGames.js +5 -9
- package/src/API/getServerInfo.js +40 -37
- package/src/API/getStatus.js +1 -0
- package/src/API/getWatchdogStats.js +1 -0
- package/src/API/skyblock/getAuction.js +8 -6
- package/src/API/skyblock/getAuctions.js +15 -12
- package/src/API/skyblock/getAuctionsByPlayer.js +1 -1
- package/src/API/skyblock/getBazaar.js +1 -3
- package/src/API/skyblock/getBingo.js +1 -2
- package/src/API/skyblock/getBingoByPlayer.js +3 -3
- package/src/API/skyblock/getEndedAuctions.js +1 -0
- package/src/API/skyblock/getFireSales.js +1 -1
- package/src/API/skyblock/getGovernment.js +1 -2
- package/src/API/skyblock/getMember.js +1 -0
- package/src/API/skyblock/getMuseum.js +1 -0
- package/src/API/skyblock/getNews.js +1 -0
- package/src/API/skyblock/getProfiles.js +1 -0
- package/src/Client.js +42 -14
- package/src/Private/rateLimit.js +7 -11
- package/src/Private/requests.js +11 -12
- package/src/Private/updater.js +2 -3
- package/src/Private/uuidCache.js +1 -2
- package/src/Private/validate.js +19 -19
- package/src/structures/APIIncident.js +1 -2
- package/src/structures/APIStatus.js +0 -1
- package/src/structures/Boosters/Booster.js +9 -8
- package/src/structures/Game.js +1 -1
- package/src/structures/Guild/Guild.js +19 -36
- package/src/structures/Guild/GuildMember.js +2 -2
- package/src/structures/MiniGames/Arcade.js +242 -240
- package/src/structures/MiniGames/ArenaBrawl.js +11 -11
- package/src/structures/MiniGames/BedWars.js +197 -194
- package/src/structures/MiniGames/BlitzSurvivalGames.js +24 -23
- package/src/structures/MiniGames/CopsAndCrims.js +1 -0
- package/src/structures/MiniGames/Duels.js +9 -11
- package/src/structures/MiniGames/Pit.js +4 -5
- package/src/structures/MiniGames/SkyWars.js +197 -186
- package/src/structures/MiniGames/SmashHeroes.js +36 -34
- package/src/structures/MiniGames/SpeedUHC.js +17 -4
- package/src/structures/MiniGames/UHC.js +26 -25
- package/src/structures/MiniGames/WoolWars.js +6 -5
- package/src/structures/Pet.js +1 -1
- package/src/structures/Player.js +13 -104
- package/src/structures/PlayerCosmetics.js +5 -4
- package/src/structures/SkyBlock/Auctions/AuctionInfo.js +2 -1
- package/src/structures/SkyBlock/Auctions/BaseAuction.js +1 -1
- package/src/structures/SkyBlock/News/SkyblockNews.js +15 -15
- package/src/structures/SkyBlock/PlayerBingo.js +7 -14
- package/src/structures/SkyBlock/SkyblockInventoryItem.js +4 -28
- package/src/structures/SkyBlock/SkyblockMember.js +78 -223
- package/src/structures/SkyBlock/SkyblockPet.js +3 -4
- package/src/structures/SkyBlock/Static/Bingo.js +10 -11
- package/src/structures/SkyBlock/Static/BingoData.js +1 -1
- package/src/structures/Static/Achievement.js +16 -15
- package/src/structures/Static/AchievementTier.js +2 -2
- package/src/structures/Static/Quest.js +2 -2
- package/src/utils/Constants.js +17 -517
- package/src/utils/{guildExp.js → Guild.js} +42 -12
- package/src/utils/Player.js +112 -0
- package/src/utils/SkyblockUtils.js +449 -192
- package/src/utils/arrayTools.js +1 -1
- package/src/utils/divide.js +1 -1
- package/src/utils/index.js +2 -1
- package/src/utils/isGuildID.js +1 -1
- package/src/utils/oscillation.js +4 -2
- package/src/utils/removeSnakeCase.js +11 -7
- package/src/utils/rgbToHexColor.js +1 -1
- package/src/utils/romanize.js +3 -3
- package/src/utils/toUuid.js +4 -4
- package/src/utils/varInt.js +2 -2
- package/typings/index.d.ts +272 -162
- package/src/utils/toIGN.js +0 -24
package/src/Client.js
CHANGED
|
@@ -1,13 +1,37 @@
|
|
|
1
|
-
/* eslint-disable require-jsdoc */
|
|
2
|
-
/* eslint-disable max-len */
|
|
3
|
-
const validate = new (require('./Private/validate'))();
|
|
4
1
|
const rateLimit = new (require('./Private/rateLimit'))();
|
|
5
|
-
const
|
|
2
|
+
const validate = new (require('./Private/validate'))();
|
|
6
3
|
const updater = new (require('./Private/updater'))();
|
|
4
|
+
const Requests = require('./Private/requests');
|
|
5
|
+
const EventEmitter = require('events');
|
|
7
6
|
const Errors = require('./Errors');
|
|
8
7
|
const API = require('./API/index');
|
|
9
|
-
const EventEmitter = require('events');
|
|
10
8
|
const clients = [];
|
|
9
|
+
|
|
10
|
+
/* eslint-disable */
|
|
11
|
+
const Player = require('./structures/Player');
|
|
12
|
+
const Guild = require('./structures/Guild/Guild');
|
|
13
|
+
const WatchdogStats = require('./structures/Watchdog/Stats');
|
|
14
|
+
const Booster = require('./structures/Boosters/Booster');
|
|
15
|
+
const SkyblockProfile = require('./structures/SkyBlock/SkyblockProfile');
|
|
16
|
+
const SkyblockMember = require('./structures/SkyBlock/SkyblockMember');
|
|
17
|
+
const SkyblockMuseum = require('./structures/SkyBlock/SkyblockMuseum');
|
|
18
|
+
const APIStatus = require('./structures/APIStatus');
|
|
19
|
+
const Leaderboard = require('./structures/Leaderboard');
|
|
20
|
+
const ServerInfo = require('./structures/ServerInfo');
|
|
21
|
+
const RecentGame = require('./structures/RecentGame');
|
|
22
|
+
const Status = require('./structures/Status');
|
|
23
|
+
const Auction = require('./structures/SkyBlock/Auctions/Auction');
|
|
24
|
+
const AuctionInfo = require('./structures/SkyBlock/Auctions/AuctionInfo');
|
|
25
|
+
const PartialAuction = require('./structures/SkyBlock/Auctions/PartialAuction');
|
|
26
|
+
const Product = require('./structures/SkyBlock/Bazzar/Product');
|
|
27
|
+
const BingoData = require('./structures/SkyBlock/Static/BingoData');
|
|
28
|
+
const PlayerBingo = require('./structures/SkyBlock/PlayerBingo');
|
|
29
|
+
const GovernmentData = require('./structures/SkyBlock/Static/Government');
|
|
30
|
+
const FireSale = require('./structures/SkyBlock/Static/FireSale');
|
|
31
|
+
const SkyblockNews = require('./structures/SkyBlock/News/SkyblockNews');
|
|
32
|
+
const GameCounts = require('./structures/GameCounts');
|
|
33
|
+
/* eslint-enable */
|
|
34
|
+
|
|
11
35
|
/**
|
|
12
36
|
* Client class
|
|
13
37
|
*/
|
|
@@ -30,12 +54,13 @@ class Client extends EventEmitter {
|
|
|
30
54
|
this.key = validate.validateKey(key);
|
|
31
55
|
this.options = validate.parseOptions(options);
|
|
32
56
|
validate.validateOptions(this.options);
|
|
33
|
-
|
|
57
|
+
|
|
34
58
|
for (const func in API) {
|
|
35
59
|
Client.prototype[func] = (...args) => {
|
|
36
60
|
const lastArg = args[args.length - 1];
|
|
37
61
|
return API[func].apply(
|
|
38
62
|
{
|
|
63
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
39
64
|
_makeRequest: this._makeRequest.bind(this, validate.cacheSuboptions(lastArg) ? lastArg : {}),
|
|
40
65
|
...this
|
|
41
66
|
},
|
|
@@ -68,8 +93,8 @@ class Client extends EventEmitter {
|
|
|
68
93
|
*/
|
|
69
94
|
async _makeRequest(options, url, useRateLimitManager = true) {
|
|
70
95
|
if (!url) return;
|
|
71
|
-
if (
|
|
72
|
-
return Object.assign(await this.requests.cache.get(url), { raw:
|
|
96
|
+
if ('/key' !== url && !options.noCacheCheck && (await this.requests.cache.has(url))) {
|
|
97
|
+
return Object.assign(await this.requests.cache.get(url), { raw: Boolean(options.raw) });
|
|
73
98
|
}
|
|
74
99
|
if (useRateLimitManager) await rateLimit.rateLimitManager();
|
|
75
100
|
this.emit('outgoingRequest', url, { ...options, headers: { ...options.headers, ...this.options.headers } });
|
|
@@ -77,12 +102,13 @@ class Client extends EventEmitter {
|
|
|
77
102
|
...options,
|
|
78
103
|
headers: { ...options.headers, ...this.options.headers }
|
|
79
104
|
});
|
|
105
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
80
106
|
if (this.options.syncWithHeaders) rateLimit.sync(result._headers);
|
|
81
107
|
return result;
|
|
82
108
|
}
|
|
83
109
|
/**
|
|
84
110
|
* Emitted when rate limiter is ready. ( You don't have to wait for this event to emit UNLESS you are planning to do data scraping which means spamming requests )
|
|
85
|
-
* @event
|
|
111
|
+
* @event ready
|
|
86
112
|
* @name Client#ready
|
|
87
113
|
* @example
|
|
88
114
|
* // This example gets player's uuid.
|
|
@@ -94,14 +120,14 @@ class Client extends EventEmitter {
|
|
|
94
120
|
*/
|
|
95
121
|
/**
|
|
96
122
|
* Emitted when a request is going to be sent
|
|
97
|
-
* @event
|
|
123
|
+
* @event outgoingRequest
|
|
98
124
|
* @name Client#outgoingRequest
|
|
99
125
|
* @param {string} url URL
|
|
100
126
|
* @param {object} [options] Options, if any
|
|
101
127
|
*/
|
|
102
128
|
/**
|
|
103
129
|
* Emitted when there is a warning.
|
|
104
|
-
* @event
|
|
130
|
+
* @event warn
|
|
105
131
|
* @name Client#warn
|
|
106
132
|
* @param {string} error Warning Message
|
|
107
133
|
*/
|
|
@@ -140,7 +166,7 @@ class Client extends EventEmitter {
|
|
|
140
166
|
* Allows you to get statistics of hypixel guild
|
|
141
167
|
* @method
|
|
142
168
|
* @name Client#getGuild
|
|
143
|
-
* @param {id|name|player} searchParameter Search for guild by id, name or player (if player is in guild)
|
|
169
|
+
* @param {'id'|'name'|'player'} searchParameter Search for guild by id, name or player (if player is in guild)
|
|
144
170
|
* @param {string} query Guild ID, Guild name or player uuid/nickname
|
|
145
171
|
* @param {MethodOptions} [options={}] Method options
|
|
146
172
|
* @return {Promise<Guild>}
|
|
@@ -347,7 +373,8 @@ class Client extends EventEmitter {
|
|
|
347
373
|
* console.log(products[0].productId); // INK_SACK:3
|
|
348
374
|
* })
|
|
349
375
|
* .catch(console.log);
|
|
350
|
-
*/
|
|
376
|
+
*/
|
|
377
|
+
/**
|
|
351
378
|
* Allows you to get bingo data
|
|
352
379
|
* @method
|
|
353
380
|
* @name Client#getSkyblockBingo
|
|
@@ -415,7 +442,7 @@ class Client extends EventEmitter {
|
|
|
415
442
|
* @prop {number} [hypixelCacheTime=60] Amount of time in seconds to cache the hypixel api requests.
|
|
416
443
|
* @prop {number} [mojangCacheTime=600] Amount of time in seconds to cache the mojang api requests.
|
|
417
444
|
* @prop {CacheHandler} [cacheHandler] Custom Cache Handler
|
|
418
|
-
* @prop {AUTO|HARD|NONE} [rateLimit='AUTO'] Rate limit mode.
|
|
445
|
+
* @prop {'AUTO'|'HARD'|'NONE'} [rateLimit='AUTO'] Rate limit mode.
|
|
419
446
|
* @prop {boolean} [syncWithHeaders=false] Sync with headers rate limit information. Usually not necessary nor recommended ( because of latency )
|
|
420
447
|
* @prop {number} [keyLimit=60] Key limit of your key.
|
|
421
448
|
* @prop {number} [cacheSize=-1] The amount how many results will be cached. (`-1` for infinity)
|
|
@@ -424,6 +451,7 @@ class Client extends EventEmitter {
|
|
|
424
451
|
* @prop {boolean} [checkForUpdates=true] Enable/Disable check for new version of hypixel-api-reborn.
|
|
425
452
|
* @prop {boolean|string} [useThirdPartyAPI=false] Enable/Disable Mojang Third Party API
|
|
426
453
|
*/
|
|
454
|
+
// eslint-disable-next-line no-unused-vars
|
|
427
455
|
const defaultCache = require('./Private/defaultCache.js');
|
|
428
456
|
/**
|
|
429
457
|
* @typedef {defaultCache} Cache
|
package/src/Private/rateLimit.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
2
|
-
/* eslint-disable camelcase */
|
|
3
1
|
const Errors = require('../Errors');
|
|
4
2
|
|
|
5
|
-
/* eslint-disable require-jsdoc */
|
|
6
3
|
class RateLimit {
|
|
7
4
|
constructor() {
|
|
8
5
|
this.initialized = 0;
|
|
@@ -12,12 +9,11 @@ class RateLimit {
|
|
|
12
9
|
if (!this.initialized) return;
|
|
13
10
|
this.requests++;
|
|
14
11
|
this.requestQueue.unshift(Date.now());
|
|
15
|
-
if (this.options.rateLimit
|
|
16
|
-
if (this.options.rateLimit
|
|
12
|
+
if ('NONE' === this.options.rateLimit || !this.requestQueue.length) return;
|
|
13
|
+
if ('AUTO' === this.options.rateLimit && this.requests <= this.options.keyLimit / 2) return;
|
|
17
14
|
const cooldown = this.computeCooldownTime();
|
|
18
15
|
this.requestQueue[0] = Date.now() + cooldown;
|
|
19
|
-
await new Promise((r) => setTimeout(r, cooldown), true);
|
|
20
|
-
return;
|
|
16
|
+
return await new Promise((r) => setTimeout(r, cooldown), true);
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
sync(data) {
|
|
@@ -45,7 +41,7 @@ class RateLimit {
|
|
|
45
41
|
|
|
46
42
|
reset() {
|
|
47
43
|
this.requests = this.requests - this.options.keyLimit;
|
|
48
|
-
if (this.requests
|
|
44
|
+
if (0 > this.requests) this.requests = 0;
|
|
49
45
|
this.lastResetHappenedAt = Date.now();
|
|
50
46
|
this.resetTimer = setTimeout(this.reset.bind(this), 300000);
|
|
51
47
|
this.requestQueue = this.requestQueue.filter((x) => x >= Date.now());
|
|
@@ -58,13 +54,13 @@ class RateLimit {
|
|
|
58
54
|
init(keyInfo, options, client) {
|
|
59
55
|
this.options = options;
|
|
60
56
|
this.requests = 0;
|
|
61
|
-
this.cooldownTime = 300000 / this.options.keyLimit;
|
|
57
|
+
this.cooldownTime = 300000 / this.options.keyLimit;
|
|
62
58
|
this.requestQueue = [];
|
|
63
59
|
this.client = client;
|
|
64
60
|
return keyInfo
|
|
65
61
|
.then((info) => {
|
|
66
62
|
this.requests = info.requestsInPastMin;
|
|
67
|
-
this.lastResetHappenedAt = Date.now() - (300 - info.resetsAfter) * 1000;
|
|
63
|
+
this.lastResetHappenedAt = Date.now() - (300 - info.resetsAfter) * 1000;
|
|
68
64
|
this.resetTimer = setTimeout(this.rateLimitMonitor.bind(this), 1000 * info.resetsAfter);
|
|
69
65
|
this.initialized = 1;
|
|
70
66
|
})
|
|
@@ -82,6 +78,6 @@ module.exports = RateLimit;
|
|
|
82
78
|
/**
|
|
83
79
|
* @typedef {Object} RLOptions
|
|
84
80
|
* @property {number} keyLimit Max request of key per min
|
|
85
|
-
* @property {NONE|AUTO|HARD} rateLimit rate limit mode
|
|
81
|
+
* @property {'NONE'|'AUTO'|'HARD'} rateLimit rate limit mode
|
|
86
82
|
* @property {boolean} syncWithHeaders Sync rate limits with headers
|
|
87
83
|
*/
|
package/src/Private/requests.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
/* eslint-disable require-jsdoc */
|
|
2
1
|
const requireFetch = !globalThis.fetch;
|
|
3
2
|
const externalFetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
|
|
4
3
|
const fetch = requireFetch ? externalFetch : globalThis.fetch;
|
|
5
4
|
const BASE_URL = 'https://api.hypixel.net/v2';
|
|
6
|
-
const Errors = require('../Errors');
|
|
7
5
|
const Cache = require('./defaultCache');
|
|
8
|
-
const
|
|
6
|
+
const Errors = require('../Errors');
|
|
9
7
|
|
|
10
8
|
class Requests {
|
|
11
9
|
constructor(client, cache) {
|
|
@@ -19,7 +17,7 @@ class Requests {
|
|
|
19
17
|
* @type {externalFetch.Response|Response}
|
|
20
18
|
*/
|
|
21
19
|
const res = await fetch(BASE_URL + endpoint, options);
|
|
22
|
-
if (res.status
|
|
20
|
+
if (500 <= res.status && 528 > res.status) {
|
|
23
21
|
throw new Error(
|
|
24
22
|
Errors.ERROR_STATUSTEXT.replace(/{statustext}/, `Server Error : ${res.status} ${res.statusText}`)
|
|
25
23
|
);
|
|
@@ -27,20 +25,21 @@ class Requests {
|
|
|
27
25
|
const parsedRes = await res.json().catch(() => {
|
|
28
26
|
throw new Error(Errors.INVALID_RESPONSE_BODY);
|
|
29
27
|
});
|
|
30
|
-
if (res.status
|
|
28
|
+
if (400 === res.status) {
|
|
31
29
|
throw new Error(
|
|
32
30
|
Errors.ERROR_CODE_CAUSE.replace(/{code}/, '400 Bad Request').replace(/{cause}/, parsedRes.cause || '')
|
|
33
31
|
);
|
|
34
32
|
}
|
|
35
|
-
if (res.status
|
|
36
|
-
if (res.status
|
|
37
|
-
if (res.status
|
|
38
|
-
if (res.status
|
|
33
|
+
if (403 === res.status) throw new Error(Errors.INVALID_API_KEY);
|
|
34
|
+
if (422 === res.status) throw new Error(Errors.UNEXPECTED_ERROR);
|
|
35
|
+
if (429 === res.status) throw new Error(Errors.RATE_LIMIT_EXCEEDED);
|
|
36
|
+
if (200 !== res.status) throw new Error(Errors.ERROR_STATUSTEXT.replace(/{statustext}/, res.statusText));
|
|
39
37
|
if (!parsedRes.success) {
|
|
40
38
|
throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.cause));
|
|
41
39
|
}
|
|
40
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
42
41
|
parsedRes._headers = res.headers;
|
|
43
|
-
parsedRes.raw =
|
|
42
|
+
parsedRes.raw = Boolean(options.raw);
|
|
44
43
|
if (options.noCaching) return parsedRes;
|
|
45
44
|
// split by question mark : first part is /path, remove /
|
|
46
45
|
if (this.client.options.cache && this.client.options.cacheFilter(endpoint.split('?')[0].slice(1))) {
|
|
@@ -49,7 +48,7 @@ class Requests {
|
|
|
49
48
|
}
|
|
50
49
|
await this.cached.delete(endpoint);
|
|
51
50
|
await this.cached.set(endpoint, parsedRes);
|
|
52
|
-
if (this.client.options.hypixelCacheTime
|
|
51
|
+
if (0 <= this.client.options.hypixelCacheTime) {
|
|
53
52
|
setTimeout(() => this.cached.delete(endpoint), 1000 * this.client.options.hypixelCacheTime);
|
|
54
53
|
}
|
|
55
54
|
}
|
|
@@ -70,7 +69,7 @@ class Requests {
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
validateCustomCache(cache) {
|
|
73
|
-
return
|
|
72
|
+
return Boolean(cache.set && cache.get && cache.delete && cache.keys);
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
|
package/src/Private/updater.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable require-jsdoc */
|
|
2
1
|
/* eslint-disable no-console */
|
|
3
2
|
const requireFetch = !globalThis.fetch;
|
|
4
3
|
const externalFetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
|
|
@@ -12,7 +11,7 @@ class Updater {
|
|
|
12
11
|
const metadata = await request.json();
|
|
13
12
|
const latest = metadata['dist-tags'].latest;
|
|
14
13
|
const compare = this.compare(version, latest);
|
|
15
|
-
if (
|
|
14
|
+
if (-1 === compare) {
|
|
16
15
|
console.log(
|
|
17
16
|
`New version of hypixel-api-reborn is available! Current version: ${version}, Latest version: ${latest}`
|
|
18
17
|
);
|
|
@@ -21,7 +20,7 @@ class Updater {
|
|
|
21
20
|
compare(a, b) {
|
|
22
21
|
const pa = a.split('.');
|
|
23
22
|
const pb = b.split('.');
|
|
24
|
-
for (let i = 0;
|
|
23
|
+
for (let i = 0; 3 > i; i++) {
|
|
25
24
|
const na = Number(pa[i]);
|
|
26
25
|
const nb = Number(pb[i]);
|
|
27
26
|
if (na > nb) return 1;
|
package/src/Private/uuidCache.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable require-jsdoc */
|
|
2
1
|
const requireFetch = !globalThis.fetch;
|
|
3
2
|
const externalFetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
|
|
4
3
|
const fetch = requireFetch ? externalFetch : globalThis.fetch;
|
|
@@ -12,7 +11,7 @@ module.exports = async (url, query, cacheTime) => {
|
|
|
12
11
|
const res = await fetch(url);
|
|
13
12
|
const data = await res.json();
|
|
14
13
|
// Don't cache 4xx
|
|
15
|
-
if (res.status
|
|
14
|
+
if (400 <= res.status) {
|
|
16
15
|
return {
|
|
17
16
|
status: res.status,
|
|
18
17
|
id: null,
|
package/src/Private/validate.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable require-jsdoc */
|
|
2
1
|
const Errors = require('../Errors');
|
|
3
2
|
const { isStrArray, strToArray } = require('../utils/arrayTools');
|
|
4
3
|
/**
|
|
@@ -12,17 +11,17 @@ class Validation {
|
|
|
12
11
|
* @private
|
|
13
12
|
*/
|
|
14
13
|
validateOptions(options) {
|
|
15
|
-
if (typeof options.hypixelCacheTime
|
|
16
|
-
if (typeof options.mojangCacheTime
|
|
17
|
-
if (typeof options.cacheSize
|
|
18
|
-
if (typeof options.rateLimit
|
|
14
|
+
if ('number' !== typeof options.hypixelCacheTime) throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER);
|
|
15
|
+
if ('number' !== typeof options.mojangCacheTime) throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER);
|
|
16
|
+
if ('number' !== typeof options.cacheSize) throw new Error(Errors.CACHE_LIMIT_MUST_BE_A_NUMBER);
|
|
17
|
+
if ('string' !== typeof options.rateLimit || !['AUTO', 'HARD', 'NONE'].includes(options.rateLimit)) {
|
|
19
18
|
throw new Error(Errors.INVALID_RATE_LIMIT_OPTION);
|
|
20
19
|
}
|
|
21
|
-
if (typeof options.keyLimit
|
|
22
|
-
if (typeof options.syncWithHeaders
|
|
23
|
-
if (typeof options.headers
|
|
24
|
-
if (typeof options.silent
|
|
25
|
-
if (typeof options.checkForUpdates
|
|
20
|
+
if ('number' !== typeof options.keyLimit) throw new Error(Errors.INVALID_KEY_LIMIT_OPTION);
|
|
21
|
+
if ('boolean' !== typeof options.syncWithHeaders) throw new Error(Errors.INVALID_HEADER_SYNC_OPTION);
|
|
22
|
+
if ('object' !== typeof options.headers) throw new Error(Errors.INVALID_HEADERS);
|
|
23
|
+
if ('boolean' !== typeof options.silent) throw new Error(Errors.INVALID_SILENT_OPTION);
|
|
24
|
+
if ('boolean' !== typeof options.checkForUpdates) throw new Error(Errors.INVALID_UPDATE_OPTION);
|
|
26
25
|
if (!['boolean', 'string'].includes(typeof options.useThirdPartyAPI)) {
|
|
27
26
|
throw new Error(Errors.INVALID_THIRD_PARTY_API_OPTION);
|
|
28
27
|
}
|
|
@@ -35,19 +34,20 @@ class Validation {
|
|
|
35
34
|
* @private
|
|
36
35
|
*/
|
|
37
36
|
parseOptions(options) {
|
|
38
|
-
if (
|
|
37
|
+
if ('object' !== typeof options || null === options) throw new Error(Errors.OPTIONS_MUST_BE_AN_OBJECT);
|
|
39
38
|
return {
|
|
40
39
|
cache: options.cache ?? true,
|
|
41
40
|
hypixelCacheTime: options.hypixelCacheTime ?? 60,
|
|
42
41
|
mojangCacheTime: options.mojangCacheTime ?? 600,
|
|
43
|
-
cacheSize: (options.cacheSize
|
|
42
|
+
cacheSize: (-1 === options.cacheSize ? Infinity : options.cacheSize) || Infinity,
|
|
44
43
|
cacheFilter:
|
|
45
|
-
|
|
44
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
45
|
+
'function' === typeof options.cacheFilter ? options.cacheFilter : this._handleFilter(options.cacheFilter),
|
|
46
46
|
rateLimit: options.rateLimit ?? 'AUTO',
|
|
47
47
|
keyLimit: options.keyLimit ?? 60,
|
|
48
|
-
syncWithHeaders:
|
|
48
|
+
syncWithHeaders: Boolean(options.syncWithHeaders),
|
|
49
49
|
headers: options.headers ?? {},
|
|
50
|
-
silent:
|
|
50
|
+
silent: Boolean(options.silent),
|
|
51
51
|
checkForUpdates: options.checkForUpdates ?? true,
|
|
52
52
|
useThirdPartyAPI: options.useThirdPartyAPI ?? false
|
|
53
53
|
};
|
|
@@ -61,7 +61,7 @@ class Validation {
|
|
|
61
61
|
*/
|
|
62
62
|
validateKey(key) {
|
|
63
63
|
if (!key) throw new Error(Errors.NO_API_KEY);
|
|
64
|
-
if (typeof key
|
|
64
|
+
if ('string' !== typeof key) throw new Error(Errors.KEY_MUST_BE_A_STRING);
|
|
65
65
|
return key;
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -72,7 +72,7 @@ class Validation {
|
|
|
72
72
|
* @private
|
|
73
73
|
*/
|
|
74
74
|
cacheSuboptions(input) {
|
|
75
|
-
if (
|
|
75
|
+
if ('object' !== typeof input || null === input) return false;
|
|
76
76
|
if (!input.noCacheCheck && !input.noCaching && !input.raw) return false;
|
|
77
77
|
return true;
|
|
78
78
|
}
|
|
@@ -85,7 +85,7 @@ class Validation {
|
|
|
85
85
|
*/
|
|
86
86
|
_handleFilter(filter) {
|
|
87
87
|
if (!filter) return () => true;
|
|
88
|
-
if (typeof filter
|
|
88
|
+
if ('object' === typeof filter && !Array.isArray(filter)) {
|
|
89
89
|
if (filter.whitelist && isStrArray(filter.whitelist)) return (x) => strToArray(filter.whitelist).includes(x);
|
|
90
90
|
if (filter.blacklist && isStrArray(filter.blacklist)) return (x) => !strToArray(filter.blacklist).includes(x);
|
|
91
91
|
throw new Error(Errors.CACHE_FILTER_INVALID);
|
|
@@ -102,7 +102,7 @@ class Validation {
|
|
|
102
102
|
*/
|
|
103
103
|
validateNodeVersion() {
|
|
104
104
|
const nodeVersion = parseInt(process.version.match(/v(\d{2})\.\d{1,}\.\d+/)[1], 10);
|
|
105
|
-
if (
|
|
105
|
+
if (12 > nodeVersion) throw new Error(Errors.NODE_VERSION_ERR);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
module.exports = Validation;
|
|
@@ -16,7 +16,7 @@ class APIIncident {
|
|
|
16
16
|
* Timestamp when investigation was started as Date object
|
|
17
17
|
* @type {object|null}
|
|
18
18
|
*/
|
|
19
|
-
this.start = new Date(data.pubDate)
|
|
19
|
+
this.start = data.pubDate ? new Date(data.pubDate) : null;
|
|
20
20
|
/**
|
|
21
21
|
* Formatted timestamp when investigation was started
|
|
22
22
|
* @type {string|null}
|
|
@@ -56,7 +56,6 @@ class APIIncident {
|
|
|
56
56
|
* Whether the incident is resolved/completed or not
|
|
57
57
|
* @author linearaccelerator
|
|
58
58
|
* @type {boolean}
|
|
59
|
-
* @version >6.0.1
|
|
60
59
|
*/
|
|
61
60
|
this.isResolved = this.HTMLContent.includes('Resolved -') || this.HTMLContent.includes('Completed -');
|
|
62
61
|
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
const Game = require('../Game');
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
4
|
+
function parseType(data) {
|
|
5
|
+
if (true === data.stacked) return 'STACKED';
|
|
6
|
+
if (!data.stacked) return 'QUEUED';
|
|
7
|
+
return 'ACTIVE';
|
|
8
|
+
}
|
|
9
|
+
|
|
2
10
|
/**
|
|
3
11
|
* Booster class
|
|
4
12
|
*/
|
|
@@ -63,7 +71,7 @@ class Booster {
|
|
|
63
71
|
* Works by checking if date.length is negative
|
|
64
72
|
* @type {boolean}
|
|
65
73
|
*/
|
|
66
|
-
this.expired = data.length
|
|
74
|
+
this.expired = 0 > data.length;
|
|
67
75
|
}
|
|
68
76
|
/**
|
|
69
77
|
* Beautiful format
|
|
@@ -73,11 +81,4 @@ class Booster {
|
|
|
73
81
|
return `${this.purchaser}'s booster in ${this.game}`;
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
|
-
|
|
77
|
-
// eslint-disable-next-line require-jsdoc
|
|
78
|
-
function parseType(data) {
|
|
79
|
-
if (data.stacked === true) return 'STACKED';
|
|
80
|
-
if (!data.stacked) return 'QUEUED';
|
|
81
|
-
return 'ACTIVE';
|
|
82
|
-
}
|
|
83
84
|
module.exports = Booster;
|
package/src/structures/Game.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
const { getGuildLevel, ranks, calculateExpHistory } = require('../../utils/Guild');
|
|
1
2
|
const GuildMember = require('./GuildMember');
|
|
2
3
|
const GuildRank = require('./GuildRank');
|
|
3
4
|
const Color = require('../Color');
|
|
4
5
|
const Game = require('../Game');
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
8
|
+
function members(data) {
|
|
9
|
+
return data.members.length ? data.members.map((m) => new GuildMember(m)) : [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
13
|
+
function totalWeeklyGexp(data) {
|
|
14
|
+
return members(data)
|
|
15
|
+
.map((m) => m.weeklyExperience)
|
|
16
|
+
.reduce((acc, cur) => acc + cur);
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
/**
|
|
7
20
|
* Guild class
|
|
8
21
|
*/
|
|
@@ -16,6 +29,8 @@ class Guild {
|
|
|
16
29
|
* Guild ID
|
|
17
30
|
* @type {string}
|
|
18
31
|
*/
|
|
32
|
+
|
|
33
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
19
34
|
this.id = data._id;
|
|
20
35
|
/**
|
|
21
36
|
* Guild name
|
|
@@ -105,7 +120,7 @@ class Guild {
|
|
|
105
120
|
* Whether this guild is listed in the Guild Finder
|
|
106
121
|
* @type {boolean}
|
|
107
122
|
*/
|
|
108
|
-
this.publiclyListed =
|
|
123
|
+
this.publiclyListed = Boolean(data.publiclyListed);
|
|
109
124
|
/**
|
|
110
125
|
* Timestamp guild chat will be unmuted at.
|
|
111
126
|
* @type {number|null}
|
|
@@ -115,7 +130,7 @@ class Guild {
|
|
|
115
130
|
* Timestamp guild chat will be unmuted at as Date.
|
|
116
131
|
* @type {Date|null}
|
|
117
132
|
*/
|
|
118
|
-
this.chatMuteUntil = new Date(data.chatMute)
|
|
133
|
+
this.chatMuteUntil = data.chatMute ? new Date(data.chatMute) : null;
|
|
119
134
|
/**
|
|
120
135
|
* Timestamp guild chat will be unmuted at.
|
|
121
136
|
* @type {Array<{ Pattern: string, Color: string }>}
|
|
@@ -169,40 +184,8 @@ class Guild {
|
|
|
169
184
|
* @type {GuildMember}
|
|
170
185
|
*/
|
|
171
186
|
get guildMaster() {
|
|
172
|
-
return this.members.find((member) =>
|
|
187
|
+
return this.members.find((member) => 'Guild Master' === member.rank || 'GUILDMASTER' === member.rank);
|
|
173
188
|
}
|
|
174
189
|
}
|
|
175
|
-
// eslint-disable-next-line require-jsdoc
|
|
176
|
-
function members(data) {
|
|
177
|
-
return data.members.length ? data.members.map((m) => new GuildMember(m)) : [];
|
|
178
|
-
}
|
|
179
|
-
// eslint-disable-next-line require-jsdoc
|
|
180
|
-
function ranks(data) {
|
|
181
|
-
return data.ranks && data.ranks.length
|
|
182
|
-
? data.ranks.map((r) => new GuildRank(r)).sort((a, b) => a.priority - b.priority)
|
|
183
|
-
: [];
|
|
184
|
-
}
|
|
185
|
-
// eslint-disable-next-line require-jsdoc
|
|
186
|
-
function totalWeeklyGexp(data) {
|
|
187
|
-
return members(data)
|
|
188
|
-
.map((m) => m.weeklyExperience)
|
|
189
|
-
.reduce((acc, cur) => acc + cur);
|
|
190
|
-
}
|
|
191
|
-
// eslint-disable-next-line require-jsdoc
|
|
192
|
-
function calculateExpHistory(data) {
|
|
193
|
-
const finalObj = {};
|
|
194
|
-
for (const day of Object.keys(data.members[0].expHistory)) {
|
|
195
|
-
let gexp = 0;
|
|
196
|
-
for (const member of data.members) {
|
|
197
|
-
gexp += member.expHistory[day] || 0;
|
|
198
|
-
}
|
|
199
|
-
finalObj[day] = expLimit(gexp);
|
|
200
|
-
}
|
|
201
|
-
return parseHistory(finalObj);
|
|
202
|
-
}
|
|
203
|
-
// eslint-disable-next-line require-jsdoc
|
|
204
|
-
function expLimit(exp) {
|
|
205
|
-
return exp > 2e5 ? (exp > 7e5 ? 2.5e5 + Math.round(exp * 0.03) : 2e5 + Math.round((exp - 2e5) / 10)) : exp;
|
|
206
|
-
}
|
|
207
190
|
|
|
208
191
|
module.exports = Guild;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { parseHistory } = require('../../utils/
|
|
1
|
+
const { parseHistory } = require('../../utils/Guild');
|
|
2
2
|
/**
|
|
3
3
|
* GuildMember class
|
|
4
4
|
*/
|
|
@@ -42,7 +42,7 @@ class GuildMember {
|
|
|
42
42
|
* @type {Date|null}
|
|
43
43
|
*/
|
|
44
44
|
this.mutedUntil = data.mutedTill ? new Date(data.mutedTill) : null;
|
|
45
|
-
const xpCheck = data.expHistory && typeof Object.values(data.expHistory)[0]
|
|
45
|
+
const xpCheck = data.expHistory && 'number' === typeof Object.values(data.expHistory)[0];
|
|
46
46
|
/**
|
|
47
47
|
* Experience history per day, resets at 5 am UTC
|
|
48
48
|
* @type {Array<ExpHistory>}
|