clashofclans.js 2.0.0-dev.c0ee4c0 → 2.0.1-dev.0dd451f

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 CHANGED
@@ -2,15 +2,33 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- ## 2.0.0
5
+ ## 2.0.1 (2021-11-27)
6
+
7
+ ### Bug Fixes
8
+
9
+ - IP retrieval method and Event Loop ([#70](https://github.com/clashperk/clashofclans.js/issues/70)) ([82b84ba](https://github.com/clashperk/clashofclans.js/commit/82b84ba5d96505c43b75e53aa07f547ef0b77778))
10
+
11
+ ## 2.0.0 (2021-11-26)
6
12
 
7
13
  This new version is a complete TypeScript rewrite to convert everything from plain (literal JSON) objects to class (constructor) objects and support a lot more features.
8
14
 
9
15
  ### Features
10
16
 
11
- - EventManager and Custom Events ([#37](https://github.com/clashperk/clashofclans.js/issues/37)) ([5027ae6](https://github.com/clashperk/clashofclans.js/commit/5027ae663a8e07175e17384c7e5706f4a1a7afb4)) ([984451d](https://github.com/clashperk/clashofclans.js/commit/30ea3240c11866008d0dae514468c0fdbb34ffd0))
12
- - Internal Caching Options ([#53](https://github.com/clashperk/clashofclans.js/issues/53))
17
+ - HTTP Request Request Retries ([#26](https://github.com/clashperk/clashofclans.js/issues/26)) ([94585f3](https://github.com/clashperk/clashofclans.js/commit/94585f3a84a7175b2d07872f9eb9e42372b95e12))
18
+ - Event Manager and Custom Events ([#37](https://github.com/clashperk/clashofclans.js/issues/37)) ([5027ae6](https://github.com/clashperk/clashofclans.js/commit/5027ae663a8e07175e17384c7e5706f4a1a7afb4))
13
19
  - Email Password Login ([#31](https://github.com/clashperk/clashofclans.js/issues/31)) ([4153cd3](https://github.com/clashperk/clashofclans.js/commit/4153cd37ea0e1c71550b9e892105b84d5a407e23))
14
- - API Date Parser and Request Retries ([#26](https://github.com/clashperk/clashofclans.js/issues/26)) ([94585f3](https://github.com/clashperk/clashofclans.js/commit/94585f3a84a7175b2d07872f9eb9e42372b95e12))
20
+ - Queue Throttler and Batch Throttler ([#34](https://github.com/clashperk/clashofclans.js/issues/34)) ([3a8f051](https://github.com/clashperk/clashofclans.js/commit/3a8f051552e93b98f89bc7d524acdecddf242718))
15
21
  - Override Request Options ([#36](https://github.com/clashperk/clashofclans.js/issues/36)) ([42d7fdd](https://github.com/clashperk/clashofclans.js/commit/42d7fdd36262cc46f23b731f8cffb9daea19d3b0))
16
- - QueueThrottler and BatchThrottler ([#34](https://github.com/clashperk/clashofclans.js/issues/34)) ([3a8f051](https://github.com/clashperk/clashofclans.js/commit/3a8f051552e93b98f89bc7d524acdecddf242718))
22
+ - Internal Caching Options ([#53](https://github.com/clashperk/clashofclans.js/issues/53)) ([984451d](https://github.com/clashperk/clashofclans.js/commit/30ea3240c11866008d0dae514468c0fdbb34ffd0))
23
+ - Additional Properties for Player Units ([#65](https://github.com/clashperk/clashofclans.js/pull/65)) ([aa1696](https://github.com/clashperk/clashofclans.js/commit/aa1696243d96d4fed0250b4282c60522a6482343))
24
+
25
+ ### Links
26
+
27
+ - Documentation
28
+ https://clashofclans.js.org/docs
29
+
30
+ - Guide
31
+ https://clashofclans.js.org/guide
32
+
33
+ - Updating to v2.0.0
34
+ https://clashofclans.js.org/docs/updating-to-v2
package/README.md CHANGED
@@ -39,12 +39,13 @@ const client = new Client();
39
39
  ```js
40
40
  const { Client, BatchThrottler } = require('clashofclans.js');
41
41
  const client = new Client({
42
+ cache: true,
42
43
  retryLimit: 1,
43
- restRequestTimeout: 3000,
44
- throttler: new BatchThrottler(30)
44
+ restRequestTimeout: 5000,
45
+ throttler: new BatchThrottler(20)
45
46
  });
46
47
 
47
- client.events.addClans(['#8P2QG08P']);
48
+ client.events.addClans(['#8QU8J9LP', '#8P2QG08P']);
48
49
  client.events.setClanEvent({
49
50
  name: 'clanDescriptionChange',
50
51
  filter: (oldClan, newClan) => {
@@ -21,6 +21,8 @@ export declare class Client extends EventEmitter {
21
21
  constructor(options?: ClientOptions);
22
22
  /** Contains various general-purpose utility methods. */
23
23
  get util(): typeof Util;
24
+ /** Whether the API is in maintenance break. */
25
+ get inMaintenance(): boolean;
24
26
  /**
25
27
  * Initialize the client to create keys.
26
28
  * @example
@@ -40,7 +42,7 @@ export declare class Client extends EventEmitter {
40
42
  getClanMembers(clanTag: string, options?: SearchOptions): Promise<ClanMember[]>;
41
43
  /** Get clan war log. */
42
44
  getClanWarLog(clanTag: string, options?: SearchOptions): Promise<ClanWarLog[]>;
43
- /** Get info about currently running war (regular or friendly) in the clan. */
45
+ /** Get info about currently running war (normal or friendly) in the clan. */
44
46
  getClanWar(clanTag: string, options?: OverrideOptions): Promise<ClanWar>;
45
47
  /**
46
48
  * Get info about currently running war in the clan.
@@ -76,7 +78,7 @@ export declare class Client extends EventEmitter {
76
78
  private _getClanWars;
77
79
  /** Get information about clan war league. */
78
80
  getClanWarLeagueGroup(clanTag: string, options?: OverrideOptions): Promise<ClanWarLeagueGroup>;
79
- /** Get information about CWL round by WarTag. */
81
+ /** Get info about a CWL round by WarTag. */
80
82
  getClanWarLeagueRound(warTag: string | {
81
83
  warTag: string;
82
84
  clanTag?: string;
@@ -99,9 +101,9 @@ export declare class Client extends EventEmitter {
99
101
  getClanRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedClan[]>;
100
102
  /** Get player rankings for a specific location. */
101
103
  getPlayerRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedPlayer[]>;
102
- /** Get clan versus rankings for a specific location */
104
+ /** Get clan versus rankings for a specific location. */
103
105
  getVersusClanRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedClan[]>;
104
- /** Get player versus rankings for a specific location */
106
+ /** Get player versus rankings for a specific location. */
105
107
  getVersusPlayerRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedPlayer[]>;
106
108
  /** Get list of clan labels. */
107
109
  getClanLabels(options?: SearchOptions): Promise<Label[]>;
@@ -141,15 +143,21 @@ export declare class Client extends EventEmitter {
141
143
  private static maintenanceEnd;
142
144
  /** @internal */
143
145
  on<K extends keyof ClientEvents>(event: K, listeners: (...args: ClientEvents[K]) => void): this;
146
+ /** @internal */
147
+ on<S extends keyof CustomEvents>(event: Exclude<S, keyof ClientEvents>, listeners: (...args: CustomEvents[S]) => void): this;
144
148
  /** @internal */ on<S extends string | symbol>(event: Exclude<S, keyof ClientEvents>, listeners: (...args: any[]) => void): this;
145
149
  /** @internal */
146
150
  once<K extends keyof ClientEvents>(event: K, listeners: (...args: ClientEvents[K]) => void): this;
151
+ /** @internal */
152
+ once<S extends keyof CustomEvents>(event: Exclude<S, keyof ClientEvents>, listeners: (...args: CustomEvents[S]) => void): this;
147
153
  /** @internal */ once<S extends string | symbol>(event: Exclude<S, keyof ClientEvents>, listeners: (...args: any[]) => void): this;
148
154
  /** @internal */
149
155
  emit<K extends keyof ClientEvents>(event: K, ...args: ClientEvents[K]): boolean;
156
+ /** @internal */
157
+ emit<S extends keyof CustomEvents>(event: Exclude<S, keyof ClientEvents>, ...args: CustomEvents[S]): this;
150
158
  /** @internal */ emit<S extends string | symbol>(event: Exclude<S, keyof ClientEvents>, ...args: any[]): boolean;
151
159
  }
152
- export interface ClientEvents {
160
+ interface ClientEvents {
153
161
  [EVENTS.NEW_SEASON_START]: [id: string];
154
162
  [EVENTS.MAINTENANCE_START]: [];
155
163
  [EVENTS.MAINTENANCE_END]: [duration: number];
@@ -161,3 +169,9 @@ export interface ClientEvents {
161
169
  [EVENTS.WAR_LOOP_END]: [];
162
170
  [EVENTS.ERROR]: [error: unknown];
163
171
  }
172
+ interface CustomEvents {
173
+ [key: `clan${string}`]: [oldClan: Clan, newClan: Clan];
174
+ [key: `war${string}`]: [oldWar: ClanWar, newWar: ClanWar];
175
+ [key: `player${string}`]: [oldPlayer: Player, newPlayer: Player];
176
+ }
177
+ export {};
@@ -25,6 +25,11 @@ class Client extends events_1.EventEmitter {
25
25
  get util() {
26
26
  return Util_1.Util;
27
27
  }
28
+ /** Whether the API is in maintenance break. */
29
+ get inMaintenance() {
30
+ // @ts-expect-error
31
+ return this.events._inMaintenance;
32
+ }
28
33
  /**
29
34
  * Initialize the client to create keys.
30
35
  * @example
@@ -62,11 +67,11 @@ class Client extends events_1.EventEmitter {
62
67
  const { data } = await this.rest.getClanWarLog(clanTag, options);
63
68
  return data.items.map((entry) => new struct_1.ClanWarLog(this, entry));
64
69
  }
65
- /** Get info about currently running war (regular or friendly) in the clan. */
70
+ /** Get info about currently running war (normal or friendly) in the clan. */
66
71
  async getClanWar(clanTag, options) {
67
72
  const { data, maxAge, path, status } = await this.rest.getCurrentWar(clanTag, options);
68
73
  if (data.state === 'notInWar') {
69
- throw new HTTPError_1.HTTPError(HTTPError_1.notInWarError, status, path, maxAge);
74
+ throw new HTTPError_1.HTTPError(HTTPError_1.NotInWarError, status, path, maxAge);
70
75
  }
71
76
  return new struct_1.ClanWar(this, data, { clanTag, maxAge });
72
77
  }
@@ -87,11 +92,11 @@ class Client extends events_1.EventEmitter {
87
92
  return await this.getClanWar(args.clanTag, options);
88
93
  }
89
94
  catch (e) {
90
- if (e instanceof HTTPError_1.HTTPError && e.status === 403) {
91
- return this.getLeagueWar({ clanTag: args.clanTag, round: args.round });
95
+ if (e instanceof HTTPError_1.HTTPError && [200, 403].includes(e.status)) {
96
+ return this.getLeagueWar({ clanTag: args.clanTag, round: args.round }, options);
92
97
  }
98
+ throw e;
93
99
  }
94
- return null;
95
100
  }
96
101
  /**
97
102
  * Get info about currently running CWL round.
@@ -117,7 +122,7 @@ class Client extends events_1.EventEmitter {
117
122
  .map((round) => round.warTags)
118
123
  .flat()
119
124
  .reverse();
120
- const wars = await this.util.allSettled(warTags.map((warTag) => this.getClanWarLeagueRound({ warTag, clanTag: args.clanTag }, { ignoreRateLimit: true })));
125
+ const wars = await this.util.allSettled(warTags.map((warTag) => this.getClanWarLeagueRound({ warTag, clanTag: args.clanTag }, { ...options, ignoreRateLimit: true })));
121
126
  if (args.round && args.round in Constants_1.CWL_ROUNDS) {
122
127
  return wars.find((war) => war.state === state) ?? null;
123
128
  }
@@ -126,20 +131,21 @@ class Client extends events_1.EventEmitter {
126
131
  async _getCurrentLeagueWars(clanTag, options) {
127
132
  const data = await this.getClanWarLeagueGroup(clanTag, options);
128
133
  // @ts-expect-error
129
- return data._getCurrentWars(clanTag);
134
+ return data._getCurrentWars(clanTag, options);
130
135
  }
131
136
  async _getClanWars(clanTag, options) {
132
- const date = new Date().getDate();
133
- try {
137
+ const date = new Date().getUTCDate();
138
+ if (!(date >= 1 && date <= 10)) {
134
139
  return [await this.getClanWar(clanTag, options)];
135
140
  }
141
+ try {
142
+ return this._getCurrentLeagueWars(clanTag, options);
143
+ }
136
144
  catch (e) {
137
- if (!(date >= 1 && date <= 10))
138
- return [];
139
- if (e instanceof HTTPError_1.HTTPError && [200, 403].includes(e.status)) {
140
- return this._getCurrentLeagueWars(clanTag);
145
+ if (e instanceof HTTPError_1.HTTPError && [404].includes(e.status)) {
146
+ return [await this.getClanWar(clanTag, options)];
141
147
  }
142
- return [];
148
+ throw e;
143
149
  }
144
150
  }
145
151
  /** Get information about clan war league. */
@@ -147,12 +153,12 @@ class Client extends events_1.EventEmitter {
147
153
  const { data } = await this.rest.getClanWarLeagueGroup(clanTag, options);
148
154
  return new struct_1.ClanWarLeagueGroup(this, data);
149
155
  }
150
- /** Get information about CWL round by WarTag. */
156
+ /** Get info about a CWL round by WarTag. */
151
157
  async getClanWarLeagueRound(warTag, options) {
152
158
  const args = typeof warTag === 'string' ? { warTag } : { warTag: warTag.warTag, clanTag: warTag.clanTag };
153
159
  const { data, maxAge, status, path } = await this.rest.getClanWarLeagueRound(args.warTag, options);
154
160
  if (data.state === 'notInWar') {
155
- throw new HTTPError_1.HTTPError(HTTPError_1.notInWarError, status, path, maxAge);
161
+ throw new HTTPError_1.HTTPError(HTTPError_1.NotInWarError, status, path, maxAge);
156
162
  }
157
163
  return new struct_1.ClanWar(this, data, { warTag: args.warTag, clanTag: args.clanTag, maxAge });
158
164
  }
@@ -163,7 +169,7 @@ class Client extends events_1.EventEmitter {
163
169
  }
164
170
  /** Verify Player API token that can be found from the Game settings. */
165
171
  async verifyPlayerToken(playerTag, token, options) {
166
- const { data } = await this.rest.postPlayerToken(playerTag, token, options);
172
+ const { data } = await this.rest.verifyPlayerToken(playerTag, token, options);
167
173
  return data.status === 'ok';
168
174
  }
169
175
  /** Get list of Leagues. */
@@ -202,12 +208,12 @@ class Client extends events_1.EventEmitter {
202
208
  const { data } = await this.rest.getPlayerRanks(locationId, options);
203
209
  return data.items.map((entry) => new struct_1.RankedPlayer(this, entry));
204
210
  }
205
- /** Get clan versus rankings for a specific location */
211
+ /** Get clan versus rankings for a specific location. */
206
212
  async getVersusClanRanks(locationId, options) {
207
213
  const { data } = await this.rest.getVersusClanRanks(locationId, options);
208
214
  return data.items.map((entry) => new struct_1.RankedClan(entry));
209
215
  }
210
- /** Get player versus rankings for a specific location */
216
+ /** Get player versus rankings for a specific location. */
211
217
  async getVersusPlayerRanks(locationId, options) {
212
218
  const { data } = await this.rest.getVersusPlayerRanks(locationId, options);
213
219
  return data.items.map((entry) => new struct_1.RankedPlayer(this, entry));
@@ -1,6 +1,6 @@
1
1
  import { Clan, ClanWar, Player } from '../struct';
2
2
  import { Client } from './Client';
3
- /** Represents Event Manager of the {@link Client} class. */
3
+ /** Represents Event Manager of the {@link Client}. */
4
4
  export declare class EventManager {
5
5
  private readonly client;
6
6
  private readonly _clanTags;
@@ -15,18 +15,18 @@ export declare class EventManager {
15
15
  constructor(client: Client);
16
16
  /** Initialize the Event Manager to start pulling. */
17
17
  init(): Promise<string[]>;
18
- /** Add a clan tag to clan events. */
19
- addClans(...tags: string[]): this;
20
- /** Delete a clan tag from clan events. */
21
- deleteClans(...tags: string[]): this;
22
- /** Add a player tag for player events. */
23
- addPlayers(...tags: string[]): this;
24
- /** Delete a player tag from player events. */
25
- deletePlayers(...tags: string[]): this;
26
- /** Add a clan tag for war events. */
27
- addWars(...tags: string[]): this;
28
- /** Delete a clan tag from war events. */
29
- deleteWars(...tags: string[]): this;
18
+ /** Add clan tags to clan events. */
19
+ addClans(tags: string[] | string): this;
20
+ /** Delete clan tags from clan events. */
21
+ deleteClans(tags: string[] | string): this;
22
+ /** Add player tags for player events. */
23
+ addPlayers(tags: string[] | string): this;
24
+ /** Delete player tags from player events. */
25
+ deletePlayers(tags: string[] | string): this;
26
+ /** Add clan tags for war events. */
27
+ addWars(tags: string[] | string): this;
28
+ /** Delete clan tags from war events. */
29
+ deleteWars(tags: string[] | string): this;
30
30
  /**
31
31
  * Set your own custom clan event.
32
32
  *
@@ -4,7 +4,7 @@ exports.EventManager = void 0;
4
4
  const HTTPError_1 = require("../rest/HTTPError");
5
5
  const Constants_1 = require("../util/Constants");
6
6
  const Util_1 = require("../util/Util");
7
- /** Represents Event Manager of the {@link Client} class. */
7
+ /** Represents Event Manager of the {@link Client}. */
8
8
  class EventManager {
9
9
  constructor(client) {
10
10
  this.client = client;
@@ -31,45 +31,52 @@ class EventManager {
31
31
  this.warUpdateHandler();
32
32
  return Promise.resolve(this.client.eventNames());
33
33
  }
34
- /** Add a clan tag to clan events. */
35
- addClans(...tags) {
36
- for (const tag of tags) {
34
+ /** Add clan tags to clan events. */
35
+ addClans(tags) {
36
+ for (const tag of Array.isArray(tags) ? tags : [tags]) {
37
37
  this._clanTags.add(this.client.util.parseTag(tag));
38
38
  }
39
39
  return this;
40
40
  }
41
- /** Delete a clan tag from clan events. */
42
- deleteClans(...tags) {
43
- for (const tag of tags) {
44
- this._warTags.delete(this.client.util.parseTag(tag));
41
+ /** Delete clan tags from clan events. */
42
+ deleteClans(tags) {
43
+ for (const tag of Array.isArray(tags) ? tags : [tags]) {
44
+ const key = this.client.util.parseTag(tag);
45
+ this._clans.delete(key);
46
+ this._clanTags.delete(key);
45
47
  }
46
48
  return this;
47
49
  }
48
- /** Add a player tag for player events. */
49
- addPlayers(...tags) {
50
- for (const tag of tags) {
50
+ /** Add player tags for player events. */
51
+ addPlayers(tags) {
52
+ for (const tag of Array.isArray(tags) ? tags : [tags]) {
51
53
  this._playerTags.add(this.client.util.parseTag(tag));
52
54
  }
53
55
  return this;
54
56
  }
55
- /** Delete a player tag from player events. */
56
- deletePlayers(...tags) {
57
- for (const tag of tags) {
58
- this._warTags.delete(this.client.util.parseTag(tag));
57
+ /** Delete player tags from player events. */
58
+ deletePlayers(tags) {
59
+ for (const tag of Array.isArray(tags) ? tags : [tags]) {
60
+ const key = this.client.util.parseTag(tag);
61
+ this._players.delete(key);
62
+ this._playerTags.delete(key);
59
63
  }
60
64
  return this;
61
65
  }
62
- /** Add a clan tag for war events. */
63
- addWars(...tags) {
64
- for (const tag of tags) {
66
+ /** Add clan tags for war events. */
67
+ addWars(tags) {
68
+ for (const tag of Array.isArray(tags) ? tags : [tags]) {
65
69
  this._warTags.add(this.client.util.parseTag(tag));
66
70
  }
67
71
  return this;
68
72
  }
69
- /** Delete a clan tag from war events. */
70
- deleteWars(...tags) {
71
- for (const tag of tags) {
72
- this._warTags.delete(this.client.util.parseTag(tag));
73
+ /** Delete clan tags from war events. */
74
+ deleteWars(tags) {
75
+ for (const tag of Array.isArray(tags) ? tags : [tags]) {
76
+ const key = this.client.util.parseTag(tag);
77
+ this._wars.delete(`${key}:${1}`);
78
+ this._wars.delete(`${key}:${2}`);
79
+ this._warTags.delete(key);
73
80
  }
74
81
  return this;
75
82
  }
@@ -100,7 +107,11 @@ class EventManager {
100
107
  * @returns
101
108
  */
102
109
  setClanEvent(event) {
103
- this._events.clans.push({ name: event.name, fn: event.filter });
110
+ if (!event.name)
111
+ throw new Error('Event name is required.');
112
+ if (typeof event.filter !== 'function')
113
+ throw new Error('Filter function is required.');
114
+ this._events.clans.push(event);
104
115
  return this;
105
116
  }
106
117
  /**
@@ -109,7 +120,11 @@ class EventManager {
109
120
  * In order to emit the custom event, you must have this filter function that returns a boolean.
110
121
  */
111
122
  setWarEvent(event) {
112
- this._events.wars.push({ name: event.name, fn: event.filter });
123
+ if (!event.name)
124
+ throw new Error('Event name is required.');
125
+ if (typeof event.filter !== 'function')
126
+ throw new Error('Filter function is required.');
127
+ this._events.wars.push(event);
113
128
  return this;
114
129
  }
115
130
  /**
@@ -118,7 +133,11 @@ class EventManager {
118
133
  * In order to emit the custom event, you must have this filter function that returns a boolean.
119
134
  */
120
135
  setPlayerEvent(event) {
121
- this._events.players.push({ name: event.name, fn: event.filter });
136
+ if (!event.name)
137
+ throw new Error('Event name is required.');
138
+ if (typeof event.filter !== 'function')
139
+ throw new Error('Filter function is required.');
140
+ this._events.players.push(event);
122
141
  return this;
123
142
  }
124
143
  async maintenanceHandler() {
@@ -127,7 +146,7 @@ class EventManager {
127
146
  const res = await this.client.rest.getClans({ maxMembers: Math.floor(Math.random() * 40) + 10, limit: 1 });
128
147
  if (res.status === 200 && this._inMaintenance) {
129
148
  this._inMaintenance = Boolean(false);
130
- const duration = this._maintenanceStartTime.getTime() - Date.now();
149
+ const duration = Date.now() - this._maintenanceStartTime.getTime();
131
150
  this._maintenanceStartTime = null;
132
151
  this.client.emit(Constants_1.EVENTS.MAINTENANCE_END, duration);
133
152
  }
@@ -144,7 +163,7 @@ class EventManager {
144
163
  const end = Util_1.Util.getSeasonEndTime().getTime() - Date.now();
145
164
  // Why this? setTimeout can be up to 24.8 days or 2147483647ms [(2^31 - 1) Max 32bit Integer]
146
165
  if (end > 24 * 60 * 60 * 1000) {
147
- setTimeout(this.seasonEndHandler.bind(this), 60 * 60 * 1000).unref();
166
+ setTimeout(this.seasonEndHandler.bind(this), 60 * 60 * 1000);
148
167
  }
149
168
  else if (end > 0) {
150
169
  setTimeout(() => {
@@ -164,7 +183,7 @@ class EventManager {
164
183
  for (const tag of this._playerTags)
165
184
  await this.runPlayerUpdate(tag);
166
185
  this.client.emit(Constants_1.EVENTS.PLAYER_LOOP_END);
167
- setTimeout(this.playerUpdateHandler.bind(this), 100000);
186
+ setTimeout(this.playerUpdateHandler.bind(this), 10000);
168
187
  }
169
188
  async warUpdateHandler() {
170
189
  this.client.emit(Constants_1.EVENTS.WAR_LOOP_START);
@@ -182,9 +201,9 @@ class EventManager {
182
201
  const cached = this._clans.get(clan.tag);
183
202
  if (!cached)
184
203
  return this._clans.set(clan.tag, clan);
185
- for (const { name, fn } of this._events.clans) {
204
+ for (const { name, filter } of this._events.clans) {
186
205
  try {
187
- if (!fn(cached, clan))
206
+ if (!filter(cached, clan))
188
207
  continue;
189
208
  this.client.emit(name, cached, clan);
190
209
  }
@@ -203,9 +222,9 @@ class EventManager {
203
222
  const cached = this._players.get(player.tag);
204
223
  if (!cached)
205
224
  return this._players.set(player.tag, player);
206
- for (const { name, fn } of this._events.players) {
225
+ for (const { name, filter } of this._events.players) {
207
226
  try {
208
- if (!fn(cached, player))
227
+ if (!filter(cached, player))
209
228
  continue;
210
229
  this.client.emit(name, cached, player);
211
230
  }
@@ -222,14 +241,14 @@ class EventManager {
222
241
  const clanWars = await this.client._getClanWars(tag).catch(() => null);
223
242
  if (!clanWars?.length)
224
243
  return null;
225
- clanWars.forEach((war, i) => {
226
- const key = `WAR:${i}:${tag}`;
244
+ clanWars.forEach(async (war, index) => {
245
+ const key = `${tag}:${index}`;
227
246
  const cached = this._wars.get(key);
228
247
  if (!cached)
229
248
  return this._wars.set(key, war);
230
- for (const { name, fn } of this._events.wars) {
249
+ for (const { name, filter } of this._events.wars) {
231
250
  try {
232
- if (!fn(cached, war))
251
+ if (!filter(cached, war))
233
252
  continue;
234
253
  this.client.emit(name, cached, war);
235
254
  }
@@ -237,6 +256,22 @@ class EventManager {
237
256
  this.client.emit(Constants_1.EVENTS.ERROR, error);
238
257
  }
239
258
  }
259
+ // check for war end
260
+ if (index === 1 && cached.warTag !== war.warTag) {
261
+ const data = await this.client.getLeagueWar({ clanTag: tag, round: 'PREVIOUS_ROUND' }).catch(() => null);
262
+ if (data && data.warTag === cached.warTag) {
263
+ for (const { name, filter } of this._events.wars) {
264
+ try {
265
+ if (!filter(cached, data))
266
+ continue;
267
+ this.client.emit(name, cached, data);
268
+ }
269
+ catch (error) {
270
+ this.client.emit(Constants_1.EVENTS.ERROR, error);
271
+ }
272
+ }
273
+ }
274
+ }
240
275
  return this._wars.set(key, war);
241
276
  });
242
277
  }
@@ -1,6 +1,4 @@
1
- /**
2
- * Represents an HTTP Error.
3
- */
1
+ /** Represents an HTTP Error. */
4
2
  export declare class HTTPError extends Error {
5
3
  /** The message of this error. */
6
4
  message: string;
@@ -16,11 +14,11 @@ export declare class HTTPError extends Error {
16
14
  maxAge: number;
17
15
  constructor(error: any, status: number, path: string, maxAge: number, method?: string);
18
16
  }
19
- export declare const notInWarError: {
17
+ export declare const NotInWarError: {
20
18
  message: string;
21
19
  reason: string;
22
20
  };
23
- export declare const privateWarLogError: {
21
+ export declare const PrivateWarLogError: {
24
22
  message: string;
25
23
  reason: string;
26
24
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.privateWarLogError = exports.notInWarError = exports.HTTPError = void 0;
3
+ exports.PrivateWarLogError = exports.NotInWarError = exports.HTTPError = void 0;
4
4
  const messages = {
5
5
  500: 'Unknown error happened when handling the request.',
6
6
  504: 'The user aborted this request.',
@@ -19,9 +19,7 @@ const reasons = {
19
19
  404: 'notFound',
20
20
  504: 'requestAborted'
21
21
  };
22
- /**
23
- * Represents an HTTP Error.
24
- */
22
+ /** Represents an HTTP Error. */
25
23
  class HTTPError extends Error {
26
24
  constructor(error, status, path, maxAge, method) {
27
25
  super();
@@ -34,11 +32,11 @@ class HTTPError extends Error {
34
32
  }
35
33
  }
36
34
  exports.HTTPError = HTTPError;
37
- exports.notInWarError = {
35
+ exports.NotInWarError = {
38
36
  message: 'Clan is not in war at this moment.',
39
37
  reason: 'notInWar'
40
38
  };
41
- exports.privateWarLogError = {
39
+ exports.PrivateWarLogError = {
42
40
  message: 'Access denied, clan war log is private.',
43
41
  reason: 'privateWarLog'
44
42
  };