@mtcute/core 0.30.1 → 0.30.2

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.
Files changed (83) hide show
  1. package/highlevel/methods/files/download-iterable.cjs +80 -45
  2. package/highlevel/methods/files/download-iterable.js +80 -45
  3. package/highlevel/methods/files/normalize-input-media.cjs +1 -1
  4. package/highlevel/methods/files/normalize-input-media.js +1 -1
  5. package/highlevel/methods/files/upload-file.cjs +6 -1
  6. package/highlevel/methods/files/upload-file.js +6 -1
  7. package/highlevel/methods/messages/normalize-rich-message.cjs +12 -1
  8. package/highlevel/methods/messages/normalize-rich-message.js +12 -1
  9. package/highlevel/methods/messages/send-common.cjs +3 -2
  10. package/highlevel/methods/messages/send-common.d.cts +4 -1
  11. package/highlevel/methods/messages/send-common.d.ts +4 -1
  12. package/highlevel/methods/messages/send-common.js +3 -2
  13. package/highlevel/types/files/utils.d.cts +9 -0
  14. package/highlevel/types/files/utils.d.ts +9 -0
  15. package/highlevel/updates/manager.cjs +6 -169
  16. package/highlevel/updates/manager.js +6 -169
  17. package/highlevel/utils/index.d.cts +1 -0
  18. package/highlevel/utils/index.d.ts +1 -0
  19. package/highlevel/utils/walk-page-blocks.cjs +164 -0
  20. package/highlevel/utils/walk-page-blocks.d.cts +9 -0
  21. package/highlevel/utils/walk-page-blocks.d.ts +9 -0
  22. package/highlevel/utils/walk-page-blocks.js +159 -0
  23. package/network/authorization.cjs +1 -1
  24. package/network/authorization.js +1 -1
  25. package/network/delay-gate.cjs +29 -0
  26. package/network/delay-gate.d.cts +5 -0
  27. package/network/delay-gate.d.ts +5 -0
  28. package/network/delay-gate.js +24 -0
  29. package/network/delay-gate.test.d.cts +1 -0
  30. package/network/delay-gate.test.d.ts +1 -0
  31. package/network/message-id-store.cjs +30 -0
  32. package/network/message-id-store.d.cts +7 -0
  33. package/network/message-id-store.d.ts +7 -0
  34. package/network/message-id-store.js +25 -0
  35. package/network/message-id-store.test.d.cts +1 -0
  36. package/network/message-id-store.test.d.ts +1 -0
  37. package/network/middlewares/bundle.cjs +2 -0
  38. package/network/middlewares/bundle.d.cts +1 -0
  39. package/network/middlewares/bundle.d.ts +1 -0
  40. package/network/middlewares/bundle.js +2 -0
  41. package/network/middlewares/default.cjs +6 -1
  42. package/network/middlewares/default.js +6 -1
  43. package/network/middlewares/flood-waiter.test.d.cts +1 -0
  44. package/network/middlewares/flood-waiter.test.d.ts +1 -0
  45. package/network/middlewares/internal-errors.test.d.cts +1 -0
  46. package/network/middlewares/internal-errors.test.d.ts +1 -0
  47. package/network/middlewares/media-throttle.cjs +65 -0
  48. package/network/middlewares/media-throttle.d.cts +5 -0
  49. package/network/middlewares/media-throttle.d.ts +5 -0
  50. package/network/middlewares/media-throttle.js +60 -0
  51. package/network/middlewares/media-throttle.test.d.cts +1 -0
  52. package/network/middlewares/media-throttle.test.d.ts +1 -0
  53. package/network/middlewares/on-error.test.d.cts +1 -0
  54. package/network/middlewares/on-error.test.d.ts +1 -0
  55. package/network/middlewares/on-method.test.d.cts +1 -0
  56. package/network/middlewares/on-method.test.d.ts +1 -0
  57. package/network/mtproto-session.cjs +9 -2
  58. package/network/mtproto-session.d.cts +5 -2
  59. package/network/mtproto-session.d.ts +5 -2
  60. package/network/mtproto-session.js +9 -2
  61. package/network/multi-session-connection.cjs +7 -0
  62. package/network/multi-session-connection.d.cts +2 -0
  63. package/network/multi-session-connection.d.ts +2 -0
  64. package/network/multi-session-connection.js +7 -0
  65. package/network/network-manager.cjs +7 -1
  66. package/network/network-manager.js +7 -1
  67. package/network/resource-limiter.cjs +60 -0
  68. package/network/resource-limiter.d.cts +11 -0
  69. package/network/resource-limiter.d.ts +11 -0
  70. package/network/resource-limiter.js +55 -0
  71. package/network/resource-limiter.test.d.cts +1 -0
  72. package/network/resource-limiter.test.d.ts +1 -0
  73. package/network/server-salt.cjs +7 -3
  74. package/network/server-salt.d.cts +2 -0
  75. package/network/server-salt.d.ts +2 -0
  76. package/network/server-salt.js +7 -3
  77. package/network/session-connection.cjs +106 -20
  78. package/network/session-connection.d.cts +11 -0
  79. package/network/session-connection.d.ts +11 -0
  80. package/network/session-connection.js +106 -20
  81. package/package.json +1 -1
  82. package/utils.cjs +2 -0
  83. package/utils.js +2 -0
@@ -5,6 +5,7 @@ import { ICryptoProvider, Logger, LongMap, SortedArray } from '../utils/index.js
5
5
  import { ServerSaltManager } from './server-salt.js';
6
6
  import { default as Long } from 'long';
7
7
  import { AuthKey } from './auth-key.js';
8
+ import { MessageIdStore } from './message-id-store.js';
8
9
  export interface PendingRpc {
9
10
  method: string;
10
11
  data: Uint8Array;
@@ -76,7 +77,7 @@ export declare class MtprotoSession {
76
77
  _lastMessageId: Long;
77
78
  _seqNo: number;
78
79
  recentOutgoingMsgIds: LruSet<Long>;
79
- recentIncomingMsgIds: LruSet<Long>;
80
+ recentIncomingMsgIds: MessageIdStore;
80
81
  recentStateRequests: LruMap<Long, Long[]>;
81
82
  queuedRpc: Deque<PendingRpc>;
82
83
  queuedAcks: Long[];
@@ -91,6 +92,7 @@ export declare class MtprotoSession {
91
92
  lastPingRtt: number;
92
93
  lastPingTime: number;
93
94
  lastPingMsgId: Long;
95
+ lastActivityTime: number;
94
96
  lastSessionCreatedUid: Long;
95
97
  initConnectionCalled: boolean;
96
98
  authorizationPending: boolean;
@@ -101,7 +103,8 @@ export declare class MtprotoSession {
101
103
  */
102
104
  reset(withAuthKey?: boolean): void;
103
105
  resetAuthKey(): void;
104
- updateTimeOffset(offset: number): void;
106
+ updateTimeOffset(offset: number, force?: boolean): void;
107
+ getServerTime(): number;
105
108
  /**
106
109
  * Reset session state and generate a new session ID.
107
110
  *
@@ -5,6 +5,7 @@ import { ICryptoProvider, Logger, LongMap, SortedArray } from '../utils/index.js
5
5
  import { ServerSaltManager } from './server-salt.js';
6
6
  import { default as Long } from 'long';
7
7
  import { AuthKey } from './auth-key.js';
8
+ import { MessageIdStore } from './message-id-store.js';
8
9
  export interface PendingRpc {
9
10
  method: string;
10
11
  data: Uint8Array;
@@ -76,7 +77,7 @@ export declare class MtprotoSession {
76
77
  _lastMessageId: Long;
77
78
  _seqNo: number;
78
79
  recentOutgoingMsgIds: LruSet<Long>;
79
- recentIncomingMsgIds: LruSet<Long>;
80
+ recentIncomingMsgIds: MessageIdStore;
80
81
  recentStateRequests: LruMap<Long, Long[]>;
81
82
  queuedRpc: Deque<PendingRpc>;
82
83
  queuedAcks: Long[];
@@ -91,6 +92,7 @@ export declare class MtprotoSession {
91
92
  lastPingRtt: number;
92
93
  lastPingTime: number;
93
94
  lastPingMsgId: Long;
95
+ lastActivityTime: number;
94
96
  lastSessionCreatedUid: Long;
95
97
  initConnectionCalled: boolean;
96
98
  authorizationPending: boolean;
@@ -101,7 +103,8 @@ export declare class MtprotoSession {
101
103
  */
102
104
  reset(withAuthKey?: boolean): void;
103
105
  resetAuthKey(): void;
104
- updateTimeOffset(offset: number): void;
106
+ updateTimeOffset(offset: number, force?: boolean): void;
107
+ getServerTime(): number;
105
108
  /**
106
109
  * Reset session state and generate a new session ID.
107
110
  *
@@ -5,6 +5,7 @@ import { randomLong, LongSet, LongMap, compareLongs } from "../utils/long-utils.
5
5
  import { getRandomInt } from "../utils/misc-utils.js";
6
6
  import { SortedArray } from "../utils/sorted-array.js";
7
7
  import { AuthKey } from "./auth-key.js";
8
+ import { MessageIdStore } from "./message-id-store.js";
8
9
  import { MtcuteError } from "../types/errors.js";
9
10
  class MtprotoSession {
10
11
  constructor(_crypto, log, _readerMap, _writerMap, _salts) {
@@ -14,6 +15,7 @@ class MtprotoSession {
14
15
  this._writerMap = _writerMap;
15
16
  this._salts = _salts;
16
17
  this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `;
18
+ this._salts.setTimeSource(this.getServerTime.bind(this));
17
19
  this._authKey = new AuthKey(_crypto, log, _readerMap);
18
20
  this._authKeyTemp = new AuthKey(_crypto, log, _readerMap);
19
21
  this._authKeyTempSecondary = new AuthKey(_crypto, log, _readerMap);
@@ -28,7 +30,7 @@ class MtprotoSession {
28
30
  /// state ///
29
31
  // recent msg ids
30
32
  recentOutgoingMsgIds = new LruSet(1e3, LongSet);
31
- recentIncomingMsgIds = new LruSet(1e3, LongSet);
33
+ recentIncomingMsgIds = new MessageIdStore();
32
34
  // <deno-tsignore>
33
35
  recentStateRequests = new LruMap(1e3, LongMap);
34
36
  // queues
@@ -51,6 +53,7 @@ class MtprotoSession {
51
53
  lastPingRtt = Number.NaN;
52
54
  lastPingTime = 0;
53
55
  lastPingMsgId = Long.ZERO;
56
+ lastActivityTime = 0;
54
57
  lastSessionCreatedUid = Long.ZERO;
55
58
  initConnectionCalled = false;
56
59
  authorizationPending = false;
@@ -73,11 +76,15 @@ class MtprotoSession {
73
76
  this._authKeyTemp.reset();
74
77
  this._authKeyTempSecondary.reset();
75
78
  }
76
- updateTimeOffset(offset) {
79
+ updateTimeOffset(offset, force = false) {
80
+ if (!force && offset <= this._timeOffset) return;
77
81
  this.log.debug("time offset updated: %d", offset);
78
82
  this._timeOffset = offset;
79
83
  this._lastMessageId = Long.ZERO;
80
84
  }
85
+ getServerTime() {
86
+ return Math.floor(performance.now() / 1e3) + this._timeOffset;
87
+ }
81
88
  /**
82
89
  * Reset session state and generate a new session ID.
83
90
  *
@@ -160,6 +160,13 @@ class MultiSessionConnection {
160
160
  if (this._connections[0].isConnected) return;
161
161
  this.connect();
162
162
  }
163
+ get isConnected() {
164
+ return this._connections.some((conn) => conn.isConnected);
165
+ }
166
+ destroyAuthKey() {
167
+ const conn = this._connections.find((c) => c.isConnected) ?? this._connections[0];
168
+ conn?.destroyAuthKey();
169
+ }
163
170
  _authKey = null;
164
171
  setAuthKey(authKey) {
165
172
  this._authKey = authKey;
@@ -29,6 +29,8 @@ export declare class MultiSessionConnection {
29
29
  sendRpc<T extends tl.RpcMethod>(request: T, timeout?: number, abortSignal?: AbortSignal, chainId?: string | number): Promise<tl.RpcCallReturn[T['_']] | mtp.RawMt_rpc_error>;
30
30
  connect(): void;
31
31
  ensureConnected(): void;
32
+ get isConnected(): boolean;
33
+ destroyAuthKey(): void;
32
34
  private _authKey;
33
35
  setAuthKey(authKey: Uint8Array | null): void;
34
36
  setTempAuthKey(authKey: Uint8Array | null, idx: number): void;
@@ -29,6 +29,8 @@ export declare class MultiSessionConnection {
29
29
  sendRpc<T extends tl.RpcMethod>(request: T, timeout?: number, abortSignal?: AbortSignal, chainId?: string | number): Promise<tl.RpcCallReturn[T['_']] | mtp.RawMt_rpc_error>;
30
30
  connect(): void;
31
31
  ensureConnected(): void;
32
+ get isConnected(): boolean;
33
+ destroyAuthKey(): void;
32
34
  private _authKey;
33
35
  setAuthKey(authKey: Uint8Array | null): void;
34
36
  setTempAuthKey(authKey: Uint8Array | null, idx: number): void;
@@ -153,6 +153,13 @@ class MultiSessionConnection {
153
153
  if (this._connections[0].isConnected) return;
154
154
  this.connect();
155
155
  }
156
+ get isConnected() {
157
+ return this._connections.some((conn) => conn.isConnected);
158
+ }
159
+ destroyAuthKey() {
160
+ const conn = this._connections.find((c) => c.isConnected) ?? this._connections[0];
161
+ conn?.destroyAuthKey();
162
+ }
156
163
  _authKey = null;
157
164
  setAuthKey(authKey) {
158
165
  this._authKey = authKey;
@@ -227,7 +227,7 @@ class NetworkManager {
227
227
  _: "initConnection",
228
228
  deviceModel,
229
229
  systemVersion: "1.0",
230
- appVersion: "0.30.1",
230
+ appVersion: "0.30.2",
231
231
  systemLangCode: "en",
232
232
  langPack: "",
233
233
  // "langPacks are for official apps only"
@@ -415,6 +415,12 @@ class NetworkManager {
415
415
  return user;
416
416
  }
417
417
  notifyLoggedOut() {
418
+ const primaryDcId = this._primaryDc?.dcId;
419
+ for (const dc of this._dcConnections.values()) {
420
+ if (dc.dcId === primaryDcId) continue;
421
+ const pool = [dc.main, dc.download, dc.upload, dc.downloadSmall].find((p) => p.isConnected);
422
+ pool?.destroyAuthKey();
423
+ }
418
424
  this._businessConnectionDcs.clear();
419
425
  this.setIsPremium(false);
420
426
  this.resetSessions();
@@ -220,7 +220,7 @@ class NetworkManager {
220
220
  _: "initConnection",
221
221
  deviceModel,
222
222
  systemVersion: "1.0",
223
- appVersion: "0.30.1",
223
+ appVersion: "0.30.2",
224
224
  systemLangCode: "en",
225
225
  langPack: "",
226
226
  // "langPacks are for official apps only"
@@ -408,6 +408,12 @@ class NetworkManager {
408
408
  return user;
409
409
  }
410
410
  notifyLoggedOut() {
411
+ const primaryDcId = this._primaryDc?.dcId;
412
+ for (const dc of this._dcConnections.values()) {
413
+ if (dc.dcId === primaryDcId) continue;
414
+ const pool = [dc.main, dc.download, dc.upload, dc.downloadSmall].find((p) => p.isConnected);
415
+ pool?.destroyAuthKey();
416
+ }
411
417
  this._businessConnectionDcs.clear();
412
418
  this.setIsPremium(false);
413
419
  this.resetSessions();
@@ -0,0 +1,60 @@
1
+ if (typeof globalThis !== "undefined" && !globalThis._MTCUTE_CJS_DEPRECATION_WARNED) {
2
+ globalThis._MTCUTE_CJS_DEPRECATION_WARNED = true;
3
+ console.warn("[@mtcute/core] CommonJS bundles are deprecated. They will be removed completely in one of the upcoming releases. No support is provided for CommonJS users. Please consider switching to ESM, it's " + (/* @__PURE__ */ new Date()).getFullYear() + " already.");
4
+ console.warn("[@mtcute/core] Learn more about switching to ESM: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c");
5
+ }
6
+ "use strict";
7
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
8
+ const utils = require("@fuman/utils");
9
+ class ResourceLimiter {
10
+ constructor(max) {
11
+ this.max = max;
12
+ this._available = max;
13
+ }
14
+ _available;
15
+ _waiters = [];
16
+ setMax(max) {
17
+ this._available += max - this.max;
18
+ this.max = max;
19
+ this._pump();
20
+ }
21
+ tryAcquire(bytes) {
22
+ if (bytes > this.max) bytes = this.max;
23
+ if (!this._waiters.length && this._available >= bytes) {
24
+ this._available -= bytes;
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ acquire(bytes, signal) {
30
+ if (this.tryAcquire(bytes)) return Promise.resolve();
31
+ if (bytes > this.max) bytes = this.max;
32
+ const deferred = new utils.Deferred();
33
+ const waiter = { need: bytes, deferred };
34
+ this._waiters.push(waiter);
35
+ if (signal) {
36
+ const onAbort = () => {
37
+ const idx = this._waiters.indexOf(waiter);
38
+ if (idx >= 0) this._waiters.splice(idx, 1);
39
+ deferred.reject(signal.reason);
40
+ };
41
+ signal.addEventListener("abort", onAbort, { once: true });
42
+ const removeListener = signal.removeEventListener.bind(signal, "abort", onAbort);
43
+ deferred.promise.then(removeListener, removeListener);
44
+ }
45
+ return deferred.promise;
46
+ }
47
+ release(bytes) {
48
+ if (bytes > this.max) bytes = this.max;
49
+ this._available += bytes;
50
+ this._pump();
51
+ }
52
+ _pump() {
53
+ while (this._waiters.length && this._waiters[0].need <= this._available) {
54
+ const waiter = this._waiters.shift();
55
+ this._available -= waiter.need;
56
+ waiter.deferred.resolve();
57
+ }
58
+ }
59
+ }
60
+ exports.ResourceLimiter = ResourceLimiter;
@@ -0,0 +1,11 @@
1
+ export declare class ResourceLimiter {
2
+ max: number;
3
+ private _available;
4
+ private _waiters;
5
+ constructor(max: number);
6
+ setMax(max: number): void;
7
+ tryAcquire(bytes: number): boolean;
8
+ acquire(bytes: number, signal?: AbortSignal): Promise<void>;
9
+ release(bytes: number): void;
10
+ private _pump;
11
+ }
@@ -0,0 +1,11 @@
1
+ export declare class ResourceLimiter {
2
+ max: number;
3
+ private _available;
4
+ private _waiters;
5
+ constructor(max: number);
6
+ setMax(max: number): void;
7
+ tryAcquire(bytes: number): boolean;
8
+ acquire(bytes: number, signal?: AbortSignal): Promise<void>;
9
+ release(bytes: number): void;
10
+ private _pump;
11
+ }
@@ -0,0 +1,55 @@
1
+ import { Deferred } from "@fuman/utils";
2
+ class ResourceLimiter {
3
+ constructor(max) {
4
+ this.max = max;
5
+ this._available = max;
6
+ }
7
+ _available;
8
+ _waiters = [];
9
+ setMax(max) {
10
+ this._available += max - this.max;
11
+ this.max = max;
12
+ this._pump();
13
+ }
14
+ tryAcquire(bytes) {
15
+ if (bytes > this.max) bytes = this.max;
16
+ if (!this._waiters.length && this._available >= bytes) {
17
+ this._available -= bytes;
18
+ return true;
19
+ }
20
+ return false;
21
+ }
22
+ acquire(bytes, signal) {
23
+ if (this.tryAcquire(bytes)) return Promise.resolve();
24
+ if (bytes > this.max) bytes = this.max;
25
+ const deferred = new Deferred();
26
+ const waiter = { need: bytes, deferred };
27
+ this._waiters.push(waiter);
28
+ if (signal) {
29
+ const onAbort = () => {
30
+ const idx = this._waiters.indexOf(waiter);
31
+ if (idx >= 0) this._waiters.splice(idx, 1);
32
+ deferred.reject(signal.reason);
33
+ };
34
+ signal.addEventListener("abort", onAbort, { once: true });
35
+ const removeListener = signal.removeEventListener.bind(signal, "abort", onAbort);
36
+ deferred.promise.then(removeListener, removeListener);
37
+ }
38
+ return deferred.promise;
39
+ }
40
+ release(bytes) {
41
+ if (bytes > this.max) bytes = this.max;
42
+ this._available += bytes;
43
+ this._pump();
44
+ }
45
+ _pump() {
46
+ while (this._waiters.length && this._waiters[0].need <= this._available) {
47
+ const waiter = this._waiters.shift();
48
+ this._available -= waiter.need;
49
+ waiter.deferred.resolve();
50
+ }
51
+ }
52
+ }
53
+ export {
54
+ ResourceLimiter
55
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -11,12 +11,16 @@ class ServerSaltManager {
11
11
  _futureSalts = [];
12
12
  currentSalt = Long.ZERO;
13
13
  isFetching = false;
14
+ _getServerTime = () => Date.now() / 1e3;
15
+ setTimeSource(fn) {
16
+ this._getServerTime = fn;
17
+ }
14
18
  shouldFetchSalts() {
15
19
  return !this.isFetching && !this.currentSalt.isZero() && this._futureSalts.length < 2;
16
20
  }
17
21
  setFutureSalts(salts) {
18
22
  this._futureSalts = salts;
19
- const now = Date.now() / 1e3;
23
+ const now = this._getServerTime();
20
24
  while (salts.length > 0 && salts[0].validSince <= now) {
21
25
  this.currentSalt = salts[0].salt;
22
26
  this._futureSalts.shift();
@@ -30,11 +34,11 @@ class ServerSaltManager {
30
34
  this._timer = utils.timers.setTimeout(() => {
31
35
  this.currentSalt = salt.salt;
32
36
  this._replaceAndScheduleNext();
33
- }, salt.validSince * 1e3 - Date.now());
37
+ }, (salt.validSince - this._getServerTime()) * 1e3);
34
38
  }
35
39
  _replaceAndScheduleNext() {
36
40
  if (this._timer) utils.timers.clearTimeout(this._timer);
37
- const now = Date.now() / 1e3;
41
+ const now = this._getServerTime();
38
42
  while (this._futureSalts.length !== 0) {
39
43
  const salt = this._futureSalts[0];
40
44
  if (salt.validSince > now) break;
@@ -4,6 +4,8 @@ export declare class ServerSaltManager {
4
4
  private _futureSalts;
5
5
  currentSalt: Long;
6
6
  isFetching: boolean;
7
+ private _getServerTime;
8
+ setTimeSource(fn: () => number): void;
7
9
  shouldFetchSalts(): boolean;
8
10
  setFutureSalts(salts: mtp.RawMt_future_salt[]): void;
9
11
  private _timer?;
@@ -4,6 +4,8 @@ export declare class ServerSaltManager {
4
4
  private _futureSalts;
5
5
  currentSalt: Long;
6
6
  isFetching: boolean;
7
+ private _getServerTime;
8
+ setTimeSource(fn: () => number): void;
7
9
  shouldFetchSalts(): boolean;
8
10
  setFutureSalts(salts: mtp.RawMt_future_salt[]): void;
9
11
  private _timer?;
@@ -4,12 +4,16 @@ class ServerSaltManager {
4
4
  _futureSalts = [];
5
5
  currentSalt = Long.ZERO;
6
6
  isFetching = false;
7
+ _getServerTime = () => Date.now() / 1e3;
8
+ setTimeSource(fn) {
9
+ this._getServerTime = fn;
10
+ }
7
11
  shouldFetchSalts() {
8
12
  return !this.isFetching && !this.currentSalt.isZero() && this._futureSalts.length < 2;
9
13
  }
10
14
  setFutureSalts(salts) {
11
15
  this._futureSalts = salts;
12
- const now = Date.now() / 1e3;
16
+ const now = this._getServerTime();
13
17
  while (salts.length > 0 && salts[0].validSince <= now) {
14
18
  this.currentSalt = salts[0].salt;
15
19
  this._futureSalts.shift();
@@ -23,11 +27,11 @@ class ServerSaltManager {
23
27
  this._timer = timers.setTimeout(() => {
24
28
  this.currentSalt = salt.salt;
25
29
  this._replaceAndScheduleNext();
26
- }, salt.validSince * 1e3 - Date.now());
30
+ }, (salt.validSince - this._getServerTime()) * 1e3);
27
31
  }
28
32
  _replaceAndScheduleNext() {
29
33
  if (this._timer) timers.clearTimeout(this._timer);
30
- const now = Date.now() / 1e3;
34
+ const now = this._getServerTime();
31
35
  while (this._futureSalts.length !== 0) {
32
36
  const salt = this._futureSalts[0];
33
37
  if (salt.validSince > now) break;