@mtcute/core 0.22.3 → 0.23.1
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/client.cjs +1 -1
- package/client.js +1 -1
- package/highlevel/base.cjs +1 -0
- package/highlevel/base.js +1 -0
- package/highlevel/client.d.cts +7 -3
- package/highlevel/client.d.ts +7 -3
- package/highlevel/methods/auth/send-code.cjs +8 -2
- package/highlevel/methods/auth/send-code.d.cts +4 -2
- package/highlevel/methods/auth/send-code.d.ts +4 -2
- package/highlevel/methods/auth/send-code.js +8 -2
- package/highlevel/methods/auth/start.cjs +6 -1
- package/highlevel/methods/auth/start.d.cts +1 -1
- package/highlevel/methods/auth/start.d.ts +1 -1
- package/highlevel/methods/auth/start.js +6 -1
- package/highlevel/methods/chats/open-chat.cjs +1 -1
- package/highlevel/methods/chats/open-chat.js +1 -1
- package/highlevel/methods/dialogs/find-dialogs.cjs +3 -1
- package/highlevel/methods/dialogs/find-dialogs.js +3 -1
- package/highlevel/methods/dialogs/get-peer-dialogs.cjs +49 -11
- package/highlevel/methods/dialogs/get-peer-dialogs.d.cts +1 -1
- package/highlevel/methods/dialogs/get-peer-dialogs.d.ts +1 -1
- package/highlevel/methods/dialogs/get-peer-dialogs.js +49 -11
- package/highlevel/methods/files/normalize-input-file.d.cts +1 -0
- package/highlevel/methods/files/normalize-input-file.d.ts +1 -0
- package/highlevel/methods/files/normalize-input-media.cjs +13 -6
- package/highlevel/methods/files/normalize-input-media.d.cts +1 -0
- package/highlevel/methods/files/normalize-input-media.d.ts +1 -0
- package/highlevel/methods/files/normalize-input-media.js +13 -6
- package/highlevel/methods/files/upload-file.cjs +6 -3
- package/highlevel/methods/files/upload-file.d.cts +1 -0
- package/highlevel/methods/files/upload-file.d.ts +1 -0
- package/highlevel/methods/files/upload-file.js +6 -3
- package/highlevel/methods/messages/send-common.d.cts +1 -0
- package/highlevel/methods/messages/send-common.d.ts +1 -0
- package/highlevel/methods/messages/send-media-group.cjs +3 -2
- package/highlevel/methods/messages/send-media-group.js +3 -2
- package/highlevel/methods/messages/send-media.cjs +3 -2
- package/highlevel/methods/messages/send-media.js +3 -2
- package/highlevel/methods/messages/send-text.cjs +1 -1
- package/highlevel/methods/messages/send-text.js +1 -1
- package/highlevel/methods/users/resolve-peer-many.cjs +8 -43
- package/highlevel/methods/users/resolve-peer-many.js +9 -44
- package/highlevel/storage/service/peers.cjs +37 -9
- package/highlevel/storage/service/peers.d.cts +4 -0
- package/highlevel/storage/service/peers.d.ts +4 -0
- package/highlevel/storage/service/peers.js +38 -10
- package/highlevel/storage/storage.cjs +3 -0
- package/highlevel/storage/storage.d.cts +1 -0
- package/highlevel/storage/storage.d.ts +1 -0
- package/highlevel/storage/storage.js +3 -0
- package/highlevel/types/conversation.cjs +3 -4
- package/highlevel/types/conversation.js +3 -4
- package/highlevel/types/messages/message-action.cjs +11 -0
- package/highlevel/types/messages/message-action.d.cts +15 -1
- package/highlevel/types/messages/message-action.d.ts +15 -1
- package/highlevel/types/messages/message-action.js +11 -0
- package/highlevel/types/peers/full-user.cjs +8 -0
- package/highlevel/types/peers/full-user.d.cts +4 -0
- package/highlevel/types/peers/full-user.d.ts +4 -0
- package/highlevel/types/peers/full-user.js +8 -0
- package/highlevel/types/peers/peers-index.cjs +10 -0
- package/highlevel/types/peers/peers-index.d.cts +1 -0
- package/highlevel/types/peers/peers-index.d.ts +1 -0
- package/highlevel/types/peers/peers-index.js +10 -0
- package/highlevel/types/premium/business-connection.cjs +3 -3
- package/highlevel/types/premium/business-connection.d.cts +2 -2
- package/highlevel/types/premium/business-connection.d.ts +2 -2
- package/highlevel/types/premium/business-connection.js +3 -3
- package/highlevel/types/premium/saved-star-gift.cjs +2 -2
- package/highlevel/types/premium/saved-star-gift.d.cts +2 -2
- package/highlevel/types/premium/saved-star-gift.d.ts +2 -2
- package/highlevel/types/premium/saved-star-gift.js +2 -2
- package/highlevel/types/premium/stars-gift-unique.cjs +35 -5
- package/highlevel/types/premium/stars-gift-unique.d.cts +23 -3
- package/highlevel/types/premium/stars-gift-unique.d.ts +23 -3
- package/highlevel/types/premium/stars-gift-unique.js +35 -5
- package/highlevel/types/premium/stars-transaction.cjs +4 -0
- package/highlevel/types/premium/stars-transaction.d.cts +2 -0
- package/highlevel/types/premium/stars-transaction.d.ts +2 -0
- package/highlevel/types/premium/stars-transaction.js +4 -0
- package/highlevel/updates/manager.cjs +4 -4
- package/highlevel/updates/manager.js +4 -4
- package/highlevel/worker/storage.cjs +4 -0
- package/highlevel/worker/storage.d.cts +2 -0
- package/highlevel/worker/storage.d.ts +2 -0
- package/highlevel/worker/storage.js +4 -0
- package/network/authorization.cjs +1 -1
- package/network/authorization.js +1 -1
- package/network/middlewares/flood-waiter.cjs +20 -4
- package/network/middlewares/flood-waiter.d.cts +9 -2
- package/network/middlewares/flood-waiter.d.ts +9 -2
- package/network/middlewares/flood-waiter.js +20 -4
- package/network/mtproto-session.cjs +3 -4
- package/network/mtproto-session.d.cts +1 -1
- package/network/mtproto-session.d.ts +1 -1
- package/network/mtproto-session.js +3 -4
- package/network/network-manager.cjs +3 -3
- package/network/network-manager.d.cts +1 -1
- package/network/network-manager.d.ts +1 -1
- package/network/network-manager.js +3 -3
- package/network/persistent-connection.cjs +1 -0
- package/network/persistent-connection.js +1 -0
- package/network/session-connection.cjs +7 -5
- package/network/session-connection.js +7 -5
- package/package.json +7 -7
- package/utils/binary/compat.cjs +2 -0
- package/utils/binary/compat.js +2 -0
- package/utils/early-timer.cjs +12 -7
- package/utils/early-timer.d.cts +3 -3
- package/utils/early-timer.d.ts +3 -3
- package/utils/early-timer.js +12 -7
|
@@ -1218,7 +1218,7 @@ class UpdatesManager {
|
|
|
1218
1218
|
pending.ptsBefore,
|
|
1219
1219
|
diff
|
|
1220
1220
|
);
|
|
1221
|
-
pending.timeout =
|
|
1221
|
+
pending.timeout = performance.now() + 500;
|
|
1222
1222
|
pendingPtsUpdatesPostponed.add(pending);
|
|
1223
1223
|
postponedTimer.emitBefore(pending.timeout);
|
|
1224
1224
|
} else if (diff > -1e6) {
|
|
@@ -1287,7 +1287,7 @@ class UpdatesManager {
|
|
|
1287
1287
|
continue;
|
|
1288
1288
|
}
|
|
1289
1289
|
if (localPts < pending.ptsBefore) {
|
|
1290
|
-
const now =
|
|
1290
|
+
const now = performance.now();
|
|
1291
1291
|
if (now < pending.timeout) {
|
|
1292
1292
|
log.debug(
|
|
1293
1293
|
"postponed %s (cid = %d) is still waiting (%dms left) (current pts %d, need %d)",
|
|
@@ -1341,7 +1341,7 @@ class UpdatesManager {
|
|
|
1341
1341
|
pending.qtsBefore,
|
|
1342
1342
|
diff
|
|
1343
1343
|
);
|
|
1344
|
-
pending.timeout =
|
|
1344
|
+
pending.timeout = performance.now() + 500;
|
|
1345
1345
|
pendingQtsUpdatesPostponed.add(pending);
|
|
1346
1346
|
postponedTimer.emitBefore(pending.timeout);
|
|
1347
1347
|
} else {
|
|
@@ -1375,7 +1375,7 @@ class UpdatesManager {
|
|
|
1375
1375
|
continue;
|
|
1376
1376
|
}
|
|
1377
1377
|
if (this.qts < pending.qtsBefore) {
|
|
1378
|
-
const now =
|
|
1378
|
+
const now = performance.now();
|
|
1379
1379
|
if (now < pending.timeout) {
|
|
1380
1380
|
log.debug(
|
|
1381
1381
|
"postponed %s is still waiting (%dms left) (current qts %d, need %d)",
|
|
@@ -55,6 +55,7 @@ class PeersServiceProxy {
|
|
|
55
55
|
this.getByUsername = bind("getByUsername");
|
|
56
56
|
this.getCompleteById = bind("getCompleteById");
|
|
57
57
|
this.getMinAccessHash = bind("getMinAccessHash");
|
|
58
|
+
this.close = bind("close");
|
|
58
59
|
}
|
|
59
60
|
updatePeersFrom;
|
|
60
61
|
store;
|
|
@@ -63,6 +64,7 @@ class PeersServiceProxy {
|
|
|
63
64
|
getByUsername;
|
|
64
65
|
getCompleteById;
|
|
65
66
|
getMinAccessHash;
|
|
67
|
+
close;
|
|
66
68
|
}
|
|
67
69
|
class TelegramStorageProxy {
|
|
68
70
|
constructor(_invoker) {
|
|
@@ -71,10 +73,12 @@ class TelegramStorageProxy {
|
|
|
71
73
|
this.self = new CurrentUserServiceProxy(this._invoker);
|
|
72
74
|
this.peers = new PeersServiceProxy(this._invoker);
|
|
73
75
|
this.clear = bind("clear");
|
|
76
|
+
this.close = bind("close");
|
|
74
77
|
}
|
|
75
78
|
self;
|
|
76
79
|
peers;
|
|
77
80
|
clear;
|
|
81
|
+
close;
|
|
78
82
|
// todo - remove once we move these to updates manager
|
|
79
83
|
updates = null;
|
|
80
84
|
refMsgs = null;
|
|
@@ -26,6 +26,7 @@ declare class PeersServiceProxy implements PublicPart<PeersService> {
|
|
|
26
26
|
readonly getByUsername: PeersService['getByUsername'];
|
|
27
27
|
readonly getCompleteById: PeersService['getCompleteById'];
|
|
28
28
|
readonly getMinAccessHash: PeersService['getMinAccessHash'];
|
|
29
|
+
readonly close: PeersService['close'];
|
|
29
30
|
constructor(_invoker: WorkerInvoker);
|
|
30
31
|
}
|
|
31
32
|
export declare class TelegramStorageProxy implements PublicPart<TelegramStorageManager> {
|
|
@@ -33,6 +34,7 @@ export declare class TelegramStorageProxy implements PublicPart<TelegramStorageM
|
|
|
33
34
|
readonly self: CurrentUserServiceProxy;
|
|
34
35
|
readonly peers: PeersServiceProxy;
|
|
35
36
|
readonly clear: TelegramStorageManager['clear'];
|
|
37
|
+
readonly close: TelegramStorageManager['close'];
|
|
36
38
|
constructor(_invoker: WorkerInvoker);
|
|
37
39
|
readonly updates: never;
|
|
38
40
|
readonly refMsgs: never;
|
|
@@ -26,6 +26,7 @@ declare class PeersServiceProxy implements PublicPart<PeersService> {
|
|
|
26
26
|
readonly getByUsername: PeersService['getByUsername'];
|
|
27
27
|
readonly getCompleteById: PeersService['getCompleteById'];
|
|
28
28
|
readonly getMinAccessHash: PeersService['getMinAccessHash'];
|
|
29
|
+
readonly close: PeersService['close'];
|
|
29
30
|
constructor(_invoker: WorkerInvoker);
|
|
30
31
|
}
|
|
31
32
|
export declare class TelegramStorageProxy implements PublicPart<TelegramStorageManager> {
|
|
@@ -33,6 +34,7 @@ export declare class TelegramStorageProxy implements PublicPart<TelegramStorageM
|
|
|
33
34
|
readonly self: CurrentUserServiceProxy;
|
|
34
35
|
readonly peers: PeersServiceProxy;
|
|
35
36
|
readonly clear: TelegramStorageManager['clear'];
|
|
37
|
+
readonly close: TelegramStorageManager['close'];
|
|
36
38
|
constructor(_invoker: WorkerInvoker);
|
|
37
39
|
readonly updates: never;
|
|
38
40
|
readonly refMsgs: never;
|
|
@@ -48,6 +48,7 @@ class PeersServiceProxy {
|
|
|
48
48
|
this.getByUsername = bind("getByUsername");
|
|
49
49
|
this.getCompleteById = bind("getCompleteById");
|
|
50
50
|
this.getMinAccessHash = bind("getMinAccessHash");
|
|
51
|
+
this.close = bind("close");
|
|
51
52
|
}
|
|
52
53
|
updatePeersFrom;
|
|
53
54
|
store;
|
|
@@ -56,6 +57,7 @@ class PeersServiceProxy {
|
|
|
56
57
|
getByUsername;
|
|
57
58
|
getCompleteById;
|
|
58
59
|
getMinAccessHash;
|
|
60
|
+
close;
|
|
59
61
|
}
|
|
60
62
|
class TelegramStorageProxy {
|
|
61
63
|
constructor(_invoker) {
|
|
@@ -64,10 +66,12 @@ class TelegramStorageProxy {
|
|
|
64
66
|
this.self = new CurrentUserServiceProxy(this._invoker);
|
|
65
67
|
this.peers = new PeersServiceProxy(this._invoker);
|
|
66
68
|
this.clear = bind("clear");
|
|
69
|
+
this.close = bind("close");
|
|
67
70
|
}
|
|
68
71
|
self;
|
|
69
72
|
peers;
|
|
70
73
|
clear;
|
|
74
|
+
close;
|
|
71
75
|
// todo - remove once we move these to updates manager
|
|
72
76
|
updates = null;
|
|
73
77
|
refMsgs = null;
|
|
@@ -239,7 +239,7 @@ async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
239
239
|
throw new Error("Step 3: invalid server nonce from server");
|
|
240
240
|
}
|
|
241
241
|
const dhPrime = utils.bigint.fromBytes(serverDhInner.dhPrime);
|
|
242
|
-
const timeOffset = Math.floor(
|
|
242
|
+
const timeOffset = serverDhInner.serverTime - Math.floor(performance.now() / 1e3);
|
|
243
243
|
session.updateTimeOffset(timeOffset);
|
|
244
244
|
const g = BigInt(serverDhInner.g);
|
|
245
245
|
const gA = utils.bigint.fromBytes(serverDhInner.gA);
|
package/network/authorization.js
CHANGED
|
@@ -232,7 +232,7 @@ async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
232
232
|
throw new Error("Step 3: invalid server nonce from server");
|
|
233
233
|
}
|
|
234
234
|
const dhPrime = bigint.fromBytes(serverDhInner.dhPrime);
|
|
235
|
-
const timeOffset = Math.floor(
|
|
235
|
+
const timeOffset = serverDhInner.serverTime - Math.floor(performance.now() / 1e3);
|
|
236
236
|
session.updateTimeOffset(timeOffset);
|
|
237
237
|
const g = BigInt(serverDhInner.g);
|
|
238
238
|
const gA = bigint.fromBytes(serverDhInner.gA);
|
|
@@ -8,15 +8,29 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
8
8
|
const abortSignal = require("../../utils/abort-signal.cjs");
|
|
9
9
|
const miscUtils = require("../../utils/misc-utils.cjs");
|
|
10
10
|
const typeAssertions = require("../../utils/type-assertions.cjs");
|
|
11
|
+
const SILENTLY_SLEEP_METHODS = /* @__PURE__ */ new Set([
|
|
12
|
+
"upload.getFile",
|
|
13
|
+
"upload.saveFilePart",
|
|
14
|
+
"upload.saveBigFilePart",
|
|
15
|
+
"updates.getDifference",
|
|
16
|
+
"updates.getChannelDifference"
|
|
17
|
+
]);
|
|
18
|
+
const SILENTLY_SLEEP_THRESHOLD = 5;
|
|
11
19
|
function floodWaiter(options) {
|
|
12
|
-
const {
|
|
20
|
+
const {
|
|
21
|
+
maxWait = 1e4,
|
|
22
|
+
maxRetries = 5,
|
|
23
|
+
store = true,
|
|
24
|
+
minStoredWait = 2e3,
|
|
25
|
+
onBeforeWait
|
|
26
|
+
} = options;
|
|
13
27
|
const storage = /* @__PURE__ */ new Map();
|
|
14
28
|
return async (ctx, next) => {
|
|
15
29
|
const method = ctx.request._;
|
|
16
30
|
const storedWaitUntil = store ? storage.get(method) : void 0;
|
|
17
31
|
const floodSleepThreshold = ctx.params?.floodSleepThreshold ?? maxWait;
|
|
18
32
|
if (storedWaitUntil !== void 0) {
|
|
19
|
-
const delta = storedWaitUntil -
|
|
33
|
+
const delta = storedWaitUntil - performance.now();
|
|
20
34
|
if (delta <= minStoredWait) {
|
|
21
35
|
storage.delete(method);
|
|
22
36
|
} else if (delta <= floodSleepThreshold) {
|
|
@@ -45,14 +59,16 @@ function floodWaiter(options) {
|
|
|
45
59
|
return res;
|
|
46
60
|
}
|
|
47
61
|
if (store && !err.startsWith("SLOWMODE_WAIT_")) {
|
|
48
|
-
storage.set(method,
|
|
62
|
+
storage.set(method, performance.now() + seconds * 1e3);
|
|
49
63
|
}
|
|
50
64
|
if (seconds === 0) {
|
|
51
65
|
seconds = 1;
|
|
52
66
|
}
|
|
53
67
|
const ms = seconds * 1e3;
|
|
54
68
|
if (ms <= floodSleepThreshold) {
|
|
55
|
-
if (
|
|
69
|
+
if (onBeforeWait) {
|
|
70
|
+
onBeforeWait(ctx, seconds);
|
|
71
|
+
} else if (!(seconds < SILENTLY_SLEEP_THRESHOLD && SILENTLY_SLEEP_METHODS.has(method))) {
|
|
56
72
|
ctx.manager._log.warn("%s resulted in a flood wait, will retry in %d seconds", method, seconds);
|
|
57
73
|
}
|
|
58
74
|
await miscUtils.sleepWithAbort(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RpcCallMiddleware } from '../network-manager.js';
|
|
1
|
+
import { RpcCallMiddleware, RpcCallMiddlewareContext } from '../network-manager.js';
|
|
2
2
|
export interface FloodWaiterOptions {
|
|
3
3
|
/**
|
|
4
4
|
* Maximum number of ms to wait when a FLOOD_WAIT_X
|
|
@@ -30,8 +30,15 @@ export interface FloodWaiterOptions {
|
|
|
30
30
|
* If the stored wait time is less than this value,
|
|
31
31
|
* the request will not be delayed
|
|
32
32
|
*
|
|
33
|
-
* @default
|
|
33
|
+
* @default 2_000
|
|
34
34
|
*/
|
|
35
35
|
minStoredWait?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Function that will be called before we are about to wait for `seconds`
|
|
38
|
+
* seconds before retrying the request.
|
|
39
|
+
*
|
|
40
|
+
* @default print a warning to the console, except some methods that often result in flood waits
|
|
41
|
+
*/
|
|
42
|
+
onBeforeWait?: (ctx: RpcCallMiddlewareContext, seconds: number) => void;
|
|
36
43
|
}
|
|
37
44
|
export declare function floodWaiter(options: FloodWaiterOptions): RpcCallMiddleware;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RpcCallMiddleware } from '../network-manager.js';
|
|
1
|
+
import { RpcCallMiddleware, RpcCallMiddlewareContext } from '../network-manager.js';
|
|
2
2
|
export interface FloodWaiterOptions {
|
|
3
3
|
/**
|
|
4
4
|
* Maximum number of ms to wait when a FLOOD_WAIT_X
|
|
@@ -30,8 +30,15 @@ export interface FloodWaiterOptions {
|
|
|
30
30
|
* If the stored wait time is less than this value,
|
|
31
31
|
* the request will not be delayed
|
|
32
32
|
*
|
|
33
|
-
* @default
|
|
33
|
+
* @default 2_000
|
|
34
34
|
*/
|
|
35
35
|
minStoredWait?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Function that will be called before we are about to wait for `seconds`
|
|
38
|
+
* seconds before retrying the request.
|
|
39
|
+
*
|
|
40
|
+
* @default print a warning to the console, except some methods that often result in flood waits
|
|
41
|
+
*/
|
|
42
|
+
onBeforeWait?: (ctx: RpcCallMiddlewareContext, seconds: number) => void;
|
|
36
43
|
}
|
|
37
44
|
export declare function floodWaiter(options: FloodWaiterOptions): RpcCallMiddleware;
|
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
import { combineAbortSignals } from "../../utils/abort-signal.js";
|
|
2
2
|
import { sleepWithAbort } from "../../utils/misc-utils.js";
|
|
3
3
|
import { isTlRpcError } from "../../utils/type-assertions.js";
|
|
4
|
+
const SILENTLY_SLEEP_METHODS = /* @__PURE__ */ new Set([
|
|
5
|
+
"upload.getFile",
|
|
6
|
+
"upload.saveFilePart",
|
|
7
|
+
"upload.saveBigFilePart",
|
|
8
|
+
"updates.getDifference",
|
|
9
|
+
"updates.getChannelDifference"
|
|
10
|
+
]);
|
|
11
|
+
const SILENTLY_SLEEP_THRESHOLD = 5;
|
|
4
12
|
function floodWaiter(options) {
|
|
5
|
-
const {
|
|
13
|
+
const {
|
|
14
|
+
maxWait = 1e4,
|
|
15
|
+
maxRetries = 5,
|
|
16
|
+
store = true,
|
|
17
|
+
minStoredWait = 2e3,
|
|
18
|
+
onBeforeWait
|
|
19
|
+
} = options;
|
|
6
20
|
const storage = /* @__PURE__ */ new Map();
|
|
7
21
|
return async (ctx, next) => {
|
|
8
22
|
const method = ctx.request._;
|
|
9
23
|
const storedWaitUntil = store ? storage.get(method) : void 0;
|
|
10
24
|
const floodSleepThreshold = ctx.params?.floodSleepThreshold ?? maxWait;
|
|
11
25
|
if (storedWaitUntil !== void 0) {
|
|
12
|
-
const delta = storedWaitUntil -
|
|
26
|
+
const delta = storedWaitUntil - performance.now();
|
|
13
27
|
if (delta <= minStoredWait) {
|
|
14
28
|
storage.delete(method);
|
|
15
29
|
} else if (delta <= floodSleepThreshold) {
|
|
@@ -38,14 +52,16 @@ function floodWaiter(options) {
|
|
|
38
52
|
return res;
|
|
39
53
|
}
|
|
40
54
|
if (store && !err.startsWith("SLOWMODE_WAIT_")) {
|
|
41
|
-
storage.set(method,
|
|
55
|
+
storage.set(method, performance.now() + seconds * 1e3);
|
|
42
56
|
}
|
|
43
57
|
if (seconds === 0) {
|
|
44
58
|
seconds = 1;
|
|
45
59
|
}
|
|
46
60
|
const ms = seconds * 1e3;
|
|
47
61
|
if (ms <= floodSleepThreshold) {
|
|
48
|
-
if (
|
|
62
|
+
if (onBeforeWait) {
|
|
63
|
+
onBeforeWait(ctx, seconds);
|
|
64
|
+
} else if (!(seconds < SILENTLY_SLEEP_THRESHOLD && SILENTLY_SLEEP_METHODS.has(method))) {
|
|
49
65
|
ctx.manager._log.warn("%s resulted in a flood wait, will retry in %d seconds", method, seconds);
|
|
50
66
|
}
|
|
51
67
|
await sleepWithAbort(
|
|
@@ -29,7 +29,7 @@ class MtprotoSession {
|
|
|
29
29
|
_authKey;
|
|
30
30
|
_authKeyTemp;
|
|
31
31
|
_authKeyTempSecondary;
|
|
32
|
-
_timeOffset =
|
|
32
|
+
_timeOffset = performance.timeOrigin;
|
|
33
33
|
_lastMessageId = Long.ZERO;
|
|
34
34
|
_seqNo = 0;
|
|
35
35
|
/// state ///
|
|
@@ -132,8 +132,8 @@ class MtprotoSession {
|
|
|
132
132
|
return true;
|
|
133
133
|
}
|
|
134
134
|
getMessageId() {
|
|
135
|
-
const timeTicks =
|
|
136
|
-
const timeSec = Math.floor(timeTicks / 1e3)
|
|
135
|
+
const timeTicks = performance.now();
|
|
136
|
+
const timeSec = Math.floor(timeTicks / 1e3) + this._timeOffset;
|
|
137
137
|
const timeMSec = timeTicks % 1e3;
|
|
138
138
|
const random = miscUtils.getRandomInt(65535);
|
|
139
139
|
let messageId = new Long(timeMSec << 21 | random << 3 | 4, timeSec);
|
|
@@ -206,7 +206,6 @@ class MtprotoSession {
|
|
|
206
206
|
this.next429Timeout = 1e3;
|
|
207
207
|
}, 6e4);
|
|
208
208
|
this.log.debug("transport flood, waiting for %d ms before proceeding", timeout);
|
|
209
|
-
return Date.now() + timeout;
|
|
210
209
|
}
|
|
211
210
|
resetLastPing(withTime = false) {
|
|
212
211
|
if (withTime) this.lastPingTime = 0;
|
|
@@ -119,7 +119,7 @@ export declare class MtprotoSession {
|
|
|
119
119
|
/** Decrypt a single MTProto message using session's keys */
|
|
120
120
|
decryptMessage(data: Uint8Array, callback: Parameters<AuthKey['decryptMessage']>[2]): void;
|
|
121
121
|
writeMessage(writer: TlBinaryWriter, content: tl.TlObject | mtp.TlObject | Uint8Array, isContentRelated?: boolean): Long;
|
|
122
|
-
onTransportFlood(callback: () => void):
|
|
122
|
+
onTransportFlood(callback: () => void): void;
|
|
123
123
|
resetLastPing(withTime?: boolean): void;
|
|
124
124
|
addToChain(chainId: string | number, msgId: Long): Long | undefined;
|
|
125
125
|
removeFromChain(chainId: string | number, msgId: Long): void;
|
|
@@ -119,7 +119,7 @@ export declare class MtprotoSession {
|
|
|
119
119
|
/** Decrypt a single MTProto message using session's keys */
|
|
120
120
|
decryptMessage(data: Uint8Array, callback: Parameters<AuthKey['decryptMessage']>[2]): void;
|
|
121
121
|
writeMessage(writer: TlBinaryWriter, content: tl.TlObject | mtp.TlObject | Uint8Array, isContentRelated?: boolean): Long;
|
|
122
|
-
onTransportFlood(callback: () => void):
|
|
122
|
+
onTransportFlood(callback: () => void): void;
|
|
123
123
|
resetLastPing(withTime?: boolean): void;
|
|
124
124
|
addToChain(chainId: string | number, msgId: Long): Long | undefined;
|
|
125
125
|
removeFromChain(chainId: string | number, msgId: Long): void;
|
|
@@ -22,7 +22,7 @@ class MtprotoSession {
|
|
|
22
22
|
_authKey;
|
|
23
23
|
_authKeyTemp;
|
|
24
24
|
_authKeyTempSecondary;
|
|
25
|
-
_timeOffset =
|
|
25
|
+
_timeOffset = performance.timeOrigin;
|
|
26
26
|
_lastMessageId = Long.ZERO;
|
|
27
27
|
_seqNo = 0;
|
|
28
28
|
/// state ///
|
|
@@ -125,8 +125,8 @@ class MtprotoSession {
|
|
|
125
125
|
return true;
|
|
126
126
|
}
|
|
127
127
|
getMessageId() {
|
|
128
|
-
const timeTicks =
|
|
129
|
-
const timeSec = Math.floor(timeTicks / 1e3)
|
|
128
|
+
const timeTicks = performance.now();
|
|
129
|
+
const timeSec = Math.floor(timeTicks / 1e3) + this._timeOffset;
|
|
130
130
|
const timeMSec = timeTicks % 1e3;
|
|
131
131
|
const random = getRandomInt(65535);
|
|
132
132
|
let messageId = new Long(timeMSec << 21 | random << 3 | 4, timeSec);
|
|
@@ -199,7 +199,6 @@ class MtprotoSession {
|
|
|
199
199
|
this.next429Timeout = 1e3;
|
|
200
200
|
}, 6e4);
|
|
201
201
|
this.log.debug("transport flood, waiting for %d ms before proceeding", timeout);
|
|
202
|
-
return Date.now() + timeout;
|
|
203
202
|
}
|
|
204
203
|
resetLastPing(withTime = false) {
|
|
205
204
|
if (withTime) this.lastPingTime = 0;
|
|
@@ -189,7 +189,7 @@ class DcConnectionManager {
|
|
|
189
189
|
return false;
|
|
190
190
|
}
|
|
191
191
|
if (this.manager.params.usePfs || forcePfs) {
|
|
192
|
-
const now =
|
|
192
|
+
const now = performance.now();
|
|
193
193
|
await Promise.all(
|
|
194
194
|
Array.from({ length: this.main.getCount() }, async (_, i) => {
|
|
195
195
|
const temp = await this.manager._storage.provider.authKeys.getTemp(this.dcId, i, now);
|
|
@@ -220,7 +220,7 @@ class NetworkManager {
|
|
|
220
220
|
_: "initConnection",
|
|
221
221
|
deviceModel,
|
|
222
222
|
systemVersion: "1.0",
|
|
223
|
-
appVersion: "0.
|
|
223
|
+
appVersion: "0.23.1",
|
|
224
224
|
systemLangCode: "en",
|
|
225
225
|
langPack: "",
|
|
226
226
|
// "langPacks are for official apps only"
|
|
@@ -501,7 +501,7 @@ class NetworkManager {
|
|
|
501
501
|
res = await multi.sendRpc(message, params?.timeout, params?.abortSignal, params?.chainId);
|
|
502
502
|
}
|
|
503
503
|
} else if (err === "AUTH_KEY_UNREGISTERED") {
|
|
504
|
-
this._log.
|
|
504
|
+
this._log.debug("exported auth key error, trying re-exporting..");
|
|
505
505
|
await this._exportAuthTo(manager);
|
|
506
506
|
res = await multi.sendRpc(message, params?.timeout, params?.abortSignal, params?.chainId);
|
|
507
507
|
}
|
|
@@ -32,7 +32,7 @@ export interface NetworkManagerParams {
|
|
|
32
32
|
writerMap: TlWriterMap;
|
|
33
33
|
isPremium: boolean;
|
|
34
34
|
emitError: (err: Error) => void;
|
|
35
|
-
onUpdate: (upd: tl.TypeUpdates) => void;
|
|
35
|
+
onUpdate: (upd: tl.TypeUpdates, fromClient: boolean) => void;
|
|
36
36
|
onUsable: () => void;
|
|
37
37
|
onConnecting: () => void;
|
|
38
38
|
onNetworkChanged: (connected: boolean) => void;
|
|
@@ -32,7 +32,7 @@ export interface NetworkManagerParams {
|
|
|
32
32
|
writerMap: TlWriterMap;
|
|
33
33
|
isPremium: boolean;
|
|
34
34
|
emitError: (err: Error) => void;
|
|
35
|
-
onUpdate: (upd: tl.TypeUpdates) => void;
|
|
35
|
+
onUpdate: (upd: tl.TypeUpdates, fromClient: boolean) => void;
|
|
36
36
|
onUsable: () => void;
|
|
37
37
|
onConnecting: () => void;
|
|
38
38
|
onNetworkChanged: (connected: boolean) => void;
|
|
@@ -182,7 +182,7 @@ class DcConnectionManager {
|
|
|
182
182
|
return false;
|
|
183
183
|
}
|
|
184
184
|
if (this.manager.params.usePfs || forcePfs) {
|
|
185
|
-
const now =
|
|
185
|
+
const now = performance.now();
|
|
186
186
|
await Promise.all(
|
|
187
187
|
Array.from({ length: this.main.getCount() }, async (_, i) => {
|
|
188
188
|
const temp = await this.manager._storage.provider.authKeys.getTemp(this.dcId, i, now);
|
|
@@ -213,7 +213,7 @@ class NetworkManager {
|
|
|
213
213
|
_: "initConnection",
|
|
214
214
|
deviceModel,
|
|
215
215
|
systemVersion: "1.0",
|
|
216
|
-
appVersion: "0.
|
|
216
|
+
appVersion: "0.23.1",
|
|
217
217
|
systemLangCode: "en",
|
|
218
218
|
langPack: "",
|
|
219
219
|
// "langPacks are for official apps only"
|
|
@@ -494,7 +494,7 @@ class NetworkManager {
|
|
|
494
494
|
res = await multi.sendRpc(message, params?.timeout, params?.abortSignal, params?.chainId);
|
|
495
495
|
}
|
|
496
496
|
} else if (err === "AUTH_KEY_UNREGISTERED") {
|
|
497
|
-
this._log.
|
|
497
|
+
this._log.debug("exported auth key error, trying re-exporting..");
|
|
498
498
|
await this._exportAuthTo(manager);
|
|
499
499
|
res = await multi.sendRpc(message, params?.timeout, params?.abortSignal, params?.chainId);
|
|
500
500
|
}
|
|
@@ -23,6 +23,7 @@ class PersistentConnection {
|
|
|
23
23
|
this.log.debug("connecting to %j", dc);
|
|
24
24
|
return params.transport.connect(dc);
|
|
25
25
|
},
|
|
26
|
+
strategy: params.reconnectionStrategy,
|
|
26
27
|
onOpen: this._onOpen.bind(this),
|
|
27
28
|
onClose: this._onClose.bind(this),
|
|
28
29
|
onError: this._onError.bind(this),
|
|
@@ -16,6 +16,7 @@ class PersistentConnection {
|
|
|
16
16
|
this.log.debug("connecting to %j", dc);
|
|
17
17
|
return params.transport.connect(dc);
|
|
18
18
|
},
|
|
19
|
+
strategy: params.reconnectionStrategy,
|
|
19
20
|
onOpen: this._onOpen.bind(this),
|
|
20
21
|
onClose: this._onClose.bind(this),
|
|
21
22
|
onError: this._onError.bind(this),
|
|
@@ -762,7 +762,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
762
762
|
if (info.pingId.neq(pingId)) {
|
|
763
763
|
this.log.warn("received pong to %l, but expected ping_id = %l (got %l)", msgId, info.pingId, pingId);
|
|
764
764
|
}
|
|
765
|
-
const rtt =
|
|
765
|
+
const rtt = performance.now() - this._session.lastPingTime;
|
|
766
766
|
this._session.lastPingRtt = rtt;
|
|
767
767
|
if (info.containerId.neq(msgId)) {
|
|
768
768
|
this._onMessageAcked(info.containerId);
|
|
@@ -781,7 +781,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
781
781
|
case 20: {
|
|
782
782
|
if (msg.errorCode !== 20) {
|
|
783
783
|
const serverTime = msgId.high >>> 0;
|
|
784
|
-
const timeOffset = Math.floor(
|
|
784
|
+
const timeOffset = serverTime - Math.floor(performance.now() / 1e3);
|
|
785
785
|
this._session.updateTimeOffset(timeOffset);
|
|
786
786
|
this.log.debug("server time: %d, corrected offset to %d", serverTime, timeOffset);
|
|
787
787
|
}
|
|
@@ -1130,7 +1130,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1130
1130
|
let cancelRpcs = null;
|
|
1131
1131
|
let destroySessions = null;
|
|
1132
1132
|
let rootMsgId = null;
|
|
1133
|
-
const now =
|
|
1133
|
+
const now = performance.now();
|
|
1134
1134
|
if (this._session.queuedAcks.length) {
|
|
1135
1135
|
let acks = this._session.queuedAcks;
|
|
1136
1136
|
if (acks.length > 8192) {
|
|
@@ -1151,7 +1151,9 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1151
1151
|
if (now - this._session.lastPingTime > this._pingInterval) {
|
|
1152
1152
|
if (!this._session.lastPingMsgId.isZero()) {
|
|
1153
1153
|
this.log.warn("didn't receive pong for previous ping (msg_id = %l). are we offline?", this._session.lastPingMsgId);
|
|
1154
|
-
this.
|
|
1154
|
+
if (!this._disconnectedManually) {
|
|
1155
|
+
this._resetSession("ping timeout");
|
|
1156
|
+
}
|
|
1155
1157
|
return;
|
|
1156
1158
|
}
|
|
1157
1159
|
pingId = longUtils.randomLong();
|
|
@@ -1161,7 +1163,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
|
|
|
1161
1163
|
// ÷ 1000 * 1.25
|
|
1162
1164
|
disconnectDelay: Math.round(this._pingInterval * 125e-5)
|
|
1163
1165
|
};
|
|
1164
|
-
this._session.lastPingTime =
|
|
1166
|
+
this._session.lastPingTime = now;
|
|
1165
1167
|
pingRequest = tlRuntime.TlBinaryWriter.serializeObject(this._writerMap, obj);
|
|
1166
1168
|
containerSize += pingRequest.length + 16;
|
|
1167
1169
|
containerMessageCount += 1;
|
|
@@ -755,7 +755,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
755
755
|
if (info.pingId.neq(pingId)) {
|
|
756
756
|
this.log.warn("received pong to %l, but expected ping_id = %l (got %l)", msgId, info.pingId, pingId);
|
|
757
757
|
}
|
|
758
|
-
const rtt =
|
|
758
|
+
const rtt = performance.now() - this._session.lastPingTime;
|
|
759
759
|
this._session.lastPingRtt = rtt;
|
|
760
760
|
if (info.containerId.neq(msgId)) {
|
|
761
761
|
this._onMessageAcked(info.containerId);
|
|
@@ -774,7 +774,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
774
774
|
case 20: {
|
|
775
775
|
if (msg.errorCode !== 20) {
|
|
776
776
|
const serverTime = msgId.high >>> 0;
|
|
777
|
-
const timeOffset = Math.floor(
|
|
777
|
+
const timeOffset = serverTime - Math.floor(performance.now() / 1e3);
|
|
778
778
|
this._session.updateTimeOffset(timeOffset);
|
|
779
779
|
this.log.debug("server time: %d, corrected offset to %d", serverTime, timeOffset);
|
|
780
780
|
}
|
|
@@ -1123,7 +1123,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
1123
1123
|
let cancelRpcs = null;
|
|
1124
1124
|
let destroySessions = null;
|
|
1125
1125
|
let rootMsgId = null;
|
|
1126
|
-
const now =
|
|
1126
|
+
const now = performance.now();
|
|
1127
1127
|
if (this._session.queuedAcks.length) {
|
|
1128
1128
|
let acks = this._session.queuedAcks;
|
|
1129
1129
|
if (acks.length > 8192) {
|
|
@@ -1144,7 +1144,9 @@ class SessionConnection extends PersistentConnection {
|
|
|
1144
1144
|
if (now - this._session.lastPingTime > this._pingInterval) {
|
|
1145
1145
|
if (!this._session.lastPingMsgId.isZero()) {
|
|
1146
1146
|
this.log.warn("didn't receive pong for previous ping (msg_id = %l). are we offline?", this._session.lastPingMsgId);
|
|
1147
|
-
this.
|
|
1147
|
+
if (!this._disconnectedManually) {
|
|
1148
|
+
this._resetSession("ping timeout");
|
|
1149
|
+
}
|
|
1148
1150
|
return;
|
|
1149
1151
|
}
|
|
1150
1152
|
pingId = randomLong();
|
|
@@ -1154,7 +1156,7 @@ class SessionConnection extends PersistentConnection {
|
|
|
1154
1156
|
// ÷ 1000 * 1.25
|
|
1155
1157
|
disconnectDelay: Math.round(this._pingInterval * 125e-5)
|
|
1156
1158
|
};
|
|
1157
|
-
this._session.lastPingTime =
|
|
1159
|
+
this._session.lastPingTime = now;
|
|
1158
1160
|
pingRequest = TlBinaryWriter.serializeObject(this._writerMap, obj);
|
|
1159
1161
|
containerSize += pingRequest.length + 16;
|
|
1160
1162
|
containerMessageCount += 1;
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mtcute/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.23.1",
|
|
5
5
|
"description": "Type-safe library for MTProto (Telegram API)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@fuman/io": "0.0.
|
|
10
|
-
"@fuman/net": "0.0.
|
|
11
|
-
"@fuman/utils": "0.0.
|
|
12
|
-
"@mtcute/file-id": "^0.
|
|
13
|
-
"@mtcute/tl": "^
|
|
14
|
-
"@mtcute/tl-runtime": "^0.
|
|
9
|
+
"@fuman/io": "0.0.14",
|
|
10
|
+
"@fuman/net": "0.0.14",
|
|
11
|
+
"@fuman/utils": "0.0.14",
|
|
12
|
+
"@mtcute/file-id": "^0.23.0",
|
|
13
|
+
"@mtcute/tl": "^202.0.0",
|
|
14
|
+
"@mtcute/tl-runtime": "^0.23.0",
|
|
15
15
|
"@types/events": "3.0.0",
|
|
16
16
|
"long": "5.2.3"
|
|
17
17
|
},
|
package/utils/binary/compat.cjs
CHANGED
|
@@ -89,6 +89,8 @@ function mapCompatObject(obj) {
|
|
|
89
89
|
return mapCompatMessageAction(obj);
|
|
90
90
|
case "userFull_layer199":
|
|
91
91
|
return replaceType(dropFields(obj, ["premiumGifts"]), "userFull");
|
|
92
|
+
case "userFull_layer200":
|
|
93
|
+
return replaceType(obj, "userFull");
|
|
92
94
|
case "user_layer199":
|
|
93
95
|
return {
|
|
94
96
|
...obj,
|
package/utils/binary/compat.js
CHANGED
|
@@ -82,6 +82,8 @@ function mapCompatObject(obj) {
|
|
|
82
82
|
return mapCompatMessageAction(obj);
|
|
83
83
|
case "userFull_layer199":
|
|
84
84
|
return replaceType(dropFields(obj, ["premiumGifts"]), "userFull");
|
|
85
|
+
case "userFull_layer200":
|
|
86
|
+
return replaceType(obj, "userFull");
|
|
85
87
|
case "user_layer199":
|
|
86
88
|
return {
|
|
87
89
|
...obj,
|
package/utils/early-timer.cjs
CHANGED
|
@@ -16,11 +16,11 @@ class EarlyTimer {
|
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Emit the timer when the event loop is idle
|
|
19
|
-
* (basically `
|
|
19
|
+
* (basically `queueMicrotask()`)
|
|
20
20
|
*/
|
|
21
21
|
emitWhenIdle() {
|
|
22
22
|
utils.timers.clearTimeout(this._timeout);
|
|
23
|
-
this._timeoutTs =
|
|
23
|
+
this._timeoutTs = performance.now();
|
|
24
24
|
if (typeof queueMicrotask !== "undefined") {
|
|
25
25
|
queueMicrotask(this.emitNow);
|
|
26
26
|
} else {
|
|
@@ -30,23 +30,28 @@ class EarlyTimer {
|
|
|
30
30
|
/**
|
|
31
31
|
* Emit the timer before the next given milliseconds
|
|
32
32
|
*
|
|
33
|
-
* Shorthand for `emitBefore(
|
|
33
|
+
* Shorthand for `emitBefore(performance.now() + ms)`
|
|
34
34
|
*
|
|
35
35
|
* @param ms Milliseconds to schedule for
|
|
36
36
|
*/
|
|
37
37
|
emitBeforeNext(ms) {
|
|
38
|
-
return this.emitBefore(
|
|
38
|
+
return this.emitBefore(performance.now() + ms);
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Emit the timer before the given time
|
|
42
42
|
*
|
|
43
|
-
* @param ts
|
|
43
|
+
* @param ts timestamp in ms relative to `performance.timeOrigin`
|
|
44
44
|
*/
|
|
45
45
|
emitBefore(ts) {
|
|
46
46
|
if (!this._timeoutTs || ts < this._timeoutTs) {
|
|
47
47
|
this.reset();
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const diff = ts - performance.now();
|
|
49
|
+
if (diff > 0) {
|
|
50
|
+
this._timeout = utils.timers.setTimeout(this.emitNow, diff);
|
|
51
|
+
this._timeoutTs = ts;
|
|
52
|
+
} else {
|
|
53
|
+
this._handler();
|
|
54
|
+
}
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
/**
|