clashofclans.js 3.1.2 → 3.1.3-dev.048e4b9
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/dist/client/Client.d.ts +3 -3
- package/dist/client/Client.js +5 -5
- package/dist/client/PollingClient.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -0
- package/dist/rest/RESTManager.d.ts +2 -2
- package/dist/rest/RESTManager.js +1 -1
- package/dist/rest/RequestHandler.d.ts +3 -1
- package/dist/rest/RequestHandler.js +50 -62
- package/dist/struct/Clan.d.ts +4 -4
- package/dist/struct/Clan.js +2 -2
- package/dist/struct/ClanMember.d.ts +1 -1
- package/dist/struct/ClanWar.d.ts +1 -1
- package/dist/struct/ClanWarLeagueGroup.d.ts +5 -3
- package/dist/struct/ClanWarLeagueGroup.js +9 -4
- package/dist/struct/ClanWarLog.d.ts +1 -1
- package/dist/struct/Player.d.ts +5 -5
- package/dist/struct/Player.js +4 -4
- package/dist/struct/PlayerClan.d.ts +1 -1
- package/dist/struct/Ranking.d.ts +4 -4
- package/dist/struct/Ranking.js +3 -3
- package/dist/struct/Unit.d.ts +1 -1
- package/dist/struct/index.d.ts +3 -3
- package/dist/struct/index.js +3 -3
- package/dist/types/lib.d.ts +15 -9
- package/dist/util/Util.d.ts +1 -0
- package/dist/util/Util.js +15 -1
- package/package.json +14 -17
package/README.md
CHANGED
package/dist/client/Client.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
-
import { ClanSearchOptions, SearchOptions, ClientOptions, LoginOptions, OverrideOptions } from '../types';
|
|
4
|
-
import { CWLRounds, ClientEvents } from '../util/Constants';
|
|
5
3
|
import { RESTManager } from '../rest/RESTManager';
|
|
4
|
+
import { ClanSearchOptions, ClientOptions, LoginOptions, OverrideOptions, SearchOptions } from '../types';
|
|
5
|
+
import { CWLRounds, ClientEvents } from '../util/Constants';
|
|
6
6
|
import { Util } from '../util/Util';
|
|
7
|
-
import { Clan, ClanMember, ClanWar, ClanWarLog, Location, Player, RankedClan, RankedPlayer, SeasonRankedPlayer
|
|
7
|
+
import { Clan, ClanMember, ClanWar, ClanWarLeagueGroup, ClanWarLog, GoldPassSeason, Location, Player, RankedClan, RankedPlayer, SeasonRankedPlayer } from '../struct';
|
|
8
8
|
import { CapitalRaidSeason } from '../struct/CapitalRaidSeason';
|
|
9
9
|
interface IClientEvents {
|
|
10
10
|
[ClientEvents.Error]: [error: unknown];
|
package/dist/client/Client.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Client = void 0;
|
|
4
4
|
const node_events_1 = require("node:events");
|
|
5
|
-
const Constants_1 = require("../util/Constants");
|
|
6
5
|
const HTTPError_1 = require("../rest/HTTPError");
|
|
7
6
|
const RESTManager_1 = require("../rest/RESTManager");
|
|
7
|
+
const Constants_1 = require("../util/Constants");
|
|
8
8
|
const Util_1 = require("../util/Util");
|
|
9
9
|
const struct_1 = require("../struct");
|
|
10
10
|
const CapitalRaidSeason_1 = require("../struct/CapitalRaidSeason");
|
|
@@ -75,8 +75,8 @@ class Client extends node_events_1.EventEmitter {
|
|
|
75
75
|
}
|
|
76
76
|
/** Get info about currently running war (normal or friendly) in the clan. */
|
|
77
77
|
async getClanWar(clanTag, options) {
|
|
78
|
-
const { data,
|
|
79
|
-
return new struct_1.ClanWar(this, data, { clanTag, maxAge });
|
|
78
|
+
const { data, res } = await this.rest.getCurrentWar(clanTag, options);
|
|
79
|
+
return new struct_1.ClanWar(this, data, { clanTag, maxAge: res.maxAge });
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Get info about currently running war in the clan.
|
|
@@ -166,8 +166,8 @@ class Client extends node_events_1.EventEmitter {
|
|
|
166
166
|
/** Get info about a CWL round by WarTag. */
|
|
167
167
|
async getClanWarLeagueRound(warTag, options) {
|
|
168
168
|
const args = typeof warTag === 'string' ? { warTag } : { warTag: warTag.warTag, clanTag: warTag.clanTag };
|
|
169
|
-
const { data,
|
|
170
|
-
return new struct_1.ClanWar(this, data, { warTag: args.warTag, clanTag: args.clanTag, maxAge });
|
|
169
|
+
const { data, res } = await this.rest.getClanWarLeagueRound(args.warTag, options);
|
|
170
|
+
return new struct_1.ClanWar(this, data, { warTag: args.warTag, clanTag: args.clanTag, maxAge: res.maxAge });
|
|
171
171
|
}
|
|
172
172
|
/** Get info about a player by tag. */
|
|
173
173
|
async getPlayer(playerTag, options) {
|
|
@@ -155,7 +155,7 @@ class PollingClient extends Client_1.Client {
|
|
|
155
155
|
if (!(this.listenerCount(Constants_1.PollingEvents.MaintenanceStart) && this.listenerCount(Constants_1.PollingEvents.MaintenanceEnd)))
|
|
156
156
|
return;
|
|
157
157
|
try {
|
|
158
|
-
const res = await this.rest.getClans({ maxMembers: Math.floor(Math.random() * 40) + 10, limit: 1 });
|
|
158
|
+
const { res } = await this.rest.getClans({ maxMembers: Math.floor(Math.random() * 40) + 10, limit: 1 });
|
|
159
159
|
if (res.status === 200 && this.inMaintenance) {
|
|
160
160
|
this.inMaintenance = Boolean(false);
|
|
161
161
|
const duration = Date.now() - this._maintenanceStartTime.getTime();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export * from './client/Client';
|
|
2
2
|
export * from './client/PollingClient';
|
|
3
|
+
export * from './rest/HTTPError';
|
|
3
4
|
export * from './rest/RESTManager';
|
|
4
5
|
export * from './rest/RequestHandler';
|
|
5
|
-
export * from './rest/HTTPError';
|
|
6
6
|
export * from './rest/Throttler';
|
|
7
|
-
export * from './util/Util';
|
|
8
7
|
export * from './struct';
|
|
9
8
|
export * from './types';
|
|
10
9
|
export * from './util/Constants';
|
|
11
10
|
export * from './util/Store';
|
|
11
|
+
export * from './util/Util';
|
package/dist/index.js
CHANGED
|
@@ -16,12 +16,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./client/Client"), exports);
|
|
18
18
|
__exportStar(require("./client/PollingClient"), exports);
|
|
19
|
+
__exportStar(require("./rest/HTTPError"), exports);
|
|
19
20
|
__exportStar(require("./rest/RESTManager"), exports);
|
|
20
21
|
__exportStar(require("./rest/RequestHandler"), exports);
|
|
21
|
-
__exportStar(require("./rest/HTTPError"), exports);
|
|
22
22
|
__exportStar(require("./rest/Throttler"), exports);
|
|
23
|
-
__exportStar(require("./util/Util"), exports);
|
|
24
23
|
__exportStar(require("./struct"), exports);
|
|
25
24
|
__exportStar(require("./types"), exports);
|
|
26
25
|
__exportStar(require("./util/Constants"), exports);
|
|
27
26
|
__exportStar(require("./util/Store"), exports);
|
|
27
|
+
__exportStar(require("./util/Util"), exports);
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
-
import {
|
|
4
|
-
import { APIClan, APIClanList, APIClanMemberList, APICapitalRaidSeasons, APIClanRankingList, APIClanBuilderBaseRankingList, APIClanWar, APIClanWarLeagueGroup, APIClanWarLog, APIGoldPassSeason, APILabelList, APILeague, APILeagueList, APILeagueSeasonList, APILocation, APILocationList, APIPlayer, APIPlayerRankingList, APIPlayerSeasonRankingList, APIPlayerBuilderBaseRankingList, APIVerifyToken, APIWarLeague, APIWarLeagueList, SearchOptions, ClanSearchOptions, RESTOptions, OverrideOptions, LoginOptions, APICapitalLeagueList, APICapitalLeague, APIClanCapitalRankingList, APIBuilderBaseLeagueList, APIBuilderBaseLeague } from '../types';
|
|
3
|
+
import { APIBuilderBaseLeague, APIBuilderBaseLeagueList, APICapitalLeague, APICapitalLeagueList, APICapitalRaidSeasons, APIClan, APIClanBuilderBaseRankingList, APIClanCapitalRankingList, APIClanList, APIClanMemberList, APIClanRankingList, APIClanWar, APIClanWarLeagueGroup, APIClanWarLog, APIGoldPassSeason, APILabelList, APILeague, APILeagueList, APILeagueSeasonList, APILocation, APILocationList, APIPlayer, APIPlayerBuilderBaseRankingList, APIPlayerRankingList, APIPlayerSeasonRankingList, APIVerifyToken, APIWarLeague, APIWarLeagueList, ClanSearchOptions, LoginOptions, OverrideOptions, RESTOptions, SearchOptions } from '../types';
|
|
5
4
|
import { RestEvents } from '../util/Constants';
|
|
5
|
+
import { Util } from '../util/Util';
|
|
6
6
|
import { RequestHandler } from './RequestHandler';
|
|
7
7
|
export interface IRestEvents {
|
|
8
8
|
[RestEvents.Error]: [error: unknown];
|
package/dist/rest/RESTManager.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RESTManager = void 0;
|
|
4
4
|
const node_events_1 = require("node:events");
|
|
5
|
-
const Util_1 = require("../util/Util");
|
|
6
5
|
const Constants_1 = require("../util/Constants");
|
|
6
|
+
const Util_1 = require("../util/Util");
|
|
7
7
|
const RequestHandler_1 = require("./RequestHandler");
|
|
8
8
|
/** Represents a REST Manager of the client. */
|
|
9
9
|
class RESTManager extends node_events_1.EventEmitter {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
-
import {
|
|
3
|
+
import { LoginOptions, RequestHandlerOptions, RequestOptions, Response } from '../types';
|
|
4
4
|
import { IRestEvents } from './RESTManager';
|
|
5
5
|
export interface RequestHandler {
|
|
6
6
|
emit: (<K extends keyof IRestEvents>(event: K, ...args: IRestEvents[K]) => boolean) & (<S extends string | symbol>(event: Exclude<S, keyof IRestEvents>, ...args: any[]) => boolean);
|
|
@@ -27,6 +27,7 @@ export interface RequestHandler {
|
|
|
27
27
|
*/
|
|
28
28
|
rateLimited: string;
|
|
29
29
|
}
|
|
30
|
+
export type ResponseBody = any;
|
|
30
31
|
/** Represents the class that manages handlers for endpoints. */
|
|
31
32
|
export declare class RequestHandler extends EventEmitter {
|
|
32
33
|
#private;
|
|
@@ -42,6 +43,7 @@ export declare class RequestHandler extends EventEmitter {
|
|
|
42
43
|
private readonly restRequestTimeout;
|
|
43
44
|
private readonly throttler?;
|
|
44
45
|
private readonly cached;
|
|
46
|
+
private readonly dispatcher;
|
|
45
47
|
constructor(options?: RequestHandlerOptions);
|
|
46
48
|
private get _keys();
|
|
47
49
|
private get _key();
|
|
@@ -1,27 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
26
3
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
27
4
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
@@ -33,20 +10,16 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
33
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
34
11
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
35
12
|
};
|
|
36
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
-
};
|
|
39
13
|
var _RequestHandler_keyIndex;
|
|
40
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
15
|
exports.RequestHandler = void 0;
|
|
42
|
-
const node_https_1 = __importDefault(require("node:https"));
|
|
43
16
|
const node_events_1 = require("node:events");
|
|
44
|
-
const
|
|
17
|
+
const undici_1 = require("undici");
|
|
45
18
|
const Constants_1 = require("../util/Constants");
|
|
46
19
|
const Store_1 = require("../util/Store");
|
|
20
|
+
const Util_1 = require("../util/Util");
|
|
47
21
|
const HTTPError_1 = require("./HTTPError");
|
|
48
22
|
const IP_REGEX = /\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}/g;
|
|
49
|
-
const agent = new node_https_1.default.Agent({ keepAlive: true });
|
|
50
23
|
/** Represents the class that manages handlers for endpoints. */
|
|
51
24
|
class RequestHandler extends node_events_1.EventEmitter {
|
|
52
25
|
constructor(options) {
|
|
@@ -62,6 +35,10 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
62
35
|
this.cached = options.cache;
|
|
63
36
|
else
|
|
64
37
|
this.cached = options?.cache === true ? new Store_1.CacheStore() : null;
|
|
38
|
+
this.dispatcher = new undici_1.Pool(new URL(this.baseURL).origin, {
|
|
39
|
+
connections: options?.connections ?? null,
|
|
40
|
+
pipelining: options?.pipelining ?? 1
|
|
41
|
+
});
|
|
65
42
|
}
|
|
66
43
|
get _keys() {
|
|
67
44
|
return Array.isArray(this.keys) ? this.keys : [this.keys];
|
|
@@ -81,7 +58,10 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
81
58
|
async request(path, options = {}) {
|
|
82
59
|
const cached = this.cached ? (await this.cached.get(path)) ?? null : null;
|
|
83
60
|
if (cached && options.force !== true) {
|
|
84
|
-
return {
|
|
61
|
+
return {
|
|
62
|
+
data: cached.data,
|
|
63
|
+
res: { maxAge: cached.ttl - Date.now(), status: cached.status, path, ok: cached.status === 200 }
|
|
64
|
+
};
|
|
85
65
|
}
|
|
86
66
|
if (!this.throttler || options.ignoreRateLimit)
|
|
87
67
|
return this.exec(path, options);
|
|
@@ -90,44 +70,50 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
90
70
|
}
|
|
91
71
|
async exec(path, options = {}, retries = 0) {
|
|
92
72
|
try {
|
|
93
|
-
const res = await
|
|
94
|
-
|
|
73
|
+
const res = await this.dispatcher.request({
|
|
74
|
+
path: `/v1${path}`,
|
|
95
75
|
body: options.body,
|
|
96
|
-
method:
|
|
97
|
-
|
|
76
|
+
method: 'GET',
|
|
77
|
+
signal: (0, Util_1.timeoutSignal)(options.restRequestTimeout ?? this.restRequestTimeout),
|
|
98
78
|
headers: { 'Authorization': `Bearer ${this._key}`, 'Content-Type': 'application/json' }
|
|
99
79
|
});
|
|
100
|
-
if (res.
|
|
80
|
+
if (res.statusCode === 504 && retries < (options.retryLimit ?? this.retryLimit)) {
|
|
101
81
|
return await this.exec(path, options, ++retries);
|
|
102
82
|
}
|
|
103
|
-
const data = await res.json();
|
|
83
|
+
const data = (await res.body.json());
|
|
104
84
|
if (this.creds &&
|
|
105
|
-
res.
|
|
106
|
-
data
|
|
85
|
+
res.statusCode === 403 &&
|
|
86
|
+
data?.reason === 'accessDenied.invalidIp' &&
|
|
107
87
|
retries < (options.retryLimit ?? this.retryLimit)) {
|
|
108
88
|
const keys = await this.reValidateKeys().then(() => () => this.login());
|
|
109
89
|
if (keys.length)
|
|
110
90
|
return await this.exec(path, options, ++retries);
|
|
111
91
|
}
|
|
112
|
-
const maxAge = Number(res.headers
|
|
113
|
-
if (res.
|
|
114
|
-
throw new HTTPError_1.HTTPError(HTTPError_1.PrivateWarLogError, res.
|
|
92
|
+
const maxAge = Number(res.headers['cache-control']?.split('=')?.[1] ?? 0) * 1000;
|
|
93
|
+
if (res.statusCode === 403 && !data?.message && this.rejectIfNotValid) {
|
|
94
|
+
throw new HTTPError_1.HTTPError(HTTPError_1.PrivateWarLogError, res.statusCode, path, maxAge);
|
|
115
95
|
}
|
|
116
|
-
if (
|
|
117
|
-
throw new HTTPError_1.HTTPError(data, res.
|
|
96
|
+
if (res.statusCode !== 200 && this.rejectIfNotValid) {
|
|
97
|
+
throw new HTTPError_1.HTTPError(data, res.statusCode, path, maxAge, options.method);
|
|
118
98
|
}
|
|
119
|
-
if (this.cached && maxAge > 0 && options.cache !== false && res.
|
|
120
|
-
await this.cached.set(path, { data, ttl: Date.now() + maxAge, status: res.
|
|
99
|
+
if (this.cached && maxAge > 0 && options.cache !== false && res.statusCode === 200) {
|
|
100
|
+
await this.cached.set(path, { data, ttl: Date.now() + maxAge, status: res.statusCode }, maxAge);
|
|
121
101
|
}
|
|
122
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
data: data,
|
|
104
|
+
res: { maxAge, status: res.statusCode, path, ok: res.statusCode === 200 }
|
|
105
|
+
};
|
|
123
106
|
}
|
|
124
107
|
catch (error) {
|
|
125
|
-
if (error
|
|
108
|
+
if (error.code === 'UND_ERR_ABORTED' && retries < (options.retryLimit ?? this.retryLimit)) {
|
|
126
109
|
return this.exec(path, options, ++retries);
|
|
127
110
|
}
|
|
128
111
|
if (this.rejectIfNotValid)
|
|
129
112
|
throw error;
|
|
130
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
data: { message: error.message },
|
|
115
|
+
res: { maxAge: 0, status: 500, path, ok: false }
|
|
116
|
+
};
|
|
131
117
|
}
|
|
132
118
|
}
|
|
133
119
|
async init(options) {
|
|
@@ -143,9 +129,9 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
143
129
|
}
|
|
144
130
|
async reValidateKeys() {
|
|
145
131
|
for (const key of this.keys) {
|
|
146
|
-
const res = await (0,
|
|
132
|
+
const res = await (0, undici_1.fetch)(`${this.baseURL}/locations?limit=1`, {
|
|
147
133
|
method: 'GET',
|
|
148
|
-
|
|
134
|
+
signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
|
|
149
135
|
headers: { 'Authorization': `Bearer ${key}`, 'Content-Type': 'application/json' }
|
|
150
136
|
}).catch(() => null);
|
|
151
137
|
if (res?.status === 403) {
|
|
@@ -156,13 +142,13 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
156
142
|
}
|
|
157
143
|
}
|
|
158
144
|
async login() {
|
|
159
|
-
const res = await (0,
|
|
145
|
+
const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/login`, {
|
|
160
146
|
method: 'POST',
|
|
161
|
-
|
|
147
|
+
signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
|
|
162
148
|
headers: { 'Content-Type': 'application/json' },
|
|
163
149
|
body: JSON.stringify({ email: this.email, password: this.password })
|
|
164
150
|
});
|
|
165
|
-
const data = await res.json();
|
|
151
|
+
const data = (await res.json());
|
|
166
152
|
if (!res.ok)
|
|
167
153
|
throw new Error(`Invalid email or password. ${JSON.stringify(data)}`);
|
|
168
154
|
const ip = await this.getIp(data.temporaryAPIToken);
|
|
@@ -171,12 +157,12 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
171
157
|
return this.getKeys(res.headers.get('set-cookie'), ip);
|
|
172
158
|
}
|
|
173
159
|
async getKeys(cookie, ip) {
|
|
174
|
-
const res = await (0,
|
|
160
|
+
const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/apikey/list`, {
|
|
175
161
|
method: 'POST',
|
|
176
|
-
|
|
162
|
+
signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
|
|
177
163
|
headers: { 'Content-Type': 'application/json', cookie }
|
|
178
164
|
});
|
|
179
|
-
const data = await res.json();
|
|
165
|
+
const data = (await res.json());
|
|
180
166
|
if (!res.ok)
|
|
181
167
|
throw new Error(`Failed to retrieve the API Keys. ${JSON.stringify(data)}`);
|
|
182
168
|
// Get all available keys from the developer site.
|
|
@@ -213,18 +199,18 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
213
199
|
return this.keys;
|
|
214
200
|
}
|
|
215
201
|
async revokeKey(keyId, cookie) {
|
|
216
|
-
const res = await (0,
|
|
202
|
+
const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/apikey/revoke`, {
|
|
217
203
|
method: 'POST',
|
|
218
|
-
|
|
204
|
+
signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
|
|
219
205
|
body: JSON.stringify({ id: keyId }),
|
|
220
206
|
headers: { 'Content-Type': 'application/json', cookie }
|
|
221
207
|
});
|
|
222
208
|
return res.ok;
|
|
223
209
|
}
|
|
224
210
|
async createKey(cookie, ip) {
|
|
225
|
-
const res = await (0,
|
|
211
|
+
const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/apikey/create`, {
|
|
226
212
|
method: 'POST',
|
|
227
|
-
|
|
213
|
+
signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
|
|
228
214
|
headers: { 'Content-Type': 'application/json', cookie },
|
|
229
215
|
body: JSON.stringify({
|
|
230
216
|
cidrRanges: [ip],
|
|
@@ -232,7 +218,7 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
232
218
|
description: this.keyDescription ?? new Date().toUTCString()
|
|
233
219
|
})
|
|
234
220
|
});
|
|
235
|
-
const data = await res.json();
|
|
221
|
+
const data = (await res.json());
|
|
236
222
|
if (!res.ok)
|
|
237
223
|
throw new Error(`Failed to create API Key. ${JSON.stringify(data)}`);
|
|
238
224
|
return data.key;
|
|
@@ -244,7 +230,9 @@ class RequestHandler extends node_events_1.EventEmitter {
|
|
|
244
230
|
return props.cidrs[0].match(IP_REGEX)[0];
|
|
245
231
|
}
|
|
246
232
|
catch {
|
|
247
|
-
const body = await (0,
|
|
233
|
+
const body = await (0, undici_1.fetch)('https://api.ipify.org', {
|
|
234
|
+
signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout)
|
|
235
|
+
}).then((res) => res.text());
|
|
248
236
|
return body.match(IP_REGEX)?.[0] ?? null;
|
|
249
237
|
}
|
|
250
238
|
}
|
package/dist/struct/Clan.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { APICapitalLeague, APIChatLanguage, APIClan, APILabel, APIWarLeague, OverrideOptions } from '../types';
|
|
2
1
|
import { Client } from '../client/Client';
|
|
3
|
-
import {
|
|
4
|
-
import type { Player } from './Player';
|
|
5
|
-
import { Location } from './Location';
|
|
2
|
+
import { APICapitalLeague, APIChatLanguage, APIClan, APILabel, APIWarLeague, OverrideOptions } from '../types';
|
|
6
3
|
import { Badge } from './Badge';
|
|
7
4
|
import { ClanCapital } from './ClanCapital';
|
|
5
|
+
import { ClanMember } from './ClanMember';
|
|
6
|
+
import { Location } from './Location';
|
|
7
|
+
import type { Player } from './Player';
|
|
8
8
|
/** Represents a Clan. */
|
|
9
9
|
export declare class Clan {
|
|
10
10
|
client: Client;
|
package/dist/struct/Clan.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Clan = void 0;
|
|
4
|
-
const ClanMember_1 = require("./ClanMember");
|
|
5
|
-
const Location_1 = require("./Location");
|
|
6
4
|
const Badge_1 = require("./Badge");
|
|
7
5
|
const ClanCapital_1 = require("./ClanCapital");
|
|
6
|
+
const ClanMember_1 = require("./ClanMember");
|
|
7
|
+
const Location_1 = require("./Location");
|
|
8
8
|
/** Represents a Clan. */
|
|
9
9
|
class Clan {
|
|
10
10
|
constructor(client, data) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { APIClanMember, APIPlayerHouse, OverrideOptions } from '../types';
|
|
2
1
|
import { Client } from '../client/Client';
|
|
2
|
+
import { APIClanMember, APIPlayerHouse, OverrideOptions } from '../types';
|
|
3
3
|
import { League } from './League';
|
|
4
4
|
export declare class ClanMember {
|
|
5
5
|
client: Client;
|
package/dist/struct/ClanWar.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { APIClanWar, APIClanWarAttack, APIClanWarMember, APIWarClan } from '../types';
|
|
2
1
|
import { Client } from '../client/Client';
|
|
2
|
+
import { APIClanWar, APIClanWarAttack, APIClanWarMember, APIWarClan } from '../types';
|
|
3
3
|
import { Badge } from './Badge';
|
|
4
4
|
/** Represents a Clash of Clans War Attack. */
|
|
5
5
|
export declare class ClanWarAttack {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { APIClanWarLeagueClan, APIClanWarLeagueClanMember, APIClanWarLeagueGroup, APIClanWarLeagueRound, OverrideOptions } from '../types';
|
|
2
1
|
import { Client } from '../client/Client';
|
|
2
|
+
import { APIClanWarLeagueClan, APIClanWarLeagueClanMember, APIClanWarLeagueGroup, APIClanWarLeagueRound, OverrideOptions } from '../types';
|
|
3
|
+
import { Badge } from './Badge';
|
|
3
4
|
import { ClanWar } from './ClanWar';
|
|
4
5
|
import { Player } from './Player';
|
|
5
|
-
import { Badge } from './Badge';
|
|
6
6
|
/** Represents a Clan War League member. */
|
|
7
7
|
export declare class ClanWarLeagueClanMember {
|
|
8
8
|
/** The member's name. */
|
|
@@ -46,7 +46,7 @@ export declare class ClanWarLeagueRound {
|
|
|
46
46
|
export declare class ClanWarLeagueGroup {
|
|
47
47
|
private readonly client;
|
|
48
48
|
/** The CWL group's current war state. */
|
|
49
|
-
state: 'preparation' | 'inWar' | 'ended';
|
|
49
|
+
state: 'preparation' | 'inWar' | 'ended' | 'notInWar';
|
|
50
50
|
/** Season Id of this CWL group. */
|
|
51
51
|
season: string;
|
|
52
52
|
/** Returns all participating clans. */
|
|
@@ -54,6 +54,8 @@ export declare class ClanWarLeagueGroup {
|
|
|
54
54
|
/** An array containing all war tags for each round. */
|
|
55
55
|
rounds: ClanWarLeagueRound[];
|
|
56
56
|
constructor(client: Client, data: APIClanWarLeagueGroup);
|
|
57
|
+
/** Whether the clan is not in CWL group. */
|
|
58
|
+
get isNotInWar(): boolean;
|
|
57
59
|
/** Total number of rounds for this CWL. */
|
|
58
60
|
get totalRounds(): number;
|
|
59
61
|
/**
|
|
@@ -49,11 +49,16 @@ exports.ClanWarLeagueRound = ClanWarLeagueRound;
|
|
|
49
49
|
class ClanWarLeagueGroup {
|
|
50
50
|
constructor(client, data) {
|
|
51
51
|
this.client = client;
|
|
52
|
-
// @ts-expect-error
|
|
53
52
|
this.state = data.state;
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
if (this.state !== 'notInWar') {
|
|
54
|
+
this.season = data.season;
|
|
55
|
+
this.clans = data.clans.map((clan) => new ClanWarLeagueClan(client, clan));
|
|
56
|
+
this.rounds = data.rounds.map((round, i) => new ClanWarLeagueRound(round, i));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Whether the clan is not in CWL group. */
|
|
60
|
+
get isNotInWar() {
|
|
61
|
+
return this.state === 'notInWar';
|
|
57
62
|
}
|
|
58
63
|
/** Total number of rounds for this CWL. */
|
|
59
64
|
get totalRounds() {
|
package/dist/struct/Player.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { APIPlayer, APIPlayerHouse, OverrideOptions } from '../types';
|
|
2
1
|
import { Client } from '../client/Client';
|
|
3
|
-
import {
|
|
2
|
+
import { APIPlayer, APIPlayerHouse, OverrideOptions } from '../types';
|
|
4
3
|
import { Achievement } from './Achievement';
|
|
5
|
-
import { Hero, Spell, Troop } from './Unit';
|
|
6
|
-
import { PlayerClan } from './PlayerClan';
|
|
7
|
-
import { League } from './League';
|
|
8
4
|
import { Label } from './Label';
|
|
5
|
+
import { League } from './League';
|
|
6
|
+
import { LegendStatistics } from './LegendStatistics';
|
|
7
|
+
import { PlayerClan } from './PlayerClan';
|
|
8
|
+
import { Hero, Spell, Troop } from './Unit';
|
|
9
9
|
/** Represents a Clash of Clans Player. */
|
|
10
10
|
export declare class Player {
|
|
11
11
|
client: Client;
|
package/dist/struct/Player.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Player = void 0;
|
|
4
4
|
const Constants_1 = require("../util/Constants");
|
|
5
|
-
const LegendStatistics_1 = require("./LegendStatistics");
|
|
6
5
|
const Achievement_1 = require("./Achievement");
|
|
7
|
-
const Unit_1 = require("./Unit");
|
|
8
|
-
const PlayerClan_1 = require("./PlayerClan");
|
|
9
|
-
const League_1 = require("./League");
|
|
10
6
|
const Label_1 = require("./Label");
|
|
7
|
+
const League_1 = require("./League");
|
|
8
|
+
const LegendStatistics_1 = require("./LegendStatistics");
|
|
9
|
+
const PlayerClan_1 = require("./PlayerClan");
|
|
10
|
+
const Unit_1 = require("./Unit");
|
|
11
11
|
/** Represents a Clash of Clans Player. */
|
|
12
12
|
class Player {
|
|
13
13
|
constructor(client, data) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { OverrideOptions, APIPlayerClan } from '../types';
|
|
2
1
|
import { Client } from '../client/Client';
|
|
2
|
+
import { APIPlayerClan, OverrideOptions } from '../types';
|
|
3
3
|
import { Badge } from './Badge';
|
|
4
4
|
/** Represents a Player's clan. */
|
|
5
5
|
export declare class PlayerClan {
|
package/dist/struct/Ranking.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { APIClanRanking, APIClanBuilderBaseRanking, APIPlayerRanking, APIPlayerBuilderBaseRanking } from '../types';
|
|
2
1
|
import { Client } from '../client/Client';
|
|
3
|
-
import {
|
|
4
|
-
import { Location } from './Location';
|
|
5
|
-
import { League } from './League';
|
|
2
|
+
import { APIClanBuilderBaseRanking, APIClanRanking, APIPlayerBuilderBaseRanking, APIPlayerRanking } from '../types';
|
|
6
3
|
import { Badge } from './Badge';
|
|
4
|
+
import { League } from './League';
|
|
5
|
+
import { Location } from './Location';
|
|
6
|
+
import { PlayerClan } from './PlayerClan';
|
|
7
7
|
/** Represents the Player of seasonal legend league leader-board ranking. */
|
|
8
8
|
export declare class SeasonRankedPlayer {
|
|
9
9
|
/** The player's name. */
|
package/dist/struct/Ranking.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RankedClan = exports.RankedPlayer = exports.SeasonRankedPlayer = void 0;
|
|
4
4
|
const Constants_1 = require("../util/Constants");
|
|
5
|
-
const PlayerClan_1 = require("./PlayerClan");
|
|
6
|
-
const Location_1 = require("./Location");
|
|
7
|
-
const League_1 = require("./League");
|
|
8
5
|
const Badge_1 = require("./Badge");
|
|
6
|
+
const League_1 = require("./League");
|
|
7
|
+
const Location_1 = require("./Location");
|
|
8
|
+
const PlayerClan_1 = require("./PlayerClan");
|
|
9
9
|
/** Represents the Player of seasonal legend league leader-board ranking. */
|
|
10
10
|
class SeasonRankedPlayer {
|
|
11
11
|
constructor(client, data) {
|
package/dist/struct/Unit.d.ts
CHANGED
package/dist/struct/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export * from './Achievement';
|
|
2
2
|
export * from './Badge';
|
|
3
|
+
export * from './CapitalRaidSeason';
|
|
3
4
|
export * from './Clan';
|
|
5
|
+
export * from './ClanCapital';
|
|
4
6
|
export * from './ClanMember';
|
|
5
7
|
export * from './ClanWar';
|
|
6
|
-
export * from './ClanWarLog';
|
|
7
8
|
export * from './ClanWarLeagueGroup';
|
|
9
|
+
export * from './ClanWarLog';
|
|
8
10
|
export * from './Icon';
|
|
9
11
|
export * from './LegendStatistics';
|
|
10
12
|
export * from './Location';
|
|
@@ -13,5 +15,3 @@ export * from './PlayerClan';
|
|
|
13
15
|
export * from './Ranking';
|
|
14
16
|
export * from './Season';
|
|
15
17
|
export * from './Unit';
|
|
16
|
-
export * from './ClanCapital';
|
|
17
|
-
export * from './CapitalRaidSeason';
|
package/dist/struct/index.js
CHANGED
|
@@ -16,11 +16,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./Achievement"), exports);
|
|
18
18
|
__exportStar(require("./Badge"), exports);
|
|
19
|
+
__exportStar(require("./CapitalRaidSeason"), exports);
|
|
19
20
|
__exportStar(require("./Clan"), exports);
|
|
21
|
+
__exportStar(require("./ClanCapital"), exports);
|
|
20
22
|
__exportStar(require("./ClanMember"), exports);
|
|
21
23
|
__exportStar(require("./ClanWar"), exports);
|
|
22
|
-
__exportStar(require("./ClanWarLog"), exports);
|
|
23
24
|
__exportStar(require("./ClanWarLeagueGroup"), exports);
|
|
25
|
+
__exportStar(require("./ClanWarLog"), exports);
|
|
24
26
|
__exportStar(require("./Icon"), exports);
|
|
25
27
|
__exportStar(require("./LegendStatistics"), exports);
|
|
26
28
|
__exportStar(require("./Location"), exports);
|
|
@@ -29,5 +31,3 @@ __exportStar(require("./PlayerClan"), exports);
|
|
|
29
31
|
__exportStar(require("./Ranking"), exports);
|
|
30
32
|
__exportStar(require("./Season"), exports);
|
|
31
33
|
__exportStar(require("./Unit"), exports);
|
|
32
|
-
__exportStar(require("./ClanCapital"), exports);
|
|
33
|
-
__exportStar(require("./CapitalRaidSeason"), exports);
|
package/dist/types/lib.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BatchThrottler, QueueThrottler } from '../rest/Throttler';
|
|
2
2
|
export interface Store<T = any> {
|
|
3
3
|
set: (key: string, value: T, ttl?: number) => boolean | Promise<boolean>;
|
|
4
4
|
get: (key: string) => T | null | Promise<T | null>;
|
|
@@ -50,6 +50,10 @@ export interface PollingClientOptions extends ClientOptions {
|
|
|
50
50
|
export interface RequestHandlerOptions extends ClientOptions {
|
|
51
51
|
/** Set this `false` to use `res.ok` property. */
|
|
52
52
|
rejectIfNotValid?: boolean;
|
|
53
|
+
/** The max number of clients to create. null if no limit. Default null. */
|
|
54
|
+
connections?: number;
|
|
55
|
+
/** The amount of concurrent requests to be sent over the single TCP/TLS connection according to RFC7230. Default: 1 */
|
|
56
|
+
pipelining?: number;
|
|
53
57
|
}
|
|
54
58
|
/** Search options for request. */
|
|
55
59
|
export interface SearchOptions extends OverrideOptions {
|
|
@@ -88,16 +92,18 @@ export interface RequestOptions extends OverrideOptions {
|
|
|
88
92
|
method?: string;
|
|
89
93
|
}
|
|
90
94
|
export interface Response<T> {
|
|
91
|
-
/** Whether the response is ok. */
|
|
92
|
-
ok: boolean;
|
|
93
95
|
/** The response body. */
|
|
94
96
|
data: T;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
res: {
|
|
98
|
+
/** Whether the response is ok. */
|
|
99
|
+
ok: boolean;
|
|
100
|
+
/** Path of the request for this response. */
|
|
101
|
+
path: string;
|
|
102
|
+
/** HTTP status code of this response. */
|
|
103
|
+
status: number;
|
|
104
|
+
/** The maxAge of this response. */
|
|
105
|
+
maxAge: number;
|
|
106
|
+
};
|
|
101
107
|
}
|
|
102
108
|
/**
|
|
103
109
|
* Clan search options for a request.
|
package/dist/util/Util.d.ts
CHANGED
package/dist/util/Util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Util = void 0;
|
|
3
|
+
exports.Util = exports.timeoutSignal = void 0;
|
|
4
4
|
const Constants_1 = require("../util/Constants");
|
|
5
5
|
const TAG_CHARACTERS = '0289PYLQGRJCUV';
|
|
6
6
|
const params = [
|
|
@@ -16,6 +16,20 @@ const params = [
|
|
|
16
16
|
'after',
|
|
17
17
|
'before'
|
|
18
18
|
];
|
|
19
|
+
function timeoutSignal(timeout) {
|
|
20
|
+
if (!Number.isInteger(timeout)) {
|
|
21
|
+
throw new TypeError('Expected an integer for the timeout');
|
|
22
|
+
}
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
if (timeout > 0) {
|
|
25
|
+
const timeoutId = setTimeout(() => {
|
|
26
|
+
controller.abort();
|
|
27
|
+
}, timeout);
|
|
28
|
+
timeoutId.unref();
|
|
29
|
+
}
|
|
30
|
+
return controller.signal;
|
|
31
|
+
}
|
|
32
|
+
exports.timeoutSignal = timeoutSignal;
|
|
19
33
|
/** Contains various general-purpose utility methods. */
|
|
20
34
|
class Util extends null {
|
|
21
35
|
/**
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clashofclans.js",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3-dev.048e4b9",
|
|
4
4
|
"description": "JavaScript library for interacting with the Clash of Clans API",
|
|
5
|
-
"author": "
|
|
5
|
+
"author": "https://clashofclans.js.org",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"exports": {
|
|
@@ -42,25 +42,22 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"
|
|
45
|
+
"undici": "^5.23.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@types/node
|
|
49
|
-
"
|
|
50
|
-
"@
|
|
51
|
-
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
52
|
-
"@typescript-eslint/parser": "^5.4.0",
|
|
48
|
+
"@types/node": "^18.17.5",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
|
50
|
+
"@typescript-eslint/parser": "^6.3.0",
|
|
53
51
|
"dotenv": "^16.0.2",
|
|
54
|
-
"eslint": "^8.
|
|
55
|
-
"eslint-config-
|
|
56
|
-
"eslint-
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"typescript": "^4.7.4"
|
|
52
|
+
"eslint": "^8.47.0",
|
|
53
|
+
"eslint-config-prettier": "^9.0.0",
|
|
54
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
55
|
+
"gen-esm-wrapper": "^1.1.3",
|
|
56
|
+
"prettier": "^3.0.1",
|
|
57
|
+
"rimraf": "^5.0.1",
|
|
58
|
+
"typescript": "^5.1.6"
|
|
62
59
|
},
|
|
63
60
|
"engines": {
|
|
64
|
-
"node": ">=
|
|
61
|
+
"node": ">=16.x"
|
|
65
62
|
}
|
|
66
63
|
}
|