clashofclans.js 3.4.2-dev.559ce53 → 3.5.0-dev.3cbb1a6

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.
@@ -203,7 +203,7 @@ class Client extends node_events_1.EventEmitter {
203
203
  /** Get Legend League season Ids. */
204
204
  async getLeagueSeasons(options) {
205
205
  const { body } = await this.rest.getLeagueSeasons(Constants_1.LegendLeagueId, options);
206
- return body.items.map((league) => league.id);
206
+ return body.items.map((item) => item.id);
207
207
  }
208
208
  /** Get Legend League season rankings by season Id. */
209
209
  async getSeasonRankings(seasonId, options) {
@@ -1,6 +1,6 @@
1
1
  import { Client } from '../client/Client';
2
2
  import { APIClanMember, APILeagueTier, APIPlayerHouse, OverrideOptions } from '../types';
3
- import { League } from './League';
3
+ import { LeagueTier } from './LeagueTier';
4
4
  export declare class ClanMember {
5
5
  /** The member's name. */
6
6
  name: string;
@@ -13,7 +13,7 @@ export declare class ClanMember {
13
13
  /** The member's Town Hall level. */
14
14
  townHallLevel: number;
15
15
  /** The member's current League. */
16
- league: League;
16
+ leagueTier: LeagueTier;
17
17
  /** The member's current Builder Base League. */
18
18
  builderBaseLeague: Omit<APILeagueTier, 'iconUrls'> | null;
19
19
  /** The member's trophy count. */
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.ClanMember = void 0;
10
10
  const Constants_1 = require("../util/Constants");
11
11
  const Decorators_1 = require("../util/Decorators");
12
- const League_1 = require("./League");
12
+ const LeagueTier_1 = require("./LeagueTier");
13
13
  class ClanMember {
14
14
  constructor(client, data) {
15
15
  this.client = client;
@@ -19,7 +19,7 @@ class ClanMember {
19
19
  this.role = data.role.replace('admin', 'elder');
20
20
  this.expLevel = data.expLevel;
21
21
  // eslint-disable-next-line
22
- this.league = new League_1.League(data.leagueTier ?? Constants_1.UnrankedLeagueData);
22
+ this.leagueTier = new LeagueTier_1.LeagueTier(data.leagueTier ?? Constants_1.UnrankedLeagueData);
23
23
  this.trophies = data.trophies;
24
24
  this.builderBaseTrophies = data.builderBaseTrophies ?? null;
25
25
  this.clanRank = data.clanRank;
@@ -1,7 +1,7 @@
1
1
  import { APILeagueTier } from '../types';
2
2
  import { Icon } from './Icon';
3
3
  /** Represents a Player's League. */
4
- export declare class League {
4
+ export declare class LeagueTier {
5
5
  /** The league Id. */
6
6
  id: number;
7
7
  /** The league name. */
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.League = void 0;
3
+ exports.LeagueTier = void 0;
4
4
  const Constants_1 = require("../util/Constants");
5
5
  const Icon_1 = require("./Icon");
6
6
  /** Represents a Player's League. */
7
- class League {
7
+ class LeagueTier {
8
8
  constructor(data) {
9
9
  this.id = data.id;
10
10
  this.name = data.name;
@@ -15,4 +15,4 @@ class League {
15
15
  return Constants_1.Leagues.indexOf(this.id);
16
16
  }
17
17
  }
18
- exports.League = League;
18
+ exports.LeagueTier = LeagueTier;
@@ -2,7 +2,7 @@ import { Client } from '../client/Client';
2
2
  import { APIPlayer, APIPlayerHouse, OverrideOptions } from '../types';
3
3
  import { Achievement } from './Achievement';
4
4
  import { Label } from './Label';
5
- import { League } from './League';
5
+ import { LeagueTier } from './LeagueTier';
6
6
  import { LegendStatistics } from './LegendStatistics';
7
7
  import { PlayerClan } from './PlayerClan';
8
8
  import { Equipment, Hero, Spell, Troop } from './Unit';
@@ -47,7 +47,7 @@ export declare class Player {
47
47
  /** The player's clan. */
48
48
  clan: PlayerClan | null;
49
49
  /** The player's current League. */
50
- league: League;
50
+ leagueTier: LeagueTier;
51
51
  /** The player's legend statistics, or `null` if they have never been in the legend league. */
52
52
  legendStatistics: LegendStatistics | null;
53
53
  /** An array of the player's achievements. */
@@ -11,7 +11,7 @@ const Constants_1 = require("../util/Constants");
11
11
  const Decorators_1 = require("../util/Decorators");
12
12
  const Achievement_1 = require("./Achievement");
13
13
  const Label_1 = require("./Label");
14
- const League_1 = require("./League");
14
+ const LeagueTier_1 = require("./LeagueTier");
15
15
  const LegendStatistics_1 = require("./LegendStatistics");
16
16
  const PlayerClan_1 = require("./PlayerClan");
17
17
  const Unit_1 = require("./Unit");
@@ -39,7 +39,7 @@ class Player {
39
39
  this.role = data.role?.replace('admin', 'elder') ?? null;
40
40
  this.warOptedIn = data.warPreference ? data.warPreference === 'in' : null;
41
41
  this.clan = data.clan ? new PlayerClan_1.PlayerClan(client, data.clan) : null;
42
- this.league = new League_1.League(data.leagueTier ?? Constants_1.UnrankedLeagueData);
42
+ this.leagueTier = new LeagueTier_1.LeagueTier(data.leagueTier ?? Constants_1.UnrankedLeagueData);
43
43
  this.legendStatistics = data.legendStatistics ? new LegendStatistics_1.LegendStatistics(data.legendStatistics) : null;
44
44
  this.achievements = data.achievements.map((data) => new Achievement_1.Achievement(data));
45
45
  this.labels = data.labels.map((data) => new Label_1.Label(data));
@@ -1,7 +1,7 @@
1
1
  import { Client } from '../client/Client';
2
2
  import { APIClanBuilderBaseRanking, APIClanRanking, APIPlayerBuilderBaseRanking, APIPlayerRanking } from '../types';
3
3
  import { Badge } from './Badge';
4
- import { League } from './League';
4
+ import { LeagueTier } from './LeagueTier';
5
5
  import { Location } from './Location';
6
6
  import { PlayerClan } from './PlayerClan';
7
7
  /** Represents the Player of seasonal legend league leader-board ranking. */
@@ -22,7 +22,7 @@ export declare class SeasonRankedPlayer {
22
22
  rank: number;
23
23
  /** The player's clan. */
24
24
  clan: PlayerClan | null;
25
- constructor(client: Client, data: Omit<APIPlayerRanking, 'league'>);
25
+ constructor(client: Client, data: Omit<APIPlayerRanking, 'leagueTier'>);
26
26
  /** Get player's formatted link to open player in-game. */
27
27
  get shareLink(): string;
28
28
  }
@@ -49,7 +49,7 @@ export declare class RankedPlayer {
49
49
  /** The player's clan. */
50
50
  clan: PlayerClan | null;
51
51
  /** The player's league. If retrieving info for builder base leader-boards, this will be `null`. */
52
- league: League | null;
52
+ leagueTier: LeagueTier | null;
53
53
  constructor(client: Client, data: APIPlayerRanking | APIPlayerBuilderBaseRanking);
54
54
  /** Get player's formatted link to open player in-game. */
55
55
  get shareLink(): string;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RankedClan = exports.RankedPlayer = exports.SeasonRankedPlayer = void 0;
4
4
  const Constants_1 = require("../util/Constants");
5
5
  const Badge_1 = require("./Badge");
6
- const League_1 = require("./League");
7
6
  const Location_1 = require("./Location");
8
7
  const PlayerClan_1 = require("./PlayerClan");
9
8
  /** Represents the Player of seasonal legend league leader-board ranking. */
@@ -44,7 +43,7 @@ class RankedPlayer {
44
43
  // @ts-expect-error
45
44
  this.clan = data.clan ? new PlayerClan_1.PlayerClan(client, data.clan) : null;
46
45
  // @ts-expect-error
47
- this.league = data.trophies ? new League_1.League(data.league ?? Constants_1.UnrankedLeagueData) : null; // eslint-disable-line
46
+ this.leagueTier = data.trophies ? new League(data.leagueTier ?? Constants_1.UnrankedLeagueData) : null; // eslint-disable-line
48
47
  }
49
48
  /** Get player's formatted link to open player in-game. */
50
49
  get shareLink() {
@@ -33,7 +33,9 @@ export declare class Util extends null {
33
33
  static formatDate(date: string): Date;
34
34
  /** Returns a string containing a query string suitable for use in a URL. */
35
35
  static queryString(options?: SearchOptions | ClanSearchOptions): string;
36
+ /** @deprecated Use getSeason instead */
36
37
  static getSeasonStart(inputDate: Date): Date;
38
+ /** @deprecated Use getSeason instead */
37
39
  static getSeasonEnd(inputDate: Date, forward?: boolean): Date;
38
40
  /** Get the current season ID. */
39
41
  static getSeasonId(): string;
@@ -45,6 +47,7 @@ export declare class Util extends null {
45
47
  static getSeason(timestamp?: Date, forward?: boolean): {
46
48
  endTime: Date;
47
49
  startTime: Date;
50
+ seasonId: string;
48
51
  };
49
52
  static allSettled<T>(values: Promise<T>[]): Promise<T[]>;
50
53
  static delay(ms: number): Promise<unknown>;
package/dist/util/Util.js CHANGED
@@ -95,6 +95,7 @@ class Util extends null {
95
95
  const query = new URLSearchParams(Object.entries(options).filter(([key]) => params.includes(key))).toString();
96
96
  return query.length ? `?${query}` : query;
97
97
  }
98
+ /** @deprecated Use getSeason instead */
98
99
  static getSeasonStart(inputDate) {
99
100
  const lastMonthLastDay = new Date(Date.UTC(inputDate.getUTCFullYear(), inputDate.getUTCMonth(), 0));
100
101
  const lastMonthLastMonday = new Date(lastMonthLastDay);
@@ -102,6 +103,7 @@ class Util extends null {
102
103
  lastMonthLastMonday.setUTCHours(5, 0, 0, 0);
103
104
  return lastMonthLastMonday;
104
105
  }
106
+ /** @deprecated Use getSeason instead */
105
107
  static getSeasonEnd(inputDate, forward = true) {
106
108
  const lastDayOfMonth = new Date(Date.UTC(inputDate.getUTCFullYear(), inputDate.getUTCMonth() + 1, 0));
107
109
  const lastMonday = new Date(lastDayOfMonth);
@@ -121,7 +123,7 @@ class Util extends null {
121
123
  }
122
124
  /** Get the current season ID. */
123
125
  static getSeasonId() {
124
- return this.getSeasonEnd(new Date()).toISOString().slice(0, 7);
126
+ return this.getSeason(new Date()).seasonId;
125
127
  }
126
128
  /**
127
129
  * Get the season start and end timestamp.
@@ -129,9 +131,34 @@ class Util extends null {
129
131
  * @param {boolean} forward - Whether to forward to the next month if the returned date is in the past relative to the given timestamp. Defaults to true.
130
132
  */
131
133
  static getSeason(timestamp, forward = true) {
132
- const endTime = this.getSeasonEnd(timestamp ?? new Date(), forward);
133
- const startTime = this.getSeasonStart(endTime);
134
- return { endTime, startTime };
134
+ const target = timestamp ?? new Date();
135
+ if (target < new Date('2025-08-25T05:00:00.000Z')) {
136
+ const endTime = this.getSeasonEnd(timestamp ?? new Date(), forward);
137
+ const startTime = this.getSeasonStart(endTime);
138
+ return { endTime, startTime, seasonId: endTime.toISOString().slice(0, 7) };
139
+ }
140
+ if (target > new Date('2025-08-25T05:00:00.000Z') && target <= new Date('2025-10-06T05:00:00.000Z')) {
141
+ return {
142
+ startTime: new Date('2025-08-25T05:00:00.000Z'),
143
+ endTime: new Date('2025-10-06T05:00:00.000Z'),
144
+ seasonId: '2025-09'
145
+ };
146
+ }
147
+ // After 6th October 2025, season ends every 4 weeks
148
+ const seasonDuration = 7 * 4 * 24 * 60 * 60 * 1000;
149
+ const referenceDate = new Date('2025-10-06T05:00:00.000Z');
150
+ const timeDifference = target.getTime() - referenceDate.getTime();
151
+ const seasonsPassed = Math.floor(timeDifference / seasonDuration);
152
+ const startTime = new Date(referenceDate.getTime() + seasonsPassed * seasonDuration);
153
+ const endTime = new Date(startTime.getTime() + seasonDuration);
154
+ // "month" increments by 1 each season starting from referenceDate's month
155
+ const refYear = referenceDate.getUTCFullYear();
156
+ const refMonthIndex = referenceDate.getUTCMonth(); // 0-based (Oct -> 9)
157
+ const totalMonths = refYear * 12 + refMonthIndex + seasonsPassed;
158
+ const year = Math.floor(totalMonths / 12);
159
+ const month = totalMonths - year * 12 + 1; // 1..12
160
+ const seasonId = `${year}-${String(month).padStart(2, '0')}`;
161
+ return { startTime, endTime, seasonId };
135
162
  }
136
163
  static async allSettled(values) {
137
164
  return (await Promise.allSettled(values))
package/dist/util.spec.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ process.env.TZ = 'UTC';
3
4
  const Util_1 = require("./util/Util");
4
5
  describe('util', () => {
5
6
  it('should always be UTC', () => {
@@ -31,10 +32,56 @@ describe('util', () => {
31
32
  });
32
33
  it('should forward to the next year at the end of the year', async () => {
33
34
  const timestamp = new Date('2024-12-30T05:01');
34
- const { endTime, startTime } = Util_1.Util.getSeason(timestamp);
35
- const expectedEndTime = new Date('2025-01-27T05:00').toISOString();
35
+ const { endTime, startTime, seasonId } = Util_1.Util.getSeason(timestamp);
36
36
  const expectedStartTime = new Date('2024-12-30T05:00').toISOString();
37
+ const expectedEndTime = new Date('2025-01-27T05:00').toISOString();
38
+ expect(endTime.toISOString()).toBe(expectedEndTime);
39
+ expect(startTime.toISOString()).toBe(expectedStartTime);
40
+ expect(seasonId).toBe('2025-01');
41
+ });
42
+ it('should pass October 2025', async () => {
43
+ const timestamp = new Date('2025-10-20T05:00');
44
+ const { endTime, startTime, seasonId } = Util_1.Util.getSeason(timestamp);
45
+ const expectedEndTime = new Date('2025-11-03T05:00').toISOString();
46
+ const expectedStartTime = new Date('2025-10-06T05:00').toISOString();
47
+ expect(endTime.toISOString()).toBe(expectedEndTime);
48
+ expect(startTime.toISOString()).toBe(expectedStartTime);
49
+ expect(seasonId).toBe('2025-10');
50
+ });
51
+ it('should pass November 2025', async () => {
52
+ const timestamp = new Date('2025-11-20T05:00');
53
+ const { endTime, startTime, seasonId } = Util_1.Util.getSeason(timestamp);
54
+ const expectedStartTime = new Date('2025-11-03T05:00').toISOString();
55
+ const expectedEndTime = new Date('2025-12-01T05:00').toISOString();
56
+ expect(startTime.toISOString()).toBe(expectedStartTime);
37
57
  expect(endTime.toISOString()).toBe(expectedEndTime);
58
+ expect(seasonId).toBe('2025-11');
59
+ });
60
+ it('should pass December 2025', async () => {
61
+ const timestamp = new Date('2025-12-01T05:00');
62
+ const { endTime, startTime, seasonId } = Util_1.Util.getSeason(timestamp);
63
+ const expectedStartTime = new Date('2025-12-01T05:00').toISOString();
64
+ const expectedEndTime = new Date('2025-12-29T05:00').toISOString();
65
+ expect(startTime.toISOString()).toBe(expectedStartTime);
66
+ expect(endTime.toISOString()).toBe(expectedEndTime);
67
+ expect(seasonId).toBe('2025-12');
68
+ });
69
+ it('should pass Jan 2026', async () => {
70
+ const timestamp = new Date('2026-01-01T05:00');
71
+ const { endTime, startTime, seasonId } = Util_1.Util.getSeason(timestamp);
72
+ const expectedStartTime = new Date('2025-12-29T05:00').toISOString();
73
+ const expectedEndTime = new Date('2026-01-26T05:00').toISOString();
38
74
  expect(startTime.toISOString()).toBe(expectedStartTime);
75
+ expect(endTime.toISOString()).toBe(expectedEndTime);
76
+ expect(seasonId).toBe('2026-01');
77
+ });
78
+ it('should pass Feb 2026', async () => {
79
+ const timestamp = new Date('2026-01-27T05:00');
80
+ const { endTime, startTime, seasonId } = Util_1.Util.getSeason(timestamp);
81
+ const expectedStartTime = new Date('2026-01-26T05:00').toISOString();
82
+ const expectedEndTime = new Date('2026-02-23T05:00').toISOString();
83
+ expect(startTime.toISOString()).toBe(expectedStartTime);
84
+ expect(endTime.toISOString()).toBe(expectedEndTime);
85
+ expect(seasonId).toBe('2026-02');
39
86
  });
40
87
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clashofclans.js",
3
- "version": "3.4.2-dev.559ce53",
3
+ "version": "3.5.0-dev.3cbb1a6",
4
4
  "description": "JavaScript library for interacting with the Clash of Clans API",
5
5
  "author": "https://clashofclans.js.org",
6
6
  "license": "MIT",