clashofclans.js 2.0.0 → 2.0.1-dev.82b84ba

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.
@@ -163,7 +163,7 @@ class EventManager {
163
163
  const end = Util_1.Util.getSeasonEndTime().getTime() - Date.now();
164
164
  // Why this? setTimeout can be up to 24.8 days or 2147483647ms [(2^31 - 1) Max 32bit Integer]
165
165
  if (end > 24 * 60 * 60 * 1000) {
166
- setTimeout(this.seasonEndHandler.bind(this), 60 * 60 * 1000).unref();
166
+ setTimeout(this.seasonEndHandler.bind(this), 60 * 60 * 1000);
167
167
  }
168
168
  else if (end > 0) {
169
169
  setTimeout(() => {
@@ -176,21 +176,21 @@ class EventManager {
176
176
  for (const tag of this._clanTags)
177
177
  await this.runClanUpdate(tag);
178
178
  this.client.emit(Constants_1.EVENTS.CLAN_LOOP_END);
179
- setTimeout(this.clanUpdateHandler.bind(this), 10000).unref();
179
+ setTimeout(this.clanUpdateHandler.bind(this), 10000);
180
180
  }
181
181
  async playerUpdateHandler() {
182
182
  this.client.emit(Constants_1.EVENTS.PLAYER_LOOP_START);
183
183
  for (const tag of this._playerTags)
184
184
  await this.runPlayerUpdate(tag);
185
185
  this.client.emit(Constants_1.EVENTS.PLAYER_LOOP_END);
186
- setTimeout(this.playerUpdateHandler.bind(this), 10000).unref();
186
+ setTimeout(this.playerUpdateHandler.bind(this), 10000);
187
187
  }
188
188
  async warUpdateHandler() {
189
189
  this.client.emit(Constants_1.EVENTS.WAR_LOOP_START);
190
190
  for (const tag of this._warTags)
191
191
  await this.runWarUpdate(tag);
192
192
  this.client.emit(Constants_1.EVENTS.WAR_LOOP_END);
193
- setTimeout(this.warUpdateHandler.bind(this), 10000).unref();
193
+ setTimeout(this.warUpdateHandler.bind(this), 10000);
194
194
  }
195
195
  async runClanUpdate(tag) {
196
196
  if (this._inMaintenance)
@@ -21,6 +21,7 @@ const HTTPError_1 = require("./HTTPError");
21
21
  const node_fetch_1 = __importDefault(require("node-fetch"));
22
22
  const https_1 = __importDefault(require("https"));
23
23
  const keyv_1 = __importDefault(require("keyv"));
24
+ const IP_REGEX = /\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}/g;
24
25
  const agent = new https_1.default.Agent({ keepAlive: true });
25
26
  /** Represents a Request Handler. */
26
27
  class RequestHandler {
@@ -110,7 +111,7 @@ class RequestHandler {
110
111
  if (res?.status === 403) {
111
112
  const index = this.keys.indexOf(key);
112
113
  this.keys.splice(index, 1);
113
- console.warn(`[WARN] Pre-defined key #${index + 1} is no longer valid. Removed from the key list.`);
114
+ process.emitWarning(`Pre-defined key #${index + 1} is no longer valid. Removed from the key list.`);
114
115
  }
115
116
  }
116
117
  }
@@ -121,19 +122,23 @@ class RequestHandler {
121
122
  headers: { 'Content-Type': 'application/json' },
122
123
  body: JSON.stringify({ email: this.email, password: this.password })
123
124
  });
124
- if (res.ok) {
125
- return this.getKeys(res.headers.get('set-cookie'));
126
- }
127
- throw new ReferenceError('Invalid email or password.');
125
+ const data = await res.json();
126
+ if (!res.ok)
127
+ throw new Error(`Invalid email or password. ${JSON.stringify(data)}`);
128
+ const ip = await this.getIp(data.temporaryAPIToken);
129
+ if (!ip)
130
+ throw new Error('Failed to get the IP address.');
131
+ return this.getKeys(res.headers.get('set-cookie'), ip);
128
132
  }
129
- async getKeys(cookie) {
130
- const ip = await this.getIp();
133
+ async getKeys(cookie, ip) {
131
134
  const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/apikey/list`, {
132
135
  method: 'POST',
133
136
  timeout: 10000,
134
137
  headers: { 'Content-Type': 'application/json', cookie }
135
138
  });
136
139
  const data = await res.json();
140
+ if (!res.ok)
141
+ throw new Error(`Failed to retrieve the API Keys. ${JSON.stringify(data)}`);
137
142
  // Get all available keys from the developer site.
138
143
  const keys = (data.keys ?? []);
139
144
  // Revoke keys for specified key name but not matching current IP address.
@@ -157,7 +162,7 @@ class RequestHandler {
157
162
  keys.push(key);
158
163
  }
159
164
  if (this.keys.length < this.keyCount && keys.length === 10) {
160
- console.warn(`[WARN] ${this.keyCount} key(s) were requested but failed to create ${this.keyCount - this.keys.length} more key(s).`);
165
+ process.emitWarning(`${this.keyCount} key(s) were requested but failed to create ${this.keyCount - this.keys.length} more key(s).`);
161
166
  }
162
167
  if (!this.keys.length) {
163
168
  throw new Error([
@@ -188,10 +193,20 @@ class RequestHandler {
188
193
  })
189
194
  });
190
195
  const data = await res.json();
196
+ if (!res.ok)
197
+ throw new Error(`Failed to create API Key. ${JSON.stringify(data)}`);
191
198
  return data.key;
192
199
  }
193
- async getIp() {
194
- return (0, node_fetch_1.default)('https://api.ipify.org/', { timeout: 10000 }).then((res) => res.text());
200
+ async getIp(token) {
201
+ try {
202
+ const decoded = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
203
+ const props = decoded.limits.find((limit) => limit.hasOwnProperty('cidrs'));
204
+ return props.cidrs[0].match(IP_REGEX)[0];
205
+ }
206
+ catch {
207
+ const body = await (0, node_fetch_1.default)('https://api.ipify.org', { timeout: 10000 }).then((res) => res.text());
208
+ return body.match(IP_REGEX)?.[0] ?? null;
209
+ }
195
210
  }
196
211
  }
197
212
  exports.RequestHandler = RequestHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clashofclans.js",
3
- "version": "2.0.0",
3
+ "version": "2.0.1-dev.82b84ba",
4
4
  "description": "JavaScript library for interacting with the Clash of Clans API",
5
5
  "author": "SUVAJIT <suvajit.me@gmail.com>",
6
6
  "license": "MIT",