clashofclans.js 2.0.2 → 2.1.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 CHANGED
@@ -2,6 +2,23 @@
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.1.0 (2021-12-06)
6
+
7
+ ### Bug Fixes
8
+
9
+ - Consistency of `ClanWar.attacksPerMember` property. ([#75](https://github.com/clashperk/clashofclans.js/pull/75)) ([6e23d2f](https://github.com/clashperk/clashofclans.js/commit/6e23d2fe0373f56268ffa55d5ac2807c9a2dc2fc))
10
+
11
+ ### Features
12
+
13
+ - More utility methods added to `Util` class. ([#76](https://github.com/clashperk/clashofclans.js/pull/76)) ([ff41115](https://github.com/clashperk/clashofclans.js/commit/ff4111530d6293ef1fc54aa916436130fc30a09c))
14
+ - `Util.formatTag(tag: string): string`
15
+ - `Util.formatDate(date: string): Date`
16
+ - `Util.isValidTag(tag: string): boolean`
17
+ - `Util.encodeTagToId(tag: string): string`
18
+ - `Util.decodeIdToTag(id: string): string`
19
+
20
+ - Support of async/await for custom events ([#79](https://github.com/clashperk/clashofclans.js/pull/79)) ([ff41115](https://github.com/clashperk/clashofclans.js/commit/a23db3786bcca44b8547c70f27773bdb1216f990))
21
+
5
22
  ## 2.0.2 (2021-11-30)
6
23
 
7
24
  ### Bug Fixes
@@ -34,14 +34,14 @@ class EventManager {
34
34
  /** Add clan tags to clan events. */
35
35
  addClans(tags) {
36
36
  for (const tag of Array.isArray(tags) ? tags : [tags]) {
37
- this._clanTags.add(this.client.util.parseTag(tag));
37
+ this._clanTags.add(this.client.util.formatTag(tag));
38
38
  }
39
39
  return this;
40
40
  }
41
41
  /** Delete clan tags from clan events. */
42
42
  deleteClans(tags) {
43
43
  for (const tag of Array.isArray(tags) ? tags : [tags]) {
44
- const key = this.client.util.parseTag(tag);
44
+ const key = this.client.util.formatTag(tag);
45
45
  this._clans.delete(key);
46
46
  this._clanTags.delete(key);
47
47
  }
@@ -50,14 +50,14 @@ class EventManager {
50
50
  /** Add player tags for player events. */
51
51
  addPlayers(tags) {
52
52
  for (const tag of Array.isArray(tags) ? tags : [tags]) {
53
- this._playerTags.add(this.client.util.parseTag(tag));
53
+ this._playerTags.add(this.client.util.formatTag(tag));
54
54
  }
55
55
  return this;
56
56
  }
57
57
  /** Delete player tags from player events. */
58
58
  deletePlayers(tags) {
59
59
  for (const tag of Array.isArray(tags) ? tags : [tags]) {
60
- const key = this.client.util.parseTag(tag);
60
+ const key = this.client.util.formatTag(tag);
61
61
  this._players.delete(key);
62
62
  this._playerTags.delete(key);
63
63
  }
@@ -66,14 +66,14 @@ class EventManager {
66
66
  /** Add clan tags for war events. */
67
67
  addWars(tags) {
68
68
  for (const tag of Array.isArray(tags) ? tags : [tags]) {
69
- this._warTags.add(this.client.util.parseTag(tag));
69
+ this._warTags.add(this.client.util.formatTag(tag));
70
70
  }
71
71
  return this;
72
72
  }
73
73
  /** Delete clan tags from war events. */
74
74
  deleteWars(tags) {
75
75
  for (const tag of Array.isArray(tags) ? tags : [tags]) {
76
- const key = this.client.util.parseTag(tag);
76
+ const key = this.client.util.formatTag(tag);
77
77
  this._wars.delete(`${key}:${1}`);
78
78
  this._wars.delete(`${key}:${2}`);
79
79
  this._warTags.delete(key);
@@ -203,7 +203,7 @@ class EventManager {
203
203
  return this._clans.set(clan.tag, clan);
204
204
  for (const { name, filter } of this._events.clans) {
205
205
  try {
206
- if (!filter(cached, clan))
206
+ if (!(await filter(cached, clan)))
207
207
  continue;
208
208
  this.client.emit(name, cached, clan);
209
209
  }
@@ -224,7 +224,7 @@ class EventManager {
224
224
  return this._players.set(player.tag, player);
225
225
  for (const { name, filter } of this._events.players) {
226
226
  try {
227
- if (!filter(cached, player))
227
+ if (!(await filter(cached, player)))
228
228
  continue;
229
229
  this.client.emit(name, cached, player);
230
230
  }
@@ -248,7 +248,7 @@ class EventManager {
248
248
  return this._wars.set(key, war);
249
249
  for (const { name, filter } of this._events.wars) {
250
250
  try {
251
- if (!filter(cached, war))
251
+ if (!(await filter(cached, war)))
252
252
  continue;
253
253
  this.client.emit(name, cached, war);
254
254
  }
@@ -262,7 +262,7 @@ class EventManager {
262
262
  if (data && data.warTag === cached.warTag) {
263
263
  for (const { name, filter } of this._events.wars) {
264
264
  try {
265
- if (!filter(cached, data))
265
+ if (!(await filter(cached, data)))
266
266
  continue;
267
267
  this.client.emit(name, cached, data);
268
268
  }
@@ -134,13 +134,13 @@ class ClanWar {
134
134
  // @ts-expect-error
135
135
  this.state = data.state;
136
136
  this.teamSize = data.teamSize;
137
- this.attacksPerMember = data.attacksPerMember;
138
- this.preparationStartTime = client.util.parseDate(data.preparationStartTime);
139
- this.startTime = client.util.parseDate(data.startTime);
140
- this.endTime = client.util.parseDate(data.endTime);
137
+ this.attacksPerMember = data.attacksPerMember ?? extra.warTag ? 1 : 2;
138
+ this.preparationStartTime = client.util.formatDate(data.preparationStartTime);
139
+ this.startTime = client.util.formatDate(data.startTime);
140
+ this.endTime = client.util.formatDate(data.endTime);
141
141
  this.warTag = extra.warTag ?? null;
142
142
  let [clan, opponent] = [data.clan, data.opponent];
143
- const clanTag = extra.clanTag && client.util.parseTag(extra.clanTag);
143
+ const clanTag = extra.clanTag && client.util.formatTag(extra.clanTag);
144
144
  if (clanTag && [data.clan.tag, data.opponent.tag].includes(clanTag)) {
145
145
  clan = data.clan.tag === clanTag ? data.clan : data.opponent;
146
146
  opponent = data.clan.tag === clan.tag ? data.opponent : data.clan;
@@ -28,7 +28,7 @@ class ClanWarLog {
28
28
  constructor(client, data) {
29
29
  this.client = client;
30
30
  this.result = data.result ?? null;
31
- this.endTime = Util_1.Util.parseDate(data.endTime);
31
+ this.endTime = Util_1.Util.formatDate(data.endTime);
32
32
  this.teamSize = data.teamSize;
33
33
  this.attacksPerMember = data.attacksPerMember ?? null;
34
34
  this.clan = new WarLogClan(data.clan);
@@ -14,8 +14,8 @@ exports.Season = Season;
14
14
  /** Represents a gold pass season. */
15
15
  class GoldPassSeason {
16
16
  constructor(data) {
17
- this.startTime = Util_1.Util.parseDate(data.startTime);
18
- this.endTime = Util_1.Util.parseDate(data.endTime);
17
+ this.startTime = Util_1.Util.formatDate(data.startTime);
18
+ this.endTime = Util_1.Util.formatDate(data.endTime);
19
19
  }
20
20
  }
21
21
  exports.GoldPassSeason = GoldPassSeason;
@@ -84,7 +84,8 @@ export interface APIClanWar {
84
84
  endTime: string;
85
85
  clan: APIWarClan;
86
86
  opponent: APIWarClan;
87
- attacksPerMember: number;
87
+ /** This property is not available for CWL */
88
+ attacksPerMember?: number;
88
89
  }
89
90
  export interface APIWarClan {
90
91
  tag: string;
@@ -1,17 +1,39 @@
1
1
  /** Contains various general-purpose utility methods. */
2
2
  export declare class Util extends null {
3
- /** Encode a game tag. */
4
- static encodeTag(tag: string): string;
5
- /** Parse a game tag. */
3
+ /**
4
+ * Corrects malformed tags to match how they are formatted.
5
+ * ```ts
6
+ * Util.formatTag("PccVqqGO"); // #PCCVQQG0
7
+ * ```
8
+ */
9
+ static formatTag(tag: string): string;
10
+ /** @internal */
6
11
  static parseTag(tag: string): string;
7
- /** Parse API Date to JavaScript Date. */
8
- static parseDate(time: string): Date;
9
- /** Get URL search params. */
12
+ /** Encodes a tag as a valid component of a URI. */
13
+ static encodeTag(tag: string): string;
14
+ static isValidTag(tag: string): boolean;
15
+ /**
16
+ * Encode tag string into 64bit unsigned integer string.
17
+ * ```ts
18
+ * Util.encodeTagToId('#PCCVQQG0'); // '510915076'
19
+ * ```
20
+ */
21
+ static encodeTagToId(tag: string): string;
22
+ /**
23
+ * Decode 64bit unsigned integer string into tag string with hash.
24
+ * ```ts
25
+ * Util.decodeTagToId('510915076'); // '#PCCVQQG0'
26
+ * ```
27
+ */
28
+ static decodeIdToTag(id: string): string;
29
+ /** Converts API Date to JavaScript Date. */
30
+ static formatDate(date: string): Date;
31
+ /** Returns a string containing a query string suitable for use in a URL. */
10
32
  static queryString(options?: {}): string;
11
33
  private static getSeasonEnd;
12
34
  /** Get current trophy season Id. */
13
35
  static getSeasonId(): string;
14
- /** Get current trophy season end time. */
36
+ /** Get current trophy season end date. */
15
37
  static getSeasonEndTime(date?: Date): Date;
16
38
  static allSettled<T>(values: Promise<T>[]): Promise<T[]>;
17
39
  static delay(ms: number): Promise<unknown>;
package/dist/util/Util.js CHANGED
@@ -1,21 +1,65 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Util = void 0;
4
+ const TAG_CHARACTERS = '0289PYLQGRJCUV';
4
5
  /** Contains various general-purpose utility methods. */
5
6
  class Util extends null {
6
- /** Encode a game tag. */
7
- static encodeTag(tag) {
8
- return encodeURIComponent(this.parseTag(tag));
7
+ /**
8
+ * Corrects malformed tags to match how they are formatted.
9
+ * ```ts
10
+ * Util.formatTag("PccVqqGO"); // #PCCVQQG0
11
+ * ```
12
+ */
13
+ static formatTag(tag) {
14
+ return this.parseTag(tag);
9
15
  }
10
- /** Parse a game tag. */
16
+ /** @internal */
11
17
  static parseTag(tag) {
12
- return `#${tag.toUpperCase().replace(/O/g, '0').replace(/^#/g, '')}`;
18
+ return `#${tag.toUpperCase().replace(/O/g, '0').replace(/^#/g, '').replace(/\s/g, '')}`;
19
+ }
20
+ /** Encodes a tag as a valid component of a URI. */
21
+ static encodeTag(tag) {
22
+ return encodeURIComponent(this.formatTag(tag));
23
+ }
24
+ static isValidTag(tag) {
25
+ return /^#?[0289PYLQGRJCUV]{3,}$/.test(tag);
26
+ }
27
+ /**
28
+ * Encode tag string into 64bit unsigned integer string.
29
+ * ```ts
30
+ * Util.encodeTagToId('#PCCVQQG0'); // '510915076'
31
+ * ```
32
+ */
33
+ static encodeTagToId(tag) {
34
+ const formatted = this.formatTag(tag).substring(1);
35
+ if (!this.isValidTag(formatted)) {
36
+ throw new Error(`Failed to encode tag ${formatted}. RegExp matching failed.`);
37
+ }
38
+ const result = formatted.split('').reduce((sum, char) => sum * 14n + BigInt(TAG_CHARACTERS.indexOf(char)), 0n);
39
+ return result.toString();
40
+ }
41
+ /**
42
+ * Decode 64bit unsigned integer string into tag string with hash.
43
+ * ```ts
44
+ * Util.decodeTagToId('510915076'); // '#PCCVQQG0'
45
+ * ```
46
+ */
47
+ static decodeIdToTag(id) {
48
+ let [bigint, tag] = [BigInt(id), ''];
49
+ while (bigint !== 0n) {
50
+ const index = Number(bigint % 14n);
51
+ tag = TAG_CHARACTERS[index] + tag;
52
+ bigint /= 14n;
53
+ }
54
+ return `#${tag}`;
13
55
  }
14
- /** Parse API Date to JavaScript Date. */
15
- static parseDate(time) {
16
- return new Date(`${time.slice(0, 4)}-${time.slice(4, 6)}-${time.slice(6, 8)}T${time.slice(9, 11)}:${time.slice(11, 13)}:${time.slice(13)}`);
56
+ /** Converts API Date to JavaScript Date. */
57
+ static formatDate(date) {
58
+ const YYYY_MM_DD = `${date.slice(0, 4)}-${date.slice(4, 6)}-${date.slice(6, 8)}`;
59
+ const HH_MM_SS = `${date.slice(9, 11)}:${date.slice(11, 13)}:${date.slice(13)}`;
60
+ return new Date(`${YYYY_MM_DD}T${HH_MM_SS}`);
17
61
  }
18
- /** Get URL search params. */
62
+ /** Returns a string containing a query string suitable for use in a URL. */
19
63
  static queryString(options = {}) {
20
64
  const query = new URLSearchParams(options);
21
65
  for (const key of ['cache', 'force', 'retryLimit', 'ignoreRateLimit', 'restRequestTimeout'])
@@ -37,7 +81,7 @@ class Util extends null {
37
81
  static getSeasonId() {
38
82
  return this.getSeasonEndTime().toISOString().substring(0, 7);
39
83
  }
40
- /** Get current trophy season end time. */
84
+ /** Get current trophy season end date. */
41
85
  static getSeasonEndTime(date = new Date()) {
42
86
  return this.getSeasonEnd(date.getUTCMonth() + 1);
43
87
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clashofclans.js",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
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",
@@ -12,6 +12,9 @@
12
12
  "test": "eslint --ext .ts --ignore-path .gitignore .",
13
13
  "lint": "eslint --fix --ext .ts --ignore-path .gitignore ."
14
14
  },
15
+ "files": [
16
+ "dist"
17
+ ],
15
18
  "repository": {
16
19
  "type": "git",
17
20
  "url": "https://github.com/clashperk/clashofclans.js.git"