clashofclans.js 2.3.0 → 2.4.0-dev.0d3fbc6

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,19 @@
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.4.0 (2021-12-28)
6
+
7
+ ### Features
8
+
9
+ - `ClanWar.getClanWarLeague`, `ClanWar.isCWL` and `ClanWar.isFriendly` are now available. ([#87](https://github.com/clashperk/clashofclans.js/pull/87))
10
+ - `RESTOptions.rejectIfNotValid` added to perform `res.ok` operations over `RESTManager` class. ([#87](https://github.com/clashperk/clashofclans.js/pull/87))
11
+ - `Icon.fileName` and `Icon.sizes` are now available in `Icon` class. ([#87](https://github.com/clashperk/clashofclans.js/pull/87))
12
+ - `Badge.fileName` and `Badge.sizes` are now available in `Badge` class. ([#87](https://github.com/clashperk/clashofclans.js/pull/87))
13
+
14
+ ### Deprecations
15
+
16
+ - `ClanWarMember.previousBestOpponentAttack` has been deprecated. Use `ClanWarAttack.previousBestAttack` instead. ([#87](https://github.com/clashperk/clashofclans.js/pull/87))
17
+
5
18
  ## 2.3.0 (2021-12-17)
6
19
 
7
20
  ### Features
package/LICENSE CHANGED
@@ -1,7 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 - 2021 csuvajit
4
- Copyright (c) 2020 - 2021 TheLearneer
3
+ Copyright (c) 2020 - 2021 ClashPerk
5
4
 
6
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
6
  of this software and associated documentation files (the "Software"), to deal
@@ -8,7 +8,7 @@ export declare class HTTPError extends Error {
8
8
  * The reason of this errored request.
9
9
  *
10
10
  * Expected values are `notFound`, `notInWar`, `accessDenied`, `accessDenied.invalidIp`, `privateWarLog`,
11
- * `badRequest`, `requestThrottled`, `serviceUnavailable`, `requestAborted` and `unknownException`.
11
+ * `badRequest`, `requestThrottled`, `inMaintenance`, `requestAborted` and `unknownException`.
12
12
  */
13
13
  reason: string;
14
14
  /** The HTTP status code of this request. */
@@ -1,10 +1,10 @@
1
- import { RequestHandler, SearchOptions, ClanSearchOptions, ClientOptions, OverrideOptions } from './RequestHandler';
1
+ import { RequestHandler, SearchOptions, ClanSearchOptions, RESTOptions, OverrideOptions } from './RequestHandler';
2
2
  import { APIClan, APIClanList, APIClanMemberList, APIClanRankingList, APIClanVersusRankingList, APIClanWar, APIClanWarLeagueGroup, APIClanWarLog, APIGoldPassSeason, APILabelList, APILeague, APILeagueList, APILeagueSeasonList, APILocation, APILocationList, APIPlayer, APIPlayerRankingList, APIPlayerSeasonRankingList, APIPlayerVersusRankingList, APIVerifyToken, APIWarLeague, APIWarLeagueList } from '../types';
3
3
  /** Represents a REST Manager of the client. */
4
4
  export declare class RESTManager {
5
5
  /** Request Handler for the RESTManager. */
6
6
  readonly handler: RequestHandler;
7
- constructor(options?: ClientOptions);
7
+ constructor(options?: RESTOptions);
8
8
  /** Search all clans by name and/or filtering the results using various criteria. */
9
9
  getClans(query: ClanSearchOptions, options?: OverrideOptions): Promise<import("./RequestHandler").Response<APIClanList>>;
10
10
  /** Get info about a clan. */
@@ -10,11 +10,12 @@ export declare class RequestHandler {
10
10
  private keyDescription?;
11
11
  private keys;
12
12
  private readonly baseURL;
13
+ private readonly rejectIfNotValid;
13
14
  private readonly retryLimit;
14
15
  private readonly restRequestTimeout;
15
16
  private readonly throttler?;
16
17
  private readonly cached;
17
- constructor(options?: ClientOptions);
18
+ constructor(options?: RESTOptions);
18
19
  private get _keys();
19
20
  private get _key();
20
21
  setKeys(keys: string[]): this;
@@ -28,7 +29,7 @@ export declare class RequestHandler {
28
29
  private createKey;
29
30
  private getIp;
30
31
  }
31
- /** Options for a client. */
32
+ /** Options for a Client. */
32
33
  export interface ClientOptions {
33
34
  /** Keys from Clash of Clans API developer site. */
34
35
  keys?: string[];
@@ -61,6 +62,11 @@ export interface ClientOptions {
61
62
  */
62
63
  throttler?: QueueThrottler | BatchThrottler;
63
64
  }
65
+ /** Options for a RESTManager. */
66
+ export interface RESTOptions extends ClientOptions {
67
+ /** Set this `false` to use `res.ok` property. */
68
+ rejectIfNotValid?: boolean;
69
+ }
64
70
  /** Search options for request. */
65
71
  export interface SearchOptions extends OverrideOptions {
66
72
  /** Limit the number of items returned in the response. */
@@ -98,6 +104,8 @@ export interface RequestOptions extends OverrideOptions {
98
104
  method?: string;
99
105
  }
100
106
  export interface Response<T> {
107
+ /** Whether the response is ok. */
108
+ ok: boolean;
101
109
  /** The response body. */
102
110
  data: T;
103
111
  /** Path of the request for this response. */
@@ -32,6 +32,7 @@ class RequestHandler {
32
32
  this.throttler = options?.throttler ?? null;
33
33
  this.baseURL = options?.baseURL ?? Constants_1.API_BASE_URL;
34
34
  this.restRequestTimeout = options?.restRequestTimeout ?? 0;
35
+ this.rejectIfNotValid = options?.rejectIfNotValid ?? true;
35
36
  if (options?.cache instanceof keyv_1.default)
36
37
  this.cached = options.cache;
37
38
  else
@@ -52,7 +53,7 @@ class RequestHandler {
52
53
  async request(path, options = {}) {
53
54
  const cached = (await this.cached?.get(path)) ?? null;
54
55
  if (cached && options.force !== true) {
55
- return { data: cached.data, maxAge: cached.ttl - Date.now(), status: 200, path };
56
+ return { data: cached.data, maxAge: cached.ttl - Date.now(), status: cached.status, path, ok: cached.status === 200 };
56
57
  }
57
58
  if (!this.throttler || options.ignoreRateLimit)
58
59
  return this.exec(path, options);
@@ -81,14 +82,16 @@ class RequestHandler {
81
82
  return this.exec(path, options, ++retries);
82
83
  }
83
84
  const maxAge = Number(res?.headers.get('cache-control')?.split('=')?.[1] ?? 0) * 1000;
84
- if (res?.status === 403 && !data?.message)
85
+ if (res?.status === 403 && !data?.message && this.rejectIfNotValid) {
85
86
  throw new HTTPError_1.HTTPError(HTTPError_1.PrivateWarLogError, res.status, path, maxAge);
86
- if (!res?.ok)
87
+ }
88
+ if (!res?.ok && this.rejectIfNotValid) {
87
89
  throw new HTTPError_1.HTTPError(data, res?.status ?? 504, path, maxAge, options.method);
90
+ }
88
91
  if (this.cached && maxAge > 0 && options.cache !== false) {
89
- await this.cached.set(path, { data, ttl: Date.now() + maxAge }, maxAge);
92
+ await this.cached.set(path, { data, ttl: Date.now() + maxAge, status: res?.status ?? 504 }, maxAge);
90
93
  }
91
- return { data, maxAge, status: res.status, path };
94
+ return { data, maxAge, status: res?.status ?? 504, path, ok: res?.status === 200 };
92
95
  }
93
96
  async init(options) {
94
97
  if (!(options.email && options.password))
@@ -1,16 +1,17 @@
1
1
  import { APIBadge } from '../types';
2
2
  /** Represents a Clash of Clans Badge. */
3
3
  export declare class Badge {
4
- private readonly _data;
5
4
  /** The default badge URL. */
6
5
  url: string;
7
- constructor(data: APIBadge);
8
6
  /** The large badge URL. */
9
- get large(): string;
7
+ large: string;
10
8
  /** The medium badge URL. */
11
- get medium(): string;
9
+ medium: string;
12
10
  /** The small badge URL. */
13
- get small(): string;
14
- /** Get unique hash of this Badge. */
15
- get hash(): string;
11
+ small: string;
12
+ constructor(data: APIBadge);
13
+ /** Get unique file name of this Badge. */
14
+ get fileName(): string;
15
+ /** Sizes of this Badge. */
16
+ get sizes(): string[];
16
17
  }
@@ -4,24 +4,18 @@ exports.Badge = void 0;
4
4
  /** Represents a Clash of Clans Badge. */
5
5
  class Badge {
6
6
  constructor(data) {
7
- Object.defineProperty(this, '_data', { value: data });
8
7
  this.url = data.large;
8
+ Object.defineProperty(this, 'large', { value: data.large });
9
+ Object.defineProperty(this, 'medium', { value: data.medium });
10
+ Object.defineProperty(this, 'small', { value: data.small });
9
11
  }
10
- /** The large badge URL. */
11
- get large() {
12
- return this._data.large;
13
- }
14
- /** The medium badge URL. */
15
- get medium() {
16
- return this._data.medium;
17
- }
18
- /** The small badge URL. */
19
- get small() {
20
- return this._data.small;
21
- }
22
- /** Get unique hash of this Badge. */
23
- get hash() {
12
+ /** Get unique file name of this Badge. */
13
+ get fileName() {
24
14
  return this.url.split('/').pop();
25
15
  }
16
+ /** Sizes of this Badge. */
17
+ get sizes() {
18
+ return [this.large, this.medium, this.small].map((url) => /\/(\d+)\//g.exec(url)[1]);
19
+ }
26
20
  }
27
21
  exports.Badge = Badge;
@@ -61,6 +61,8 @@ export declare class ClanWarMember {
61
61
  /**
62
62
  * Returns the previous best opponent attack on this village.
63
63
  * This is useful for calculating the new stars or destruction for new attacks.
64
+ *
65
+ * @deprecated `order` is affecting this method. Use {@link ClanWarAttack#previousBestAttack} instead.
64
66
  */
65
67
  previousBestOpponentAttack(): ClanWarAttack | null;
66
68
  }
@@ -131,7 +133,12 @@ export declare class ClanWar {
131
133
  getDefenses(defenderTag: string): ClanWarAttack[];
132
134
  /** Returns either `friendly`, `cwl` or `normal`. */
133
135
  get type(): "friendly" | "cwl" | "normal";
134
- private get _isFriendly();
136
+ /** Whether this is a friendly war. */
137
+ get isFriendly(): boolean;
138
+ /** Whether this is a CWL. */
139
+ get isCWL(): boolean;
135
140
  /** Returns the war status, based off the home clan. */
136
141
  get status(): "win" | "lose" | "tie" | "pending";
142
+ /** Returns the Clan War League Group. */
143
+ getClanWarLeagueGroup(): Promise<import("./ClanWarLeagueGroup").ClanWarLeagueGroup> | null;
137
144
  }
@@ -75,6 +75,8 @@ class ClanWarMember {
75
75
  /**
76
76
  * Returns the previous best opponent attack on this village.
77
77
  * This is useful for calculating the new stars or destruction for new attacks.
78
+ *
79
+ * @deprecated `order` is affecting this method. Use {@link ClanWarAttack#previousBestAttack} instead.
78
80
  */
79
81
  previousBestOpponentAttack() {
80
82
  return (
@@ -170,16 +172,21 @@ class ClanWar {
170
172
  }
171
173
  /** Returns either `friendly`, `cwl` or `normal`. */
172
174
  get type() {
173
- if (this._isFriendly)
175
+ if (this.isFriendly)
174
176
  return 'friendly';
175
177
  if (this.warTag)
176
178
  return 'cwl';
177
179
  return 'normal';
178
180
  }
179
- get _isFriendly() {
181
+ /** Whether this is a friendly war. */
182
+ get isFriendly() {
180
183
  const preparationTime = this.startTime.getTime() - this.preparationStartTime.getTime();
181
184
  return Constants_1.FRIENDLY_WAR_PREPARATION_TIMES.includes(preparationTime);
182
185
  }
186
+ /** Whether this is a CWL. */
187
+ get isCWL() {
188
+ return typeof this.warTag === 'string';
189
+ }
183
190
  /** Returns the war status, based off the home clan. */
184
191
  get status() {
185
192
  if (this.state === 'preparation')
@@ -194,5 +201,11 @@ class ClanWar {
194
201
  }
195
202
  return 'lose';
196
203
  }
204
+ /** Returns the Clan War League Group. */
205
+ getClanWarLeagueGroup() {
206
+ if (!this.isCWL)
207
+ return null;
208
+ return this.client.getClanWarLeagueGroup(this.clan.tag);
209
+ }
197
210
  }
198
211
  exports.ClanWar = ClanWar;
@@ -1,16 +1,17 @@
1
1
  import { APIIcon } from '../types';
2
2
  /** Represents a Clash of Clans Icon. */
3
3
  export declare class Icon {
4
- private readonly _data;
5
4
  /** The default icon URL. */
6
5
  url: string;
7
- constructor(data: APIIcon);
8
6
  /** The medium icon URL. */
9
- get medium(): string;
10
- /** The tiny icon URL. */
11
- get tiny(): string;
7
+ medium: string;
12
8
  /** The small icon URL. */
13
- get small(): string;
14
- /** Get unique hash of this Badge. */
15
- get hash(): string;
9
+ small: string;
10
+ /** The tiny icon URL. */
11
+ tiny: string;
12
+ constructor(data: APIIcon);
13
+ /** Get unique file name of this Icon. */
14
+ get fileName(): string;
15
+ /** Sizes of this Icon. */
16
+ get sizes(): string[];
16
17
  }
@@ -4,24 +4,18 @@ exports.Icon = void 0;
4
4
  /** Represents a Clash of Clans Icon. */
5
5
  class Icon {
6
6
  constructor(data) {
7
- Object.defineProperty(this, '_data', { value: data });
8
7
  this.url = data.medium ?? data.small;
8
+ Object.defineProperty(this, 'medium', { value: data.medium ?? data.small });
9
+ Object.defineProperty(this, 'tiny', { value: data.tiny ?? data.small });
10
+ Object.defineProperty(this, 'small', { value: data.small });
9
11
  }
10
- /** The medium icon URL. */
11
- get medium() {
12
- return this._data.medium ?? this._data.small;
13
- }
14
- /** The tiny icon URL. */
15
- get tiny() {
16
- return this._data.tiny ?? this._data.small;
17
- }
18
- /** The small icon URL. */
19
- get small() {
20
- return this._data.small;
21
- }
22
- /** Get unique hash of this Badge. */
23
- get hash() {
12
+ /** Get unique file name of this Icon. */
13
+ get fileName() {
24
14
  return this.url.split('/').pop();
25
15
  }
16
+ /** Sizes of this Icon. */
17
+ get sizes() {
18
+ return [this.medium, this.small, this.tiny].map((url) => /\/(\d+)\//g.exec(url)[1]);
19
+ }
26
20
  }
27
21
  exports.Icon = Icon;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clashofclans.js",
3
- "version": "2.3.0",
3
+ "version": "2.4.0-dev.0d3fbc6",
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",