clashofclans.js 2.0.0-dev.ba3ae68 → 2.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.
- package/CHANGELOG.md +6 -5
- package/README.md +5 -5
- package/dist/client/Client.d.ts +55 -25
- package/dist/client/Client.js +65 -41
- package/dist/client/EventManager.d.ts +46 -20
- package/dist/client/EventManager.js +99 -53
- package/dist/rest/HTTPError.d.ts +17 -1
- package/dist/rest/HTTPError.js +26 -7
- package/dist/rest/RESTManager.d.ts +49 -120
- package/dist/rest/RESTManager.js +25 -1
- package/dist/rest/RequestHandler.d.ts +90 -6
- package/dist/rest/RequestHandler.js +24 -15
- package/dist/rest/Throttler.d.ts +0 -4
- package/dist/struct/Clan.d.ts +2 -1
- package/dist/struct/Clan.js +2 -2
- package/dist/struct/ClanMember.d.ts +2 -1
- package/dist/struct/ClanMember.js +2 -2
- package/dist/struct/ClanWar.d.ts +6 -4
- package/dist/struct/ClanWar.js +17 -3
- package/dist/struct/ClanWarLeagueGroup.d.ts +5 -3
- package/dist/struct/ClanWarLeagueGroup.js +12 -10
- package/dist/struct/ClanWarLog.d.ts +2 -2
- package/dist/struct/ClanWarLog.js +2 -2
- package/dist/struct/Player.d.ts +2 -1
- package/dist/struct/Player.js +7 -5
- package/dist/struct/PlayerClan.d.ts +2 -1
- package/dist/struct/PlayerClan.js +2 -2
- package/dist/struct/Unit.d.ts +37 -4
- package/dist/struct/Unit.js +49 -9
- package/dist/types/index.d.ts +3 -5
- package/dist/util/Constants.d.ts +5 -0
- package/dist/util/Constants.js +6 -1
- package/dist/util/Util.js +3 -1
- package/dist/util/raw.json +1 -0
- package/package.json +5 -5
|
@@ -11,18 +11,14 @@ export declare class RequestHandler {
|
|
|
11
11
|
private keys;
|
|
12
12
|
private readonly baseURL;
|
|
13
13
|
private readonly retryLimit;
|
|
14
|
-
private readonly cached;
|
|
15
14
|
private readonly restRequestTimeout;
|
|
16
15
|
private readonly throttler?;
|
|
16
|
+
private readonly cached;
|
|
17
17
|
constructor(options?: ClientOptions);
|
|
18
18
|
private get _keys();
|
|
19
19
|
private get _key();
|
|
20
20
|
setKeys(keys: string[]): this;
|
|
21
|
-
request<T>(path: string, options?: RequestOptions): Promise<
|
|
22
|
-
data: T;
|
|
23
|
-
maxAge: number;
|
|
24
|
-
status: number;
|
|
25
|
-
}>;
|
|
21
|
+
request<T>(path: string, options?: RequestOptions): Promise<Response<T>>;
|
|
26
22
|
private exec;
|
|
27
23
|
init(options: InitOptions): Promise<string[]>;
|
|
28
24
|
private reValidateKeys;
|
|
@@ -32,47 +28,135 @@ export declare class RequestHandler {
|
|
|
32
28
|
private createKey;
|
|
33
29
|
private getIp;
|
|
34
30
|
}
|
|
31
|
+
/** Options for a client. */
|
|
35
32
|
export interface ClientOptions {
|
|
33
|
+
/** Keys from Clash of Clans API developer site. */
|
|
36
34
|
keys?: string[];
|
|
35
|
+
/** Base URL of the Clash of Clans API. */
|
|
37
36
|
baseURL?: string;
|
|
37
|
+
/**
|
|
38
|
+
* How many times to retry on 5XX errors.
|
|
39
|
+
*/
|
|
38
40
|
retryLimit?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Whether enable or disable internal caching.
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* const client = new Client({ cache: true });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
39
48
|
cache?: boolean | Keyv;
|
|
49
|
+
/** Time to wait before cancelling a REST request, in milliseconds. */
|
|
40
50
|
restRequestTimeout?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Throttler class which handles rate-limit
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* const client = new Client({ throttler: new QueueThrottler(1000 / 10) });
|
|
56
|
+
* ```
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const client = new Client({ throttler: new BatchThrottler(30) });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
41
62
|
throttler?: QueueThrottler | BatchThrottler;
|
|
42
63
|
}
|
|
64
|
+
/** Search options for request. */
|
|
43
65
|
export interface SearchOptions extends OverrideOptions {
|
|
66
|
+
/** Limit the number of items returned in the response. */
|
|
44
67
|
limit?: number;
|
|
68
|
+
/**
|
|
69
|
+
* Return only items that occur after this marker.
|
|
70
|
+
* Before marker can be found from the response, inside the 'paging' property.
|
|
71
|
+
* Note that only after or before can be specified for a request, not both.
|
|
72
|
+
*/
|
|
45
73
|
after?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Return only items that occur before this marker.
|
|
76
|
+
* Before marker can be found from the response, inside the 'paging' property.
|
|
77
|
+
* Note that only after or before can be specified for a request, not both.
|
|
78
|
+
*/
|
|
46
79
|
before?: string;
|
|
47
80
|
}
|
|
81
|
+
/** Override options for a request. */
|
|
48
82
|
export interface OverrideOptions {
|
|
83
|
+
/** Whether to cache this response. */
|
|
49
84
|
cache?: boolean;
|
|
85
|
+
/** Whether to skip the cache check and request the API. */
|
|
50
86
|
force?: boolean;
|
|
87
|
+
/** How many times to retry on 5XX errors. */
|
|
51
88
|
retryLimit?: string;
|
|
89
|
+
/** Whether to ignore throttlers. */
|
|
52
90
|
ignoreRateLimit?: boolean;
|
|
91
|
+
/** Time to wait before cancelling a REST request, in milliseconds. */
|
|
53
92
|
restRequestTimeout?: number;
|
|
54
93
|
}
|
|
55
94
|
export interface RequestOptions extends OverrideOptions {
|
|
95
|
+
/** The request body. */
|
|
56
96
|
body?: string;
|
|
97
|
+
/** The request method. */
|
|
57
98
|
method?: string;
|
|
58
99
|
}
|
|
100
|
+
export interface Response<T> {
|
|
101
|
+
/** The response body. */
|
|
102
|
+
data: T;
|
|
103
|
+
/** Path of the request for this response. */
|
|
104
|
+
path: string;
|
|
105
|
+
/** HTTP status code of this response. */
|
|
106
|
+
status: number;
|
|
107
|
+
/** The maxAge of this response. */
|
|
108
|
+
maxAge: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Clan search options for a request.
|
|
112
|
+
*
|
|
113
|
+
* ::info
|
|
114
|
+
* If name is used as part of search query, it needs to be at least three characters long.
|
|
115
|
+
* Name search parameter is interpreted as wild card search, so it may appear anywhere in the clan name.
|
|
116
|
+
* :::
|
|
117
|
+
*/
|
|
59
118
|
export interface ClanSearchOptions {
|
|
119
|
+
/** Search clans by name. */
|
|
60
120
|
name?: string;
|
|
121
|
+
/** Filter by minimum number of clan members. */
|
|
61
122
|
minMembers?: number;
|
|
123
|
+
/** Filter by maximum number of clan members. */
|
|
62
124
|
maxMembers?: number;
|
|
125
|
+
/** Filter by minimum amount of clan points. */
|
|
63
126
|
minClanPoints?: number;
|
|
127
|
+
/** Filter by minimum clan level. */
|
|
64
128
|
minClanLevel?: number;
|
|
129
|
+
/** Filter by clan war frequency. */
|
|
65
130
|
warFrequency?: string;
|
|
131
|
+
/** Filter by clan location identifier. For list of available locations, refer to getLocations operation. */
|
|
66
132
|
locationId?: string;
|
|
133
|
+
/** Comma separated list of label IDs to use for filtering results. */
|
|
67
134
|
labelIds?: string;
|
|
135
|
+
/** Limit the number of items returned in the response. */
|
|
68
136
|
limit?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Return only items that occur after this marker.
|
|
139
|
+
* Before marker can be found from the response, inside the 'paging' property.
|
|
140
|
+
* Note that only after or before can be specified for a request, not both.
|
|
141
|
+
*/
|
|
69
142
|
after?: string;
|
|
143
|
+
/**
|
|
144
|
+
* Return only items that occur before this marker.
|
|
145
|
+
* Before marker can be found from the response, inside the 'paging' property.
|
|
146
|
+
* Note that only after or before can be specified for a request, not both.
|
|
147
|
+
*/
|
|
70
148
|
before?: string;
|
|
71
149
|
}
|
|
150
|
+
/** Login options for a client. */
|
|
72
151
|
export interface InitOptions {
|
|
152
|
+
/** Developer site email address. */
|
|
73
153
|
email: string;
|
|
154
|
+
/** Developer site password. */
|
|
74
155
|
password: string;
|
|
156
|
+
/** Name of API key(s). */
|
|
75
157
|
keyName?: string;
|
|
158
|
+
/** Number of allowed API keys. */
|
|
76
159
|
keyCount?: number;
|
|
160
|
+
/** Description of API key(s). */
|
|
77
161
|
keyDescription?: string;
|
|
78
162
|
}
|
|
@@ -50,8 +50,9 @@ class RequestHandler {
|
|
|
50
50
|
}
|
|
51
51
|
async request(path, options = {}) {
|
|
52
52
|
const cached = (await this.cached?.get(path)) ?? null;
|
|
53
|
-
if (cached && options.force !== true)
|
|
54
|
-
return { data: cached, maxAge:
|
|
53
|
+
if (cached && options.force !== true) {
|
|
54
|
+
return { data: cached.data, maxAge: cached.ttl - Date.now(), status: 200, path };
|
|
55
|
+
}
|
|
55
56
|
if (!this.throttler || options.ignoreRateLimit)
|
|
56
57
|
return this.exec(path, options);
|
|
57
58
|
await this.throttler.wait();
|
|
@@ -74,15 +75,19 @@ class RequestHandler {
|
|
|
74
75
|
if (!res && retries < (options.retryLimit ?? this.retryLimit))
|
|
75
76
|
return this.exec(path, options, ++retries);
|
|
76
77
|
if (res?.status === 403 && data?.reason === 'accessDenied.invalidIp' && this.email && this.password) {
|
|
77
|
-
await this.login();
|
|
78
|
-
|
|
78
|
+
const keys = await this.reValidateKeys().then(() => this.login());
|
|
79
|
+
if (keys.length)
|
|
80
|
+
return this.exec(path, options, ++retries);
|
|
79
81
|
}
|
|
82
|
+
const maxAge = Number(res?.headers.get('cache-control')?.split('=')?.[1] ?? 0) * 1000;
|
|
83
|
+
if (res?.status === 403 && !data?.message)
|
|
84
|
+
throw new HTTPError_1.HTTPError(HTTPError_1.PrivateWarLogError, res.status, path, maxAge);
|
|
80
85
|
if (!res?.ok)
|
|
81
|
-
throw new HTTPError_1.HTTPError(data, res?.status ?? 504, path, options.method);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return { data, maxAge, status: res.status };
|
|
86
|
+
throw new HTTPError_1.HTTPError(data, res?.status ?? 504, path, maxAge, options.method);
|
|
87
|
+
if (this.cached && maxAge > 0 && options.cache !== false) {
|
|
88
|
+
await this.cached.set(path, { data, ttl: Date.now() + maxAge }, maxAge);
|
|
89
|
+
}
|
|
90
|
+
return { data, maxAge, status: res.status, path };
|
|
86
91
|
}
|
|
87
92
|
async init(options) {
|
|
88
93
|
if (!(options.email && options.password))
|
|
@@ -97,11 +102,12 @@ class RequestHandler {
|
|
|
97
102
|
}
|
|
98
103
|
async reValidateKeys() {
|
|
99
104
|
for (const key of this.keys) {
|
|
100
|
-
const res = await (0, node_fetch_1.default)(`${this.baseURL}/locations`, {
|
|
105
|
+
const res = await (0, node_fetch_1.default)(`${this.baseURL}/locations?limit=1`, {
|
|
101
106
|
method: 'GET',
|
|
107
|
+
timeout: 10000,
|
|
102
108
|
headers: { 'Authorization': `Bearer ${key}`, 'Content-Type': 'application/json' }
|
|
103
|
-
});
|
|
104
|
-
if (res
|
|
109
|
+
}).catch(() => null);
|
|
110
|
+
if (res?.status === 403) {
|
|
105
111
|
const index = this.keys.indexOf(key);
|
|
106
112
|
this.keys.splice(index, 1);
|
|
107
113
|
console.warn(`[WARN] Pre-defined key #${index + 1} is no longer valid. Removed from the key list.`);
|
|
@@ -111,6 +117,7 @@ class RequestHandler {
|
|
|
111
117
|
async login() {
|
|
112
118
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/login`, {
|
|
113
119
|
method: 'POST',
|
|
120
|
+
timeout: 10000,
|
|
114
121
|
headers: { 'Content-Type': 'application/json' },
|
|
115
122
|
body: JSON.stringify({ email: this.email, password: this.password })
|
|
116
123
|
});
|
|
@@ -123,14 +130,14 @@ class RequestHandler {
|
|
|
123
130
|
const ip = await this.getIp();
|
|
124
131
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/apikey/list`, {
|
|
125
132
|
method: 'POST',
|
|
133
|
+
timeout: 10000,
|
|
126
134
|
headers: { 'Content-Type': 'application/json', cookie }
|
|
127
135
|
});
|
|
128
136
|
const data = await res.json();
|
|
129
137
|
// Get all available keys from the developer site.
|
|
130
138
|
const keys = (data.keys ?? []);
|
|
131
139
|
// Revoke keys for specified key name but not matching current IP address.
|
|
132
|
-
const
|
|
133
|
-
for (const key of expiredKeys) {
|
|
140
|
+
for (const key of keys.filter((key) => key.name === this.keyName && !key.cidrRanges.includes(ip))) {
|
|
134
141
|
if (!(await this.revokeKey(key.id, cookie)))
|
|
135
142
|
continue;
|
|
136
143
|
const index = keys.findIndex(({ id }) => id === key.id);
|
|
@@ -163,6 +170,7 @@ class RequestHandler {
|
|
|
163
170
|
async revokeKey(keyId, cookie) {
|
|
164
171
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/apikey/revoke`, {
|
|
165
172
|
method: 'POST',
|
|
173
|
+
timeout: 10000,
|
|
166
174
|
body: JSON.stringify({ id: keyId }),
|
|
167
175
|
headers: { 'Content-Type': 'application/json', cookie }
|
|
168
176
|
});
|
|
@@ -171,6 +179,7 @@ class RequestHandler {
|
|
|
171
179
|
async createKey(cookie, ip) {
|
|
172
180
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/apikey/create`, {
|
|
173
181
|
method: 'POST',
|
|
182
|
+
timeout: 10000,
|
|
174
183
|
headers: { 'Content-Type': 'application/json', cookie },
|
|
175
184
|
body: JSON.stringify({
|
|
176
185
|
cidrRanges: [ip],
|
|
@@ -182,7 +191,7 @@ class RequestHandler {
|
|
|
182
191
|
return data.key;
|
|
183
192
|
}
|
|
184
193
|
async getIp() {
|
|
185
|
-
return (0, node_fetch_1.default)('https://api.ipify.org/').then((res) => res.text());
|
|
194
|
+
return (0, node_fetch_1.default)('https://api.ipify.org/', { timeout: 10000 }).then((res) => res.text());
|
|
186
195
|
}
|
|
187
196
|
}
|
|
188
197
|
exports.RequestHandler = RequestHandler;
|
package/dist/rest/Throttler.d.ts
CHANGED
package/dist/struct/Clan.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { ChatLanguage } from './ChatLanguage';
|
|
2
3
|
import { ClanMember } from './ClanMember';
|
|
3
4
|
import { Client } from '../client/Client';
|
|
@@ -59,5 +60,5 @@ export declare class Clan {
|
|
|
59
60
|
members: ClanMember[];
|
|
60
61
|
constructor(client: Client, data: APIClan);
|
|
61
62
|
/** Get {@link Player} information for every Player in the clan. */
|
|
62
|
-
fetchMembers(): Promise<Player[]>;
|
|
63
|
+
fetchMembers(options?: OverrideOptions): Promise<Player[]>;
|
|
63
64
|
}
|
package/dist/struct/Clan.js
CHANGED
|
@@ -35,8 +35,8 @@ class Clan {
|
|
|
35
35
|
this.members = data.memberList?.map((mem) => new ClanMember_1.ClanMember(this.client, mem)) ?? []; // eslint-disable-line
|
|
36
36
|
}
|
|
37
37
|
/** Get {@link Player} information for every Player in the clan. */
|
|
38
|
-
async fetchMembers() {
|
|
39
|
-
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ignoreRateLimit: true }))))
|
|
38
|
+
async fetchMembers(options) {
|
|
39
|
+
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ...options, ignoreRateLimit: true }))))
|
|
40
40
|
.filter((res) => res.status === 'fulfilled')
|
|
41
41
|
.map((res) => res.value);
|
|
42
42
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { Client } from '../client/Client';
|
|
2
3
|
import { APIClanMember } from '../types';
|
|
3
4
|
import { League } from './League';
|
|
@@ -27,5 +28,5 @@ export declare class ClanMember {
|
|
|
27
28
|
received: number;
|
|
28
29
|
constructor(client: Client, data: APIClanMember);
|
|
29
30
|
/** Fetch detailed clan info for the member's clan. */
|
|
30
|
-
fetch(): Promise<import("./Player").Player>;
|
|
31
|
+
fetch(options?: OverrideOptions): Promise<import("./Player").Player>;
|
|
31
32
|
}
|
|
@@ -21,8 +21,8 @@ class ClanMember {
|
|
|
21
21
|
this.received = data.donationsReceived;
|
|
22
22
|
}
|
|
23
23
|
/** Fetch detailed clan info for the member's clan. */
|
|
24
|
-
async fetch() {
|
|
25
|
-
return this.client.getPlayer(this.tag);
|
|
24
|
+
async fetch(options) {
|
|
25
|
+
return this.client.getPlayer(this.tag, options);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
exports.ClanMember = ClanMember;
|
package/dist/struct/ClanWar.d.ts
CHANGED
|
@@ -116,12 +116,12 @@ export declare class ClanWar {
|
|
|
116
116
|
opponent: WarClan;
|
|
117
117
|
/** The war's unique tag. This is `null` unless this is a CWL. */
|
|
118
118
|
warTag: string | null;
|
|
119
|
-
/**
|
|
119
|
+
/** Maximum number of milliseconds the results can be cached. */
|
|
120
120
|
maxAge: number;
|
|
121
121
|
constructor(client: Client, data: APIClanWar, extra: {
|
|
122
122
|
clanTag?: string;
|
|
123
123
|
warTag?: string;
|
|
124
|
-
maxAge
|
|
124
|
+
maxAge: number;
|
|
125
125
|
});
|
|
126
126
|
/** Return a {@link ClanWarMember} with the tag provided. */
|
|
127
127
|
getMember(tag: string): ClanWarMember | null;
|
|
@@ -129,7 +129,9 @@ export declare class ClanWar {
|
|
|
129
129
|
getAttack(attackerTag: string, defenderTag: string): ClanWarAttack | null;
|
|
130
130
|
/** Return a list of {@link ClanWarAttack} for the defenderTag provided. */
|
|
131
131
|
getDefenses(defenderTag: string): ClanWarAttack[];
|
|
132
|
-
/** Returns either `friendly`, `cwl` or `
|
|
133
|
-
get type():
|
|
132
|
+
/** Returns either `friendly`, `cwl` or `normal`. */
|
|
133
|
+
get type(): "friendly" | "cwl" | "normal";
|
|
134
134
|
private get _isFriendly();
|
|
135
|
+
/** Returns the war status, based off the home clan. */
|
|
136
|
+
get status(): "win" | "lose" | "tie" | "pending";
|
|
135
137
|
}
|
package/dist/struct/ClanWar.js
CHANGED
|
@@ -147,7 +147,7 @@ class ClanWar {
|
|
|
147
147
|
}
|
|
148
148
|
this.clan = new WarClan(this, clan);
|
|
149
149
|
this.opponent = new WarClan(this, opponent);
|
|
150
|
-
this.maxAge =
|
|
150
|
+
this.maxAge = extra.maxAge;
|
|
151
151
|
}
|
|
152
152
|
/** Return a {@link ClanWarMember} with the tag provided. */
|
|
153
153
|
getMember(tag) {
|
|
@@ -168,17 +168,31 @@ class ClanWar {
|
|
|
168
168
|
}
|
|
169
169
|
return this.opponent.attacks.filter((atk) => atk.defenderTag === defenderTag);
|
|
170
170
|
}
|
|
171
|
-
/** Returns either `friendly`, `cwl` or `
|
|
171
|
+
/** Returns either `friendly`, `cwl` or `normal`. */
|
|
172
172
|
get type() {
|
|
173
173
|
if (this._isFriendly)
|
|
174
174
|
return 'friendly';
|
|
175
175
|
if (this.warTag)
|
|
176
176
|
return 'cwl';
|
|
177
|
-
return '
|
|
177
|
+
return 'normal';
|
|
178
178
|
}
|
|
179
179
|
get _isFriendly() {
|
|
180
180
|
const preparationTime = this.startTime.getTime() - this.preparationStartTime.getTime();
|
|
181
181
|
return Constants_1.FRIENDLY_WAR_PREPARATION_TIMES.includes(preparationTime);
|
|
182
182
|
}
|
|
183
|
+
/** Returns the war status, based off the home clan. */
|
|
184
|
+
get status() {
|
|
185
|
+
if (this.state === 'preparation')
|
|
186
|
+
return 'pending';
|
|
187
|
+
if (this.clan.stars > this.opponent.stars)
|
|
188
|
+
return 'win';
|
|
189
|
+
if (this.clan.stars === this.opponent.stars) {
|
|
190
|
+
if (this.clan.destruction > this.opponent.destruction)
|
|
191
|
+
return 'win';
|
|
192
|
+
if (this.clan.destruction === this.opponent.destruction)
|
|
193
|
+
return 'tie';
|
|
194
|
+
}
|
|
195
|
+
return 'lose';
|
|
196
|
+
}
|
|
183
197
|
}
|
|
184
198
|
exports.ClanWar = ClanWar;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { APIClanWarLeagueClan, APIClanWarLeagueClanMember, APIClanWarLeagueGroup, APIClanWarLeagueRound } from '../types';
|
|
2
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
2
3
|
import { Client } from '../client/Client';
|
|
3
4
|
import { ClanWar } from './ClanWar';
|
|
4
5
|
import { Player } from './Player';
|
|
@@ -28,7 +29,7 @@ export declare class ClanWarLeagueClan {
|
|
|
28
29
|
members: ClanWarLeagueClanMember[];
|
|
29
30
|
constructor(client: Client, data: APIClanWarLeagueClan);
|
|
30
31
|
/** Get {@link Player} information for every members that are in the CWL group. */
|
|
31
|
-
fetchMembers(): Promise<Player[]>;
|
|
32
|
+
fetchMembers(options?: OverrideOptions): Promise<Player[]>;
|
|
32
33
|
}
|
|
33
34
|
/** Represents a Round of CWL Group. */
|
|
34
35
|
export declare class ClanWarLeagueRound {
|
|
@@ -53,9 +54,10 @@ export declare class ClanWarLeagueGroup {
|
|
|
53
54
|
/**
|
|
54
55
|
* This returns an array of {@link ClanWar} which fetches all wars in parallel.
|
|
55
56
|
* @param clanTag Optional clan tag. If present, this will only return wars which belong to this clan.
|
|
57
|
+
* @param options Override options for the request.
|
|
56
58
|
*/
|
|
57
|
-
getWars(clanTag?: string): Promise<ClanWar[]>;
|
|
59
|
+
getWars(clanTag?: string, options?: OverrideOptions): Promise<ClanWar[]>;
|
|
58
60
|
private _getCurrentWars;
|
|
59
|
-
/** Returns
|
|
61
|
+
/** Returns the index of the round for this specified warTag. */
|
|
60
62
|
getRoundIndex(warTag: string): number | null;
|
|
61
63
|
}
|
|
@@ -22,8 +22,8 @@ class ClanWarLeagueClan {
|
|
|
22
22
|
this.members = data.members.map((mem) => new ClanWarLeagueClanMember(mem));
|
|
23
23
|
}
|
|
24
24
|
/** Get {@link Player} information for every members that are in the CWL group. */
|
|
25
|
-
async fetchMembers() {
|
|
26
|
-
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ignoreRateLimit: true }))))
|
|
25
|
+
async fetchMembers(options) {
|
|
26
|
+
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ...options, ignoreRateLimit: true }))))
|
|
27
27
|
.filter((res) => res.status === 'fulfilled')
|
|
28
28
|
.map((res) => res.value);
|
|
29
29
|
}
|
|
@@ -49,33 +49,35 @@ class ClanWarLeagueGroup {
|
|
|
49
49
|
/**
|
|
50
50
|
* This returns an array of {@link ClanWar} which fetches all wars in parallel.
|
|
51
51
|
* @param clanTag Optional clan tag. If present, this will only return wars which belong to this clan.
|
|
52
|
+
* @param options Override options for the request.
|
|
52
53
|
*/
|
|
53
|
-
async getWars(clanTag) {
|
|
54
|
+
async getWars(clanTag, options) {
|
|
54
55
|
const rounds = this.rounds.filter((round) => !round.warTags.includes('#0'));
|
|
55
56
|
if (!rounds.length)
|
|
56
57
|
return [];
|
|
57
58
|
const warTags = rounds.map((round) => round.warTags).flat();
|
|
58
|
-
const wars = await Promise.allSettled(warTags.map((warTag) => this.client.getClanWarLeagueRound({ warTag, clanTag }, { ignoreRateLimit: true })));
|
|
59
|
+
const wars = await Promise.allSettled(warTags.map((warTag) => this.client.getClanWarLeagueRound({ warTag, clanTag }, { ...options, ignoreRateLimit: true })));
|
|
59
60
|
return wars
|
|
60
|
-
.filter((res) => res.status === 'fulfilled'
|
|
61
|
+
.filter((res) => res.status === 'fulfilled')
|
|
61
62
|
.map((res) => res.value)
|
|
62
63
|
.filter((war) => (clanTag ? war.clan.tag === clanTag : true));
|
|
63
64
|
}
|
|
64
|
-
async _getCurrentWars(clanTag) {
|
|
65
|
+
async _getCurrentWars(clanTag, options) {
|
|
65
66
|
const rounds = this.rounds.filter((round) => !round.warTags.includes('#0'));
|
|
66
67
|
if (!rounds.length)
|
|
67
68
|
return [];
|
|
68
69
|
const warTags = rounds
|
|
69
70
|
.slice(-2)
|
|
70
71
|
.map((round) => round.warTags)
|
|
71
|
-
.flat()
|
|
72
|
-
|
|
72
|
+
.flat()
|
|
73
|
+
.reverse();
|
|
74
|
+
const wars = await Promise.allSettled(warTags.map((warTag) => this.client.getClanWarLeagueRound({ warTag, clanTag }, { ...options, ignoreRateLimit: true })));
|
|
73
75
|
return wars
|
|
74
|
-
.filter((res) => res.status === 'fulfilled'
|
|
76
|
+
.filter((res) => res.status === 'fulfilled')
|
|
75
77
|
.map((res) => res.value)
|
|
76
78
|
.filter((war) => war.clan.tag === clanTag);
|
|
77
79
|
}
|
|
78
|
-
/** Returns
|
|
80
|
+
/** Returns the index of the round for this specified warTag. */
|
|
79
81
|
getRoundIndex(warTag) {
|
|
80
82
|
return this.rounds.find((round) => round.warTags.includes(warTag))?.round ?? null;
|
|
81
83
|
}
|
|
@@ -49,6 +49,6 @@ export declare class ClanWarLog {
|
|
|
49
49
|
/** The opposition clan. */
|
|
50
50
|
opponent: WarLogClan;
|
|
51
51
|
constructor(client: Client, data: APIClanWarLogEntry);
|
|
52
|
-
/** Returns either `friendly`, `cwl` or `
|
|
53
|
-
get type(): "friendly" | "cwl" | "
|
|
52
|
+
/** Returns either `friendly`, `cwl` or `normal`. */
|
|
53
|
+
get type(): "friendly" | "cwl" | "normal";
|
|
54
54
|
}
|
|
@@ -34,13 +34,13 @@ class ClanWarLog {
|
|
|
34
34
|
this.clan = new WarLogClan(data.clan);
|
|
35
35
|
this.opponent = new WarLogClan(data.opponent);
|
|
36
36
|
}
|
|
37
|
-
/** Returns either `friendly`, `cwl` or `
|
|
37
|
+
/** Returns either `friendly`, `cwl` or `normal`. */
|
|
38
38
|
get type() {
|
|
39
39
|
if (!this.clan.expEarned)
|
|
40
40
|
return 'friendly';
|
|
41
41
|
if (!this.opponent.tag)
|
|
42
42
|
return 'cwl';
|
|
43
|
-
return '
|
|
43
|
+
return 'normal';
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
exports.ClanWarLog = ClanWarLog;
|
package/dist/struct/Player.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { LegendStatistics } from './LegendStatistics';
|
|
2
3
|
import { Achievement } from './Achievement';
|
|
3
4
|
import { Hero, Spell, Troop } from './Unit';
|
|
@@ -63,7 +64,7 @@ export declare class Player {
|
|
|
63
64
|
heroes: Hero[];
|
|
64
65
|
constructor(client: Client, data: APIPlayer);
|
|
65
66
|
/** Fetch detailed clan info for the player's clan. */
|
|
66
|
-
fetchClan(): Promise<import("./Clan").Clan | null>;
|
|
67
|
+
fetchClan(options?: OverrideOptions): Promise<import("./Clan").Clan | null>;
|
|
67
68
|
/** An array of the player's home base troops. */
|
|
68
69
|
get homeTroops(): Troop[];
|
|
69
70
|
/** An array of the player's builder base troops. */
|
package/dist/struct/Player.js
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Player = void 0;
|
|
4
4
|
const Constants_1 = require("../util/Constants");
|
|
5
|
+
const raw_json_1 = require("../util/raw.json");
|
|
5
6
|
const LegendStatistics_1 = require("./LegendStatistics");
|
|
6
7
|
const Achievement_1 = require("./Achievement");
|
|
7
8
|
const Unit_1 = require("./Unit");
|
|
8
9
|
const PlayerClan_1 = require("./PlayerClan");
|
|
9
10
|
const League_1 = require("./League");
|
|
10
11
|
const Label_1 = require("./Label");
|
|
12
|
+
const UNIT_NAMES = [...raw_json_1.RAW_UNITS.map((unit) => unit.name), ...raw_json_1.RAW_SUPER_UNITS.map((unit) => unit.name)];
|
|
11
13
|
/** Represents a Clash of Clans Player. */
|
|
12
14
|
class Player {
|
|
13
15
|
constructor(client, data) {
|
|
@@ -36,15 +38,15 @@ class Player {
|
|
|
36
38
|
this.legendStatistics = data.legendStatistics ? new LegendStatistics_1.LegendStatistics(data.legendStatistics) : null;
|
|
37
39
|
this.achievements = data.achievements.map((data) => new Achievement_1.Achievement(data));
|
|
38
40
|
this.labels = data.labels.map((data) => new Label_1.Label(data));
|
|
39
|
-
this.troops = data.troops.map((
|
|
40
|
-
this.spells = data.spells.map((
|
|
41
|
-
this.heroes = data.heroes.map((
|
|
41
|
+
this.troops = data.troops.filter((unit) => UNIT_NAMES.includes(unit.name)).map((unit) => new Unit_1.Troop(data, unit));
|
|
42
|
+
this.spells = data.spells.filter((unit) => UNIT_NAMES.includes(unit.name)).map((unit) => new Unit_1.Spell(data, unit));
|
|
43
|
+
this.heroes = data.heroes.filter((unit) => UNIT_NAMES.includes(unit.name)).map((unit) => new Unit_1.Hero(data, unit));
|
|
42
44
|
}
|
|
43
45
|
/** Fetch detailed clan info for the player's clan. */
|
|
44
|
-
async fetchClan() {
|
|
46
|
+
async fetchClan(options) {
|
|
45
47
|
if (!this.clan)
|
|
46
48
|
return null;
|
|
47
|
-
return this.client.getClan(this.clan.tag);
|
|
49
|
+
return this.client.getClan(this.clan.tag, options);
|
|
48
50
|
}
|
|
49
51
|
/** An array of the player's home base troops. */
|
|
50
52
|
get homeTroops() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { Client } from '../client/Client';
|
|
2
3
|
import { APIPlayerClan } from '../types';
|
|
3
4
|
import { Badge } from './Badge';
|
|
@@ -14,5 +15,5 @@ export declare class PlayerClan {
|
|
|
14
15
|
badge: Badge;
|
|
15
16
|
constructor(_client: Client, data: APIPlayerClan);
|
|
16
17
|
/** Fetch detailed clan info for the player's clan. */
|
|
17
|
-
fetch(): Promise<import("./Clan").Clan>;
|
|
18
|
+
fetch(options?: OverrideOptions): Promise<import("./Clan").Clan>;
|
|
18
19
|
}
|
|
@@ -12,8 +12,8 @@ class PlayerClan {
|
|
|
12
12
|
this.badge = new Badge_1.Badge(data.badgeUrls);
|
|
13
13
|
}
|
|
14
14
|
/** Fetch detailed clan info for the player's clan. */
|
|
15
|
-
fetch() {
|
|
16
|
-
return this._client.getClan(this.tag);
|
|
15
|
+
fetch(options) {
|
|
16
|
+
return this._client.getClan(this.tag, options);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
exports.PlayerClan = PlayerClan;
|
package/dist/struct/Unit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APIPlayerItem } from '../types';
|
|
1
|
+
import { APIPlayerItem, APIPlayer } from '../types';
|
|
2
2
|
/** Represents a player's unit. */
|
|
3
3
|
export declare class Unit {
|
|
4
4
|
/** The name of this unit. */
|
|
@@ -9,7 +9,35 @@ export declare class Unit {
|
|
|
9
9
|
maxLevel: number;
|
|
10
10
|
/** The village type of this unit. */
|
|
11
11
|
village: 'home' | 'builderBase';
|
|
12
|
-
|
|
12
|
+
/** Id of this unit. */
|
|
13
|
+
id: number;
|
|
14
|
+
/** Housing space of this unit. */
|
|
15
|
+
housingSpace: number;
|
|
16
|
+
/** Town/Builder hall's max level of this unit. */
|
|
17
|
+
hallMaxLevel: number;
|
|
18
|
+
/** Unlock Town/Builder Hall level of this unit. */
|
|
19
|
+
unlockHallLevel: number;
|
|
20
|
+
/** Unlock cost of this unit. */
|
|
21
|
+
unlockCost: number;
|
|
22
|
+
/** Unlock time of this unit. */
|
|
23
|
+
unlockTime: number;
|
|
24
|
+
/** Unlock resource of this unit. */
|
|
25
|
+
unlockResource: string;
|
|
26
|
+
/** Unlock building of this unit. */
|
|
27
|
+
unlockBuilding: string;
|
|
28
|
+
/** Unlock building level of this unit. */
|
|
29
|
+
unlockBuildingLevel: number;
|
|
30
|
+
/** Upgrade cost of this unit. */
|
|
31
|
+
upgradeCost: number;
|
|
32
|
+
/** Upgrade resource of this unit. */
|
|
33
|
+
upgradeResource: string;
|
|
34
|
+
/** Upgrade time of this unit. */
|
|
35
|
+
upgradeTime: number;
|
|
36
|
+
/** @internal */
|
|
37
|
+
minOriginalLevel: number | null;
|
|
38
|
+
/** @internal */
|
|
39
|
+
originalName: string | null;
|
|
40
|
+
constructor(data: APIPlayer, unit: APIPlayerItem);
|
|
13
41
|
/** Whether the unit belongs to the home base. */
|
|
14
42
|
get isHomeBase(): boolean;
|
|
15
43
|
/** Whether the unit belongs to the builder base. */
|
|
@@ -22,8 +50,13 @@ export declare class Unit {
|
|
|
22
50
|
/** Represents a player's troop. */
|
|
23
51
|
export declare class Troop extends Unit {
|
|
24
52
|
name: string;
|
|
25
|
-
|
|
26
|
-
|
|
53
|
+
/** Whether this troop is currently active of boosted. */
|
|
54
|
+
isActive: boolean;
|
|
55
|
+
/** Origin troop's minimum level of this super troop. */
|
|
56
|
+
minOriginalLevel: number | null;
|
|
57
|
+
/** Origin troop's name of this super troop. */
|
|
58
|
+
originalName: string | null;
|
|
59
|
+
constructor(data: APIPlayer, unit: APIPlayerItem);
|
|
27
60
|
/** Whether this troop is a Super Troop. */
|
|
28
61
|
get isSuperTroop(): boolean;
|
|
29
62
|
}
|