clashofclans.js 2.6.0 → 2.6.1-dev.208c20e
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 +8 -1
- package/dist/client/Client.js +5 -2
- package/dist/index.mjs +66 -0
- package/dist/rest/RequestHandler.d.ts +1 -0
- package/dist/rest/RequestHandler.js +11 -5
- package/dist/struct/Clan.d.ts +2 -0
- package/dist/struct/Clan.js +4 -0
- package/dist/struct/ClanWar.d.ts +4 -0
- package/dist/struct/ClanWar.js +8 -0
- package/dist/struct/ClanWarLeagueGroup.d.ts +4 -0
- package/dist/struct/ClanWarLeagueGroup.js +9 -0
- package/dist/struct/ClanWarLog.d.ts +2 -0
- package/dist/struct/ClanWarLog.js +4 -0
- package/dist/struct/Player.d.ts +2 -0
- package/dist/struct/Player.js +4 -0
- package/dist/struct/PlayerClan.d.ts +2 -0
- package/dist/struct/PlayerClan.js +4 -0
- package/dist/struct/Ranking.d.ts +6 -0
- package/dist/struct/Ranking.js +12 -0
- package/dist/types/api.d.ts +1 -1
- package/dist/types/lib.d.ts +1 -1
- package/dist/util/Store.d.ts +2 -2
- package/dist/util/Util.d.ts +3 -0
- package/dist/util/Util.js +17 -2
- package/package.json +8 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,14 @@
|
|
|
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
|
-
|
|
5
|
+
# 2.6.1 (2022-02-03)
|
|
6
|
+
|
|
7
|
+
Bug Fixes
|
|
8
|
+
|
|
9
|
+
- New value and typings `notInWar` added for `ClanWarLeagueGroup#state` ([#101](https://github.com/clashperk/clashofclans.js/pull/101))
|
|
10
|
+
- Throw error if `Util.formatTag` / `Util.parseTag` is called with invalid argument ([#102](https://github.com/clashperk/clashofclans.js/pull/101))
|
|
11
|
+
|
|
12
|
+
## 2.6.0 (2022-01-29)
|
|
6
13
|
|
|
7
14
|
## Features
|
|
8
15
|
|
package/dist/client/Client.js
CHANGED
|
@@ -18,7 +18,7 @@ const struct_1 = require("../struct");
|
|
|
18
18
|
class Client extends events_1.EventEmitter {
|
|
19
19
|
constructor(options) {
|
|
20
20
|
super();
|
|
21
|
-
this.rest = new RESTManager_1.RESTManager(options);
|
|
21
|
+
this.rest = new RESTManager_1.RESTManager({ ...options, rejectIfNotValid: true });
|
|
22
22
|
this.events = new EventManager_1.EventManager(this);
|
|
23
23
|
}
|
|
24
24
|
/** Contains various general-purpose utility methods. */
|
|
@@ -150,7 +150,10 @@ class Client extends events_1.EventEmitter {
|
|
|
150
150
|
}
|
|
151
151
|
/** Get info about clan war league. */
|
|
152
152
|
async getClanWarLeagueGroup(clanTag, options) {
|
|
153
|
-
const { data } = await this.rest.getClanWarLeagueGroup(clanTag, options);
|
|
153
|
+
const { data, status, path, maxAge } = await this.rest.getClanWarLeagueGroup(clanTag, options);
|
|
154
|
+
if (data.state === 'notInWar') {
|
|
155
|
+
throw new HTTPError_1.HTTPError(HTTPError_1.NotInWarError, status, path, maxAge);
|
|
156
|
+
}
|
|
154
157
|
return new struct_1.ClanWarLeagueGroup(this, data);
|
|
155
158
|
}
|
|
156
159
|
/** Get info about a CWL round by WarTag. */
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import mod from "./index.js";
|
|
2
|
+
|
|
3
|
+
export default mod;
|
|
4
|
+
export const API_BASE_URL = mod.API_BASE_URL;
|
|
5
|
+
export const Achievement = mod.Achievement;
|
|
6
|
+
export const BUILDER_TROOPS = mod.BUILDER_TROOPS;
|
|
7
|
+
export const Badge = mod.Badge;
|
|
8
|
+
export const BatchThrottler = mod.BatchThrottler;
|
|
9
|
+
export const CWL_ROUNDS = mod.CWL_ROUNDS;
|
|
10
|
+
export const CacheStore = mod.CacheStore;
|
|
11
|
+
export const ChatLanguage = mod.ChatLanguage;
|
|
12
|
+
export const Clan = mod.Clan;
|
|
13
|
+
export const ClanMember = mod.ClanMember;
|
|
14
|
+
export const ClanWar = mod.ClanWar;
|
|
15
|
+
export const ClanWarAttack = mod.ClanWarAttack;
|
|
16
|
+
export const ClanWarLeagueClan = mod.ClanWarLeagueClan;
|
|
17
|
+
export const ClanWarLeagueClanMember = mod.ClanWarLeagueClanMember;
|
|
18
|
+
export const ClanWarLeagueGroup = mod.ClanWarLeagueGroup;
|
|
19
|
+
export const ClanWarLeagueRound = mod.ClanWarLeagueRound;
|
|
20
|
+
export const ClanWarLog = mod.ClanWarLog;
|
|
21
|
+
export const ClanWarMember = mod.ClanWarMember;
|
|
22
|
+
export const Client = mod.Client;
|
|
23
|
+
export const DARK_ELIXIR_SPELLS = mod.DARK_ELIXIR_SPELLS;
|
|
24
|
+
export const DARK_ELIXIR_TROOPS = mod.DARK_ELIXIR_TROOPS;
|
|
25
|
+
export const DEV_SITE_API_BASE_URL = mod.DEV_SITE_API_BASE_URL;
|
|
26
|
+
export const ELIXIR_SPELLS = mod.ELIXIR_SPELLS;
|
|
27
|
+
export const ELIXIR_TROOPS = mod.ELIXIR_TROOPS;
|
|
28
|
+
export const EVENTS = mod.EVENTS;
|
|
29
|
+
export const EventManager = mod.EventManager;
|
|
30
|
+
export const FRIENDLY_WAR_PREPARATION_TIMES = mod.FRIENDLY_WAR_PREPARATION_TIMES;
|
|
31
|
+
export const GoldPassSeason = mod.GoldPassSeason;
|
|
32
|
+
export const HEROES = mod.HEROES;
|
|
33
|
+
export const HERO_PETS = mod.HERO_PETS;
|
|
34
|
+
export const HOME_TROOPS = mod.HOME_TROOPS;
|
|
35
|
+
export const HTTPError = mod.HTTPError;
|
|
36
|
+
export const Hero = mod.Hero;
|
|
37
|
+
export const Icon = mod.Icon;
|
|
38
|
+
export const LEAGUES = mod.LEAGUES;
|
|
39
|
+
export const LEGEND_LEAGUE_ID = mod.LEGEND_LEAGUE_ID;
|
|
40
|
+
export const Label = mod.Label;
|
|
41
|
+
export const League = mod.League;
|
|
42
|
+
export const LegendStatistics = mod.LegendStatistics;
|
|
43
|
+
export const Location = mod.Location;
|
|
44
|
+
export const NotInWarError = mod.NotInWarError;
|
|
45
|
+
export const Player = mod.Player;
|
|
46
|
+
export const PlayerClan = mod.PlayerClan;
|
|
47
|
+
export const PrivateWarLogError = mod.PrivateWarLogError;
|
|
48
|
+
export const QueueThrottler = mod.QueueThrottler;
|
|
49
|
+
export const RESTManager = mod.RESTManager;
|
|
50
|
+
export const RankedClan = mod.RankedClan;
|
|
51
|
+
export const RankedPlayer = mod.RankedPlayer;
|
|
52
|
+
export const RequestHandler = mod.RequestHandler;
|
|
53
|
+
export const SIEGE_MACHINES = mod.SIEGE_MACHINES;
|
|
54
|
+
export const SPELLS = mod.SPELLS;
|
|
55
|
+
export const SUPER_TROOPS = mod.SUPER_TROOPS;
|
|
56
|
+
export const Season = mod.Season;
|
|
57
|
+
export const SeasonRankedPlayer = mod.SeasonRankedPlayer;
|
|
58
|
+
export const Spell = mod.Spell;
|
|
59
|
+
export const Troop = mod.Troop;
|
|
60
|
+
export const UNRANKED_LEAGUE_DATA = mod.UNRANKED_LEAGUE_DATA;
|
|
61
|
+
export const Unit = mod.Unit;
|
|
62
|
+
export const Util = mod.Util;
|
|
63
|
+
export const WAR_LEAGUES = mod.WAR_LEAGUES;
|
|
64
|
+
export const WarClan = mod.WarClan;
|
|
65
|
+
export const WarLeague = mod.WarLeague;
|
|
66
|
+
export const WarLogClan = mod.WarLogClan;
|
|
@@ -18,6 +18,7 @@ export declare class RequestHandler {
|
|
|
18
18
|
private get _keys();
|
|
19
19
|
private get _key();
|
|
20
20
|
setKeys(keys: string[]): this;
|
|
21
|
+
private get creds();
|
|
21
22
|
request<T>(path: string, options?: RequestOptions): Promise<Response<T>>;
|
|
22
23
|
private exec;
|
|
23
24
|
init(options: LoginOptions): Promise<string[]>;
|
|
@@ -50,6 +50,9 @@ class RequestHandler {
|
|
|
50
50
|
this.keys = keys;
|
|
51
51
|
return this;
|
|
52
52
|
}
|
|
53
|
+
get creds() {
|
|
54
|
+
return Boolean(this.email && this.password);
|
|
55
|
+
}
|
|
53
56
|
async request(path, options = {}) {
|
|
54
57
|
const cached = (await this.cached?.get(path)) ?? null;
|
|
55
58
|
if (cached && options.force !== true) {
|
|
@@ -76,8 +79,11 @@ class RequestHandler {
|
|
|
76
79
|
const data = await res?.json().catch(() => null);
|
|
77
80
|
if (!res && retries < (options.retryLimit ?? this.retryLimit))
|
|
78
81
|
return this.exec(path, options, ++retries);
|
|
79
|
-
if (
|
|
80
|
-
|
|
82
|
+
if (this.creds &&
|
|
83
|
+
res?.status === 403 &&
|
|
84
|
+
data?.reason === 'accessDenied.invalidIp' &&
|
|
85
|
+
retries < (options.retryLimit ?? this.retryLimit)) {
|
|
86
|
+
const keys = await this.reValidateKeys().then(() => () => this.login());
|
|
81
87
|
if (keys.length)
|
|
82
88
|
return this.exec(path, options, ++retries);
|
|
83
89
|
}
|
|
@@ -114,7 +120,7 @@ class RequestHandler {
|
|
|
114
120
|
if (res?.status === 403) {
|
|
115
121
|
const index = this.keys.indexOf(key);
|
|
116
122
|
this.keys.splice(index, 1);
|
|
117
|
-
process.emitWarning(`
|
|
123
|
+
process.emitWarning(`Key #${index + 1} is no longer valid. Removed from the key list.`);
|
|
118
124
|
}
|
|
119
125
|
}
|
|
120
126
|
}
|
|
@@ -145,14 +151,14 @@ class RequestHandler {
|
|
|
145
151
|
// Get all available keys from the developer site.
|
|
146
152
|
const keys = (data.keys ?? []);
|
|
147
153
|
// Revoke keys for specified key name but not matching current IP address.
|
|
148
|
-
for (const key of keys.filter((key) => key.name === this.keyName && !key.cidrRanges
|
|
154
|
+
for (const key of keys.filter((key) => key.name === this.keyName && !key.cidrRanges?.includes(ip))) {
|
|
149
155
|
if (!(await this.revokeKey(key.id, cookie)))
|
|
150
156
|
continue;
|
|
151
157
|
const index = keys.findIndex(({ id }) => id === key.id);
|
|
152
158
|
keys.splice(index, 1);
|
|
153
159
|
}
|
|
154
160
|
// Filter keys for current IP address and specified key name.
|
|
155
|
-
for (const key of keys.filter((key) => key.name === this.keyName && key.cidrRanges
|
|
161
|
+
for (const key of keys.filter((key) => key.name === this.keyName && key.cidrRanges?.includes(ip))) {
|
|
156
162
|
if (this.keys.length >= this.keyCount)
|
|
157
163
|
break;
|
|
158
164
|
if (!this.keys.includes(key.key))
|
package/dist/struct/Clan.d.ts
CHANGED
|
@@ -60,4 +60,6 @@ export declare class Clan {
|
|
|
60
60
|
constructor(client: Client, data: APIClan);
|
|
61
61
|
/** Get {@link Player} info for every Player in the clan. */
|
|
62
62
|
fetchMembers(options?: OverrideOptions): Promise<Player[]>;
|
|
63
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
64
|
+
get shareLink(): string;
|
|
63
65
|
}
|
package/dist/struct/Clan.js
CHANGED
|
@@ -40,5 +40,9 @@ class Clan {
|
|
|
40
40
|
.filter((res) => res.status === 'fulfilled')
|
|
41
41
|
.map((res) => res.value);
|
|
42
42
|
}
|
|
43
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
44
|
+
get shareLink() {
|
|
45
|
+
return `https://link.clashofclans.com/en?action=OpenClanProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
46
|
+
}
|
|
43
47
|
}
|
|
44
48
|
exports.Clan = Clan;
|
package/dist/struct/ClanWar.d.ts
CHANGED
|
@@ -58,6 +58,8 @@ export declare class ClanWarMember {
|
|
|
58
58
|
get defenses(): ClanWarAttack[];
|
|
59
59
|
/** Best opponent attack on this base. */
|
|
60
60
|
get bestOpponentAttack(): ClanWarAttack | null;
|
|
61
|
+
/** Get member's formatted link to open member in-game. */
|
|
62
|
+
get shareLink(): string;
|
|
61
63
|
/**
|
|
62
64
|
* Returns the previous best opponent attack on this village.
|
|
63
65
|
* This is useful for calculating the new stars or destruction for new attacks.
|
|
@@ -96,6 +98,8 @@ export declare class WarClan {
|
|
|
96
98
|
get defenses(): ClanWarAttack[];
|
|
97
99
|
/** Get a member of the clan for the given tag, or `null` if not found. */
|
|
98
100
|
getMember(tag: string): ClanWarMember | null;
|
|
101
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
102
|
+
get shareLink(): string;
|
|
99
103
|
}
|
|
100
104
|
/** Represents a Clan War in Clash of Clans. */
|
|
101
105
|
export declare class ClanWar {
|
package/dist/struct/ClanWar.js
CHANGED
|
@@ -72,6 +72,10 @@ class ClanWarMember {
|
|
|
72
72
|
return null;
|
|
73
73
|
return this.war.getAttack(this._bestOpponentAttackerTag, this.tag);
|
|
74
74
|
}
|
|
75
|
+
/** Get member's formatted link to open member in-game. */
|
|
76
|
+
get shareLink() {
|
|
77
|
+
return `https://link.clashofclans.com/en?action=OpenPlayerProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
78
|
+
}
|
|
75
79
|
/**
|
|
76
80
|
* Returns the previous best opponent attack on this village.
|
|
77
81
|
* This is useful for calculating the new stars or destruction for new attacks.
|
|
@@ -127,6 +131,10 @@ class WarClan {
|
|
|
127
131
|
getMember(tag) {
|
|
128
132
|
return this.members.find((m) => m.tag === tag) ?? null;
|
|
129
133
|
}
|
|
134
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
135
|
+
get shareLink() {
|
|
136
|
+
return `https://link.clashofclans.com/en?action=OpenClanProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
137
|
+
}
|
|
130
138
|
}
|
|
131
139
|
exports.WarClan = WarClan;
|
|
132
140
|
/** Represents a Clan War in Clash of Clans. */
|
|
@@ -12,6 +12,8 @@ export declare class ClanWarLeagueClanMember {
|
|
|
12
12
|
/** The member's town hall level. */
|
|
13
13
|
townHallLevel: number;
|
|
14
14
|
constructor(data: APIClanWarLeagueClanMember);
|
|
15
|
+
/** Get member's formatted link to open member in-game. */
|
|
16
|
+
get shareLink(): string;
|
|
15
17
|
}
|
|
16
18
|
/** Represents a Clan of CWL Group. */
|
|
17
19
|
export declare class ClanWarLeagueClan {
|
|
@@ -29,6 +31,8 @@ export declare class ClanWarLeagueClan {
|
|
|
29
31
|
constructor(client: Client, data: APIClanWarLeagueClan);
|
|
30
32
|
/** Get {@link Player} info for every members that are in the CWL group. */
|
|
31
33
|
fetchMembers(options?: OverrideOptions): Promise<Player[]>;
|
|
34
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
35
|
+
get shareLink(): string;
|
|
32
36
|
}
|
|
33
37
|
/** Represents a Round of CWL Group. */
|
|
34
38
|
export declare class ClanWarLeagueRound {
|
|
@@ -9,6 +9,10 @@ class ClanWarLeagueClanMember {
|
|
|
9
9
|
this.tag = data.tag;
|
|
10
10
|
this.townHallLevel = data.townHallLevel;
|
|
11
11
|
}
|
|
12
|
+
/** Get member's formatted link to open member in-game. */
|
|
13
|
+
get shareLink() {
|
|
14
|
+
return `https://link.clashofclans.com/en?action=OpenPlayerProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
exports.ClanWarLeagueClanMember = ClanWarLeagueClanMember;
|
|
14
18
|
/** Represents a Clan of CWL Group. */
|
|
@@ -27,6 +31,10 @@ class ClanWarLeagueClan {
|
|
|
27
31
|
.filter((res) => res.status === 'fulfilled')
|
|
28
32
|
.map((res) => res.value);
|
|
29
33
|
}
|
|
34
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
35
|
+
get shareLink() {
|
|
36
|
+
return `https://link.clashofclans.com/en?action=OpenClanProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
37
|
+
}
|
|
30
38
|
}
|
|
31
39
|
exports.ClanWarLeagueClan = ClanWarLeagueClan;
|
|
32
40
|
/** Represents a Round of CWL Group. */
|
|
@@ -41,6 +49,7 @@ exports.ClanWarLeagueRound = ClanWarLeagueRound;
|
|
|
41
49
|
class ClanWarLeagueGroup {
|
|
42
50
|
constructor(client, data) {
|
|
43
51
|
this.client = client;
|
|
52
|
+
// @ts-expect-error
|
|
44
53
|
this.state = data.state;
|
|
45
54
|
this.season = data.season;
|
|
46
55
|
this.clans = data.clans.map((clan) => new ClanWarLeagueClan(client, clan));
|
|
@@ -31,6 +31,8 @@ export declare class WarLogClan {
|
|
|
31
31
|
*/
|
|
32
32
|
attackCount: number | null;
|
|
33
33
|
constructor(data: APIWarLogClan);
|
|
34
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
35
|
+
get shareLink(): string | null;
|
|
34
36
|
}
|
|
35
37
|
export declare class ClanWarLog {
|
|
36
38
|
client: Client;
|
|
@@ -20,6 +20,10 @@ class WarLogClan {
|
|
|
20
20
|
this.destruction = data.destructionPercentage;
|
|
21
21
|
this.expEarned = data.expEarned ?? null;
|
|
22
22
|
}
|
|
23
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
24
|
+
get shareLink() {
|
|
25
|
+
return this.tag ? `https://link.clashofclans.com/en?action=OpenClanProfile&tag=${this.tag.replace(/#/g, '')}` : null;
|
|
26
|
+
}
|
|
23
27
|
}
|
|
24
28
|
exports.WarLogClan = WarLogClan;
|
|
25
29
|
class ClanWarLog {
|
package/dist/struct/Player.d.ts
CHANGED
package/dist/struct/Player.js
CHANGED
|
@@ -76,5 +76,9 @@ class Player {
|
|
|
76
76
|
.filter((entry) => Constants_1.SIEGE_MACHINES.includes(entry.name))
|
|
77
77
|
.sort((a, b) => Constants_1.SIEGE_MACHINES.indexOf(a.name) - Constants_1.SIEGE_MACHINES.indexOf(b.name));
|
|
78
78
|
}
|
|
79
|
+
/** Get player's formatted link to open player in-game. */
|
|
80
|
+
get shareLink() {
|
|
81
|
+
return `https://link.clashofclans.com/en?action=OpenPlayerProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
82
|
+
}
|
|
79
83
|
}
|
|
80
84
|
exports.Player = Player;
|
|
@@ -19,4 +19,6 @@ export declare class PlayerClan {
|
|
|
19
19
|
constructor(_client: Client, data: APIPlayerClan);
|
|
20
20
|
/** Fetch detailed clan info for the player's clan. */
|
|
21
21
|
fetch(options?: OverrideOptions): Promise<import("./Clan").Clan>;
|
|
22
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
23
|
+
get shareLink(): string;
|
|
22
24
|
}
|
|
@@ -15,5 +15,9 @@ class PlayerClan {
|
|
|
15
15
|
fetch(options) {
|
|
16
16
|
return this._client.getClan(this.tag, options);
|
|
17
17
|
}
|
|
18
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
19
|
+
get shareLink() {
|
|
20
|
+
return `https://link.clashofclans.com/en?action=OpenClanProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
exports.PlayerClan = PlayerClan;
|
package/dist/struct/Ranking.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export declare class SeasonRankedPlayer {
|
|
|
23
23
|
/** The player's clan. */
|
|
24
24
|
clan: PlayerClan | null;
|
|
25
25
|
constructor(client: Client, data: Omit<APIPlayerRanking, 'league'>);
|
|
26
|
+
/** Get player's formatted link to open player in-game. */
|
|
27
|
+
get shareLink(): string;
|
|
26
28
|
}
|
|
27
29
|
/** Represents the Player of location based leader-board ranking. */
|
|
28
30
|
export declare class RankedPlayer {
|
|
@@ -51,6 +53,8 @@ export declare class RankedPlayer {
|
|
|
51
53
|
/** The player's league. If retrieving info for versus leader-boards, this will be `null`. */
|
|
52
54
|
league: League | null;
|
|
53
55
|
constructor(client: Client, data: APIPlayerRanking | APIPlayerVersusRanking);
|
|
56
|
+
/** Get player's formatted link to open player in-game. */
|
|
57
|
+
get shareLink(): string;
|
|
54
58
|
}
|
|
55
59
|
/** Represents the Clan of location based leader-board ranking. */
|
|
56
60
|
export declare class RankedClan {
|
|
@@ -75,4 +79,6 @@ export declare class RankedClan {
|
|
|
75
79
|
/** The clan's badge. */
|
|
76
80
|
badge: Badge;
|
|
77
81
|
constructor(data: APIClanRanking | APIClanVersusRanking);
|
|
82
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
83
|
+
get shareLink(): string;
|
|
78
84
|
}
|
package/dist/struct/Ranking.js
CHANGED
|
@@ -19,6 +19,10 @@ class SeasonRankedPlayer {
|
|
|
19
19
|
// @ts-expect-error
|
|
20
20
|
this.clan = data.clan ? new PlayerClan_1.PlayerClan(client, data.clan) : null;
|
|
21
21
|
}
|
|
22
|
+
/** Get player's formatted link to open player in-game. */
|
|
23
|
+
get shareLink() {
|
|
24
|
+
return `https://link.clashofclans.com/en?action=OpenPlayerProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
25
|
+
}
|
|
22
26
|
}
|
|
23
27
|
exports.SeasonRankedPlayer = SeasonRankedPlayer;
|
|
24
28
|
/** Represents the Player of location based leader-board ranking. */
|
|
@@ -44,6 +48,10 @@ class RankedPlayer {
|
|
|
44
48
|
// @ts-expect-error
|
|
45
49
|
this.league = data.trophies ? new League_1.League(data.league ?? Constants_1.UNRANKED_LEAGUE_DATA) : null; // eslint-disable-line
|
|
46
50
|
}
|
|
51
|
+
/** Get player's formatted link to open player in-game. */
|
|
52
|
+
get shareLink() {
|
|
53
|
+
return `https://link.clashofclans.com/en?action=OpenPlayerProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
54
|
+
}
|
|
47
55
|
}
|
|
48
56
|
exports.RankedPlayer = RankedPlayer;
|
|
49
57
|
/** Represents the Clan of location based leader-board ranking. */
|
|
@@ -62,5 +70,9 @@ class RankedClan {
|
|
|
62
70
|
this.previousRank = data.previousRank;
|
|
63
71
|
this.badge = new Badge_1.Badge(data.badgeUrls);
|
|
64
72
|
}
|
|
73
|
+
/** Get clan's formatted link to open clan in-game. */
|
|
74
|
+
get shareLink() {
|
|
75
|
+
return `https://link.clashofclans.com/en?action=OpenClanProfile&tag=${this.tag.replace(/#/g, '')}`;
|
|
76
|
+
}
|
|
65
77
|
}
|
|
66
78
|
exports.RankedClan = RankedClan;
|
package/dist/types/api.d.ts
CHANGED
|
@@ -139,7 +139,7 @@ export interface APIClanWarLog {
|
|
|
139
139
|
}
|
|
140
140
|
/** /clans/{clanTag}/currentwar/leaguegroup */
|
|
141
141
|
export interface APIClanWarLeagueGroup {
|
|
142
|
-
state: 'preparation' | 'inWar' | 'ended';
|
|
142
|
+
state: 'notInWar' | 'preparation' | 'inWar' | 'ended';
|
|
143
143
|
season: string;
|
|
144
144
|
clans: APIClanWarLeagueClan[];
|
|
145
145
|
rounds: APIClanWarLeagueRound[];
|
package/dist/types/lib.d.ts
CHANGED
|
@@ -67,7 +67,7 @@ export interface OverrideOptions {
|
|
|
67
67
|
/** Whether to skip the cache check and request the API. */
|
|
68
68
|
force?: boolean;
|
|
69
69
|
/** How many times to retry on 5XX errors. */
|
|
70
|
-
retryLimit?:
|
|
70
|
+
retryLimit?: number;
|
|
71
71
|
/** Whether to ignore throttlers. */
|
|
72
72
|
ignoreRateLimit?: boolean;
|
|
73
73
|
/** Time to wait before cancelling a REST request, in milliseconds. */
|
package/dist/util/Store.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ export interface CacheOptions {
|
|
|
15
15
|
*/
|
|
16
16
|
ttl?: number;
|
|
17
17
|
}
|
|
18
|
-
export declare class CacheStore<T
|
|
18
|
+
export declare class CacheStore<T> implements Store<T> {
|
|
19
19
|
private readonly ttl;
|
|
20
|
-
private readonly sweepInterval
|
|
20
|
+
private readonly sweepInterval;
|
|
21
21
|
private readonly store;
|
|
22
22
|
constructor(options?: CacheOptions);
|
|
23
23
|
private _sweep;
|
package/dist/util/Util.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Clan, ClanMember } from '../struct';
|
|
1
2
|
import { ClanSearchOptions, SearchOptions } from '../types';
|
|
2
3
|
/** Contains various general-purpose utility methods. */
|
|
3
4
|
export declare class Util extends null {
|
|
@@ -39,4 +40,6 @@ export declare class Util extends null {
|
|
|
39
40
|
static getSeasonEndTime(timestamp?: Date): Date;
|
|
40
41
|
static allSettled<T>(values: Promise<T>[]): Promise<T[]>;
|
|
41
42
|
static delay(ms: number): Promise<unknown>;
|
|
43
|
+
static joinedMembers(oldClan: Clan, newClan: Clan): ClanMember[];
|
|
44
|
+
static leftMembers(oldClan: Clan, newClan: Clan): ClanMember[];
|
|
42
45
|
}
|
package/dist/util/Util.js
CHANGED
|
@@ -28,7 +28,10 @@ class Util extends null {
|
|
|
28
28
|
}
|
|
29
29
|
/** @internal */
|
|
30
30
|
static parseTag(tag) {
|
|
31
|
-
|
|
31
|
+
if (tag && typeof tag === 'string') {
|
|
32
|
+
return `#${tag.toUpperCase().replace(/O/g, '0').replace(/^#/g, '').replace(/\s/g, '')}`;
|
|
33
|
+
}
|
|
34
|
+
throw new TypeError('The "tag" argument must be of type string.');
|
|
32
35
|
}
|
|
33
36
|
/** Encodes a tag as a valid component of a URI. */
|
|
34
37
|
static encodeURI(tag) {
|
|
@@ -47,7 +50,7 @@ class Util extends null {
|
|
|
47
50
|
static encodeTag(tag) {
|
|
48
51
|
const formatted = this.formatTag(tag).substring(1);
|
|
49
52
|
if (!this.isValidTag(formatted)) {
|
|
50
|
-
throw new
|
|
53
|
+
throw new TypeError(`Failed to encode tag ${formatted}. RegExp matching failed.`);
|
|
51
54
|
}
|
|
52
55
|
const result = formatted.split('').reduce((sum, char) => sum * BigInt(14) + BigInt(TAG_CHARACTERS.indexOf(char)), BigInt(0));
|
|
53
56
|
return result.toString();
|
|
@@ -108,5 +111,17 @@ class Util extends null {
|
|
|
108
111
|
static async delay(ms) {
|
|
109
112
|
return new Promise((res) => setTimeout(res, ms));
|
|
110
113
|
}
|
|
114
|
+
static joinedMembers(oldClan, newClan) {
|
|
115
|
+
const oldMembers = oldClan.members.map((member) => member.tag);
|
|
116
|
+
return newClan.members.filter((member) => {
|
|
117
|
+
return !oldMembers.includes(member.tag);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
static leftMembers(oldClan, newClan) {
|
|
121
|
+
const newMembers = newClan.members.map((member) => member.tag);
|
|
122
|
+
return oldClan.members.filter((member) => {
|
|
123
|
+
return !newMembers.includes(member.tag);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
111
126
|
}
|
|
112
127
|
exports.Util = Util;
|
package/package.json
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clashofclans.js",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1-dev.208c20e",
|
|
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",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
|
-
"
|
|
8
|
+
"exports": {
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
9
13
|
"scripts": {
|
|
10
|
-
"build": "tsc",
|
|
14
|
+
"build": "tsc && gen-esm-wrapper dist/index.js dist/index.mjs",
|
|
11
15
|
"prepare": "rimraf dist && npm run build",
|
|
12
16
|
"test": "eslint --ext .ts --ignore-path .gitignore .",
|
|
13
17
|
"lint": "eslint --fix --ext .ts --ignore-path .gitignore ."
|
|
@@ -104,6 +108,7 @@
|
|
|
104
108
|
"eslint-config-marine": "^9.0.6",
|
|
105
109
|
"eslint-config-prettier": "^8.3.0",
|
|
106
110
|
"eslint-plugin-prettier": "^4.0.0",
|
|
111
|
+
"gen-esm-wrapper": "^1.1.3",
|
|
107
112
|
"prettier": "^2.4.1",
|
|
108
113
|
"rimraf": "^3.0.2",
|
|
109
114
|
"typescript": "^4.5.2"
|