@mtcute/core 0.29.7 → 0.30.0

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 (90) hide show
  1. package/highlevel/client.d.cts +4 -6
  2. package/highlevel/client.d.ts +4 -6
  3. package/highlevel/methods/chats/join-chat.cjs +38 -16
  4. package/highlevel/methods/chats/join-chat.d.cts +20 -6
  5. package/highlevel/methods/chats/join-chat.d.ts +20 -6
  6. package/highlevel/methods/chats/join-chat.js +38 -16
  7. package/highlevel/methods/chats/save-draft.d.cts +4 -1
  8. package/highlevel/methods/chats/save-draft.d.ts +4 -1
  9. package/highlevel/methods.d.cts +2 -0
  10. package/highlevel/methods.d.ts +2 -0
  11. package/highlevel/storage/service/peers.cjs +1 -0
  12. package/highlevel/storage/service/peers.js +1 -0
  13. package/highlevel/types/files/utils.d.cts +1 -1
  14. package/highlevel/types/files/utils.d.ts +1 -1
  15. package/highlevel/types/messages/index.d.cts +1 -0
  16. package/highlevel/types/messages/index.d.ts +1 -0
  17. package/highlevel/types/messages/message.cjs +5 -0
  18. package/highlevel/types/messages/message.d.cts +3 -0
  19. package/highlevel/types/messages/message.d.ts +3 -0
  20. package/highlevel/types/messages/message.js +5 -0
  21. package/highlevel/types/messages/rich-message.cjs +50 -0
  22. package/highlevel/types/messages/rich-message.d.cts +18 -0
  23. package/highlevel/types/messages/rich-message.d.ts +18 -0
  24. package/highlevel/types/messages/rich-message.js +45 -0
  25. package/highlevel/types/peers/full-chat.cjs +6 -0
  26. package/highlevel/types/peers/full-chat.d.cts +2 -0
  27. package/highlevel/types/peers/full-chat.d.ts +2 -0
  28. package/highlevel/types/peers/full-chat.js +6 -0
  29. package/highlevel/types/peers/user.cjs +4 -0
  30. package/highlevel/types/peers/user.d.cts +2 -0
  31. package/highlevel/types/peers/user.d.ts +2 -0
  32. package/highlevel/types/peers/user.js +4 -0
  33. package/highlevel/types/updates/user-typing-update.cjs +2 -0
  34. package/highlevel/types/updates/user-typing-update.js +2 -0
  35. package/highlevel/updates/manager.cjs +191 -0
  36. package/highlevel/updates/manager.js +191 -0
  37. package/highlevel/utils/inspectable.cjs +1 -0
  38. package/highlevel/utils/inspectable.d.cts +1 -0
  39. package/highlevel/utils/inspectable.d.ts +1 -0
  40. package/highlevel/utils/inspectable.js +1 -0
  41. package/index.cjs +2 -0
  42. package/index.js +2 -0
  43. package/network/flood-control.cjs +149 -0
  44. package/network/flood-control.d.cts +79 -0
  45. package/network/flood-control.d.ts +79 -0
  46. package/network/flood-control.js +144 -0
  47. package/network/flood-control.test.d.cts +1 -0
  48. package/network/flood-control.test.d.ts +1 -0
  49. package/network/mtproto-session.cjs +1 -21
  50. package/network/mtproto-session.d.cts +1 -5
  51. package/network/mtproto-session.d.ts +1 -5
  52. package/network/mtproto-session.js +2 -22
  53. package/network/multi-session-connection.cjs +26 -16
  54. package/network/multi-session-connection.d.cts +1 -1
  55. package/network/multi-session-connection.d.ts +1 -1
  56. package/network/multi-session-connection.js +26 -16
  57. package/network/multi-session-connection.test.d.cts +1 -0
  58. package/network/multi-session-connection.test.d.ts +1 -0
  59. package/network/network-manager.cjs +3 -2
  60. package/network/network-manager.d.cts +12 -0
  61. package/network/network-manager.d.ts +12 -0
  62. package/network/network-manager.js +3 -2
  63. package/network/persistent-connection.cjs +25 -1
  64. package/network/persistent-connection.d.cts +5 -0
  65. package/network/persistent-connection.d.ts +5 -0
  66. package/network/persistent-connection.js +25 -1
  67. package/network/session-connection.cjs +5 -10
  68. package/network/session-connection.d.cts +0 -2
  69. package/network/session-connection.d.ts +0 -2
  70. package/network/session-connection.js +5 -10
  71. package/package.json +1 -1
  72. package/tl/api-schema.json +1 -1
  73. package/tl/binary/reader.cjs +176 -26
  74. package/tl/binary/reader.js +176 -26
  75. package/tl/binary/writer.cjs +439 -20
  76. package/tl/binary/writer.js +439 -20
  77. package/tl/compat/reader.cjs +23 -0
  78. package/tl/compat/reader.js +23 -0
  79. package/tl/index.d.cts +414 -14
  80. package/tl/index.d.ts +414 -14
  81. package/tl/inner-tl.cjs +20 -8
  82. package/tl/inner-tl.js +20 -8
  83. package/utils/binary/compat.cjs +79 -0
  84. package/utils/binary/compat.js +79 -0
  85. package/utils/index.d.cts +1 -0
  86. package/utils/index.d.ts +1 -0
  87. package/utils/long-utils.cjs +10 -0
  88. package/utils/long-utils.js +10 -0
  89. package/utils.cjs +7 -0
  90. package/utils.js +8 -1
@@ -6,6 +6,7 @@ import { Deferred, Emitter } from '@fuman/utils';
6
6
  export declare class MultiSessionConnection {
7
7
  readonly params: SessionConnectionParams;
8
8
  private _count;
9
+ static _pickConnection(loads: readonly number[], ready: readonly boolean[]): number;
9
10
  private _log;
10
11
  private _enforcePfs;
11
12
  readonly onRequestKeys: Emitter<Deferred<void>>;
@@ -25,7 +26,6 @@ export declare class MultiSessionConnection {
25
26
  private _updateConnections;
26
27
  _destroyed: boolean;
27
28
  destroy(): Promise<void>;
28
- private _nextConnection;
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;
@@ -6,6 +6,7 @@ import { Deferred, Emitter } from '@fuman/utils';
6
6
  export declare class MultiSessionConnection {
7
7
  readonly params: SessionConnectionParams;
8
8
  private _count;
9
+ static _pickConnection(loads: readonly number[], ready: readonly boolean[]): number;
9
10
  private _log;
10
11
  private _enforcePfs;
11
12
  readonly onRequestKeys: Emitter<Deferred<void>>;
@@ -25,7 +26,6 @@ export declare class MultiSessionConnection {
25
26
  private _updateConnections;
26
27
  _destroyed: boolean;
27
28
  destroy(): Promise<void>;
28
- private _nextConnection;
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;
@@ -9,6 +9,24 @@ class MultiSessionConnection {
9
9
  this._enforcePfs = _count > 1 && params.isMainConnection;
10
10
  this._updateConnections();
11
11
  }
12
+ static _pickConnection(loads, ready) {
13
+ let min = Infinity;
14
+ let minIdx = 0;
15
+ let foundReady = false;
16
+ for (let i = 0; i < loads.length; i++) {
17
+ const isReady = ready[i];
18
+ if (foundReady && !isReady) continue;
19
+ if (isReady && !foundReady) {
20
+ foundReady = true;
21
+ min = Infinity;
22
+ }
23
+ if (loads[i] < min) {
24
+ min = loads[i];
25
+ minIdx = i;
26
+ }
27
+ }
28
+ return minIdx;
29
+ }
12
30
  _log;
13
31
  _enforcePfs = false;
14
32
  // NB: dont forget to update .reset()
@@ -96,10 +114,6 @@ class MultiSessionConnection {
96
114
  conn.onUsable.add(() => this.onUsable.emit(i));
97
115
  conn.onWait.add(() => this.onWait.emit(i));
98
116
  conn.onRequestAuth.add(() => this.onRequestAuth.emit(i));
99
- conn.onFloodDone.add(() => {
100
- this._log.debug("received flood-done from connection %d", i);
101
- this._connections.forEach((it) => it.flushWhenIdle());
102
- });
103
117
  this._connections.push(conn);
104
118
  if (this._authKey !== null) conn._session._authKey.setup(this._authKey);
105
119
  if (connect && !enforcePfsChanged) conn.connect();
@@ -120,19 +134,15 @@ class MultiSessionConnection {
120
134
  this.onRequestAuth.clear();
121
135
  this._destroyed = true;
122
136
  }
123
- _nextConnection = 0;
124
137
  sendRpc(request, timeout, abortSignal, chainId) {
125
- let min = Infinity;
126
- let minIdx = 0;
127
- for (let i = 0; i < this._connections.length; i++) {
128
- const conn = this._connections[i];
129
- const total = conn._session.queuedRpc.length + conn._session.pendingMessages.size;
130
- if (total < min) {
131
- min = total;
132
- minIdx = i;
133
- }
134
- }
135
- return this._connections[minIdx].sendRpc(request, timeout, abortSignal, chainId);
138
+ const loads = this._connections.map((c) => c._session.queuedRpc.length + c._session.pendingMessages.size);
139
+ const ready = this._connections.map((c) => c.isConnected);
140
+ return this._connections[MultiSessionConnection._pickConnection(loads, ready)].sendRpc(
141
+ request,
142
+ timeout,
143
+ abortSignal,
144
+ chainId
145
+ );
136
146
  }
137
147
  connect() {
138
148
  for (const conn of this._connections) {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -53,7 +53,8 @@ class DcConnectionManager {
53
53
  // NB: we need a separate salts manager for each pfs connection, because server salts are auth_key-bound
54
54
  salts: managerParams.usePfs ? new serverSalt.ServerSaltManager() : this._salts,
55
55
  platform: managerParams.platform,
56
- pingInterval: managerParams.pingInterval ?? 6e4
56
+ pingInterval: managerParams.pingInterval ?? 6e4,
57
+ floodControl: managerParams.floodControl === false ? void 0 : managerParams.floodControl ?? {}
57
58
  });
58
59
  const mainParams = baseConnectionParams();
59
60
  mainParams.isMainConnection = true;
@@ -226,7 +227,7 @@ class NetworkManager {
226
227
  _: "initConnection",
227
228
  deviceModel,
228
229
  systemVersion: "1.0",
229
- appVersion: "0.29.7",
230
+ appVersion: "0.30.0",
230
231
  systemLangCode: "en",
231
232
  langPack: "",
232
233
  // "langPacks are for official apps only"
@@ -7,6 +7,7 @@ import { mtp, tl } from '../tl/index.js';
7
7
  import { ICorePlatform } from '../types/platform.js';
8
8
  import { DcOptions, ICryptoProvider, Logger } from '../utils/index.js';
9
9
  import { ConfigManager } from './config-manager.js';
10
+ import { ConnectionFloodLimits } from './flood-control.js';
10
11
  import { TelegramTransport } from './transports/abstract.js';
11
12
  import { MultiSessionConnection } from './multi-session-connection.js';
12
13
  export type ConnectionKind = 'main' | 'upload' | 'download' | 'downloadSmall';
@@ -83,6 +84,17 @@ export interface NetworkManagerExtraParams {
83
84
  * @default 60000 (1 minute)
84
85
  */
85
86
  pingInterval?: number;
87
+ /**
88
+ * Per-connection-slot flood-control limits (each socket throttles its own
89
+ * connect attempts independently, like TDLib). Override only if you
90
+ * understand the consequences — defaults are derived from TDLib and
91
+ * should fit most clients.
92
+ *
93
+ * See {@link ConnectionFloodLimits} for the limiter taxonomy.
94
+ *
95
+ * `false` to disable flood control.
96
+ */
97
+ floodControl?: ConnectionFloodLimits | false;
86
98
  }
87
99
  /** Options that can be customized when making an RPC call */
88
100
  export interface RpcCallOptions {
@@ -7,6 +7,7 @@ import { mtp, tl } from '../tl/index.js';
7
7
  import { ICorePlatform } from '../types/platform.js';
8
8
  import { DcOptions, ICryptoProvider, Logger } from '../utils/index.js';
9
9
  import { ConfigManager } from './config-manager.js';
10
+ import { ConnectionFloodLimits } from './flood-control.js';
10
11
  import { TelegramTransport } from './transports/abstract.js';
11
12
  import { MultiSessionConnection } from './multi-session-connection.js';
12
13
  export type ConnectionKind = 'main' | 'upload' | 'download' | 'downloadSmall';
@@ -83,6 +84,17 @@ export interface NetworkManagerExtraParams {
83
84
  * @default 60000 (1 minute)
84
85
  */
85
86
  pingInterval?: number;
87
+ /**
88
+ * Per-connection-slot flood-control limits (each socket throttles its own
89
+ * connect attempts independently, like TDLib). Override only if you
90
+ * understand the consequences — defaults are derived from TDLib and
91
+ * should fit most clients.
92
+ *
93
+ * See {@link ConnectionFloodLimits} for the limiter taxonomy.
94
+ *
95
+ * `false` to disable flood control.
96
+ */
97
+ floodControl?: ConnectionFloodLimits | false;
86
98
  }
87
99
  /** Options that can be customized when making an RPC call */
88
100
  export interface RpcCallOptions {
@@ -46,7 +46,8 @@ class DcConnectionManager {
46
46
  // NB: we need a separate salts manager for each pfs connection, because server salts are auth_key-bound
47
47
  salts: managerParams.usePfs ? new ServerSaltManager() : this._salts,
48
48
  platform: managerParams.platform,
49
- pingInterval: managerParams.pingInterval ?? 6e4
49
+ pingInterval: managerParams.pingInterval ?? 6e4,
50
+ floodControl: managerParams.floodControl === false ? void 0 : managerParams.floodControl ?? {}
50
51
  });
51
52
  const mainParams = baseConnectionParams();
52
53
  mainParams.isMainConnection = true;
@@ -219,7 +220,7 @@ class NetworkManager {
219
220
  _: "initConnection",
220
221
  deviceModel,
221
222
  systemVersion: "1.0",
222
- appVersion: "0.29.7",
223
+ appVersion: "0.30.0",
223
224
  systemLangCode: "en",
224
225
  langPack: "",
225
226
  // "langPacks are for official apps only"
@@ -8,6 +8,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
8
8
  const io = require("@fuman/io");
9
9
  const net = require("@fuman/net");
10
10
  const utils = require("@fuman/utils");
11
+ const floodControl = require("./flood-control.cjs");
11
12
  let nextConnectionUid = 0;
12
13
  class PersistentConnection {
13
14
  constructor(params, log) {
@@ -16,9 +17,20 @@ class PersistentConnection {
16
17
  this.params.transport.setup?.(this.params.crypto, log);
17
18
  this._codec = this.params.transport.packetCodec(params.dc);
18
19
  this._codec.setup?.(this.params.crypto, this.log);
20
+ if (params.floodControl) {
21
+ this._floodControl = new floodControl.ConnectionFloodController(params.floodControl);
22
+ this._floodControl.setLogger(log.create("flood"));
23
+ }
19
24
  this._onInactivityTimeout = this._onInactivityTimeout.bind(this);
20
25
  this._fuman = new net.PersistentConnection({
21
- connect: (dc) => {
26
+ connect: async (dc) => {
27
+ if (this._floodControl) {
28
+ if (!this._connectAbort || this._connectAbort.signal.aborted) {
29
+ this._connectAbort = new AbortController();
30
+ }
31
+ this._updateLogPrefix();
32
+ await this._floodControl.wait(this._connectAbort.signal);
33
+ }
22
34
  this._updateLogPrefix();
23
35
  this.log.debug("connecting to %j", dc);
24
36
  return params.transport.connect(dc);
@@ -47,6 +59,14 @@ class PersistentConnection {
47
59
  _inactive = true;
48
60
  _destroyed = false;
49
61
  _usable = false;
62
+ // each connection slot throttles its own connect attempts, mirroring
63
+ // TDLib's per-SessionProxy flood control. a fresh controller has empty
64
+ // limiters, so the first connect always passes immediately.
65
+ _floodControl;
66
+ // aborts a pending flood-control wait when the connection is being
67
+ // closed (manually or for good) — otherwise close() would block until
68
+ // the wait expires, and the connect would still proceed afterwards
69
+ _connectAbort;
50
70
  onWait = new utils.Emitter();
51
71
  onUsable = new utils.Emitter();
52
72
  onError = new utils.Emitter();
@@ -111,6 +131,7 @@ class PersistentConnection {
111
131
  return "reconnect";
112
132
  }
113
133
  async changeTransport(transport) {
134
+ this._connectAbort?.abort();
114
135
  await this._fuman.close();
115
136
  this._codec = transport.packetCodec(this.params.dc);
116
137
  this._codec.setup?.(this.params.crypto, this.log);
@@ -134,6 +155,7 @@ class PersistentConnection {
134
155
  utils.timers.clearTimeout(this._inactivityTimeout);
135
156
  }
136
157
  this._disconnectedManually = true;
158
+ this._connectAbort?.abort();
137
159
  await this._fuman.close();
138
160
  }
139
161
  async destroy() {
@@ -141,6 +163,7 @@ class PersistentConnection {
141
163
  utils.timers.clearTimeout(this._inactivityTimeout);
142
164
  }
143
165
  this._destroyed = true;
166
+ this._connectAbort?.abort();
144
167
  await this._fuman.close();
145
168
  }
146
169
  _rescheduleInactivity() {
@@ -152,6 +175,7 @@ class PersistentConnection {
152
175
  this.log.info("disconnected because of inactivity for %d", this.params.inactivityTimeout);
153
176
  this._inactive = true;
154
177
  this._inactivityTimeout = null;
178
+ this._connectAbort?.abort();
155
179
  Promise.resolve(this._fuman.close()).catch((err) => {
156
180
  this.log.warn("error closing transport: %e", err);
157
181
  });
@@ -1,6 +1,7 @@
1
1
  import { ReconnectionStrategy } from '@fuman/net';
2
2
  import { tl } from '../tl/index.js';
3
3
  import { BasicDcOption, ICryptoProvider, Logger } from '../utils/index.js';
4
+ import { ConnectionFloodLimits, ConnectionFloodController } from './flood-control.js';
4
5
  import { TelegramTransport } from './transports/abstract.js';
5
6
  import { Emitter } from '@fuman/utils';
6
7
  export interface PersistentConnectionParams {
@@ -10,6 +11,8 @@ export interface PersistentConnectionParams {
10
11
  testMode: boolean;
11
12
  reconnectionStrategy: ReconnectionStrategy;
12
13
  inactivityTimeout?: number;
14
+ /** if present, each connection gates its connects through its own flood controller */
15
+ floodControl?: ConnectionFloodLimits;
13
16
  }
14
17
  /**
15
18
  * Base class for persistent connections.
@@ -28,6 +31,8 @@ export declare abstract class PersistentConnection {
28
31
  _inactive: boolean;
29
32
  _destroyed: boolean;
30
33
  _usable: boolean;
34
+ protected readonly _floodControl?: ConnectionFloodController;
35
+ private _connectAbort?;
31
36
  readonly onWait: Emitter<number>;
32
37
  readonly onUsable: Emitter<void>;
33
38
  readonly onError: Emitter<Error>;
@@ -1,6 +1,7 @@
1
1
  import { ReconnectionStrategy } from '@fuman/net';
2
2
  import { tl } from '../tl/index.js';
3
3
  import { BasicDcOption, ICryptoProvider, Logger } from '../utils/index.js';
4
+ import { ConnectionFloodLimits, ConnectionFloodController } from './flood-control.js';
4
5
  import { TelegramTransport } from './transports/abstract.js';
5
6
  import { Emitter } from '@fuman/utils';
6
7
  export interface PersistentConnectionParams {
@@ -10,6 +11,8 @@ export interface PersistentConnectionParams {
10
11
  testMode: boolean;
11
12
  reconnectionStrategy: ReconnectionStrategy;
12
13
  inactivityTimeout?: number;
14
+ /** if present, each connection gates its connects through its own flood controller */
15
+ floodControl?: ConnectionFloodLimits;
13
16
  }
14
17
  /**
15
18
  * Base class for persistent connections.
@@ -28,6 +31,8 @@ export declare abstract class PersistentConnection {
28
31
  _inactive: boolean;
29
32
  _destroyed: boolean;
30
33
  _usable: boolean;
34
+ protected readonly _floodControl?: ConnectionFloodController;
35
+ private _connectAbort?;
31
36
  readonly onWait: Emitter<number>;
32
37
  readonly onUsable: Emitter<void>;
33
38
  readonly onError: Emitter<Error>;
@@ -1,6 +1,7 @@
1
1
  import { FramedReader, FramedWriter } from "@fuman/io";
2
2
  import { PersistentConnection as PersistentConnection$1, ip, ConnectionClosedError } from "@fuman/net";
3
3
  import { Emitter, timers } from "@fuman/utils";
4
+ import { ConnectionFloodController } from "./flood-control.js";
4
5
  let nextConnectionUid = 0;
5
6
  class PersistentConnection {
6
7
  constructor(params, log) {
@@ -9,9 +10,20 @@ class PersistentConnection {
9
10
  this.params.transport.setup?.(this.params.crypto, log);
10
11
  this._codec = this.params.transport.packetCodec(params.dc);
11
12
  this._codec.setup?.(this.params.crypto, this.log);
13
+ if (params.floodControl) {
14
+ this._floodControl = new ConnectionFloodController(params.floodControl);
15
+ this._floodControl.setLogger(log.create("flood"));
16
+ }
12
17
  this._onInactivityTimeout = this._onInactivityTimeout.bind(this);
13
18
  this._fuman = new PersistentConnection$1({
14
- connect: (dc) => {
19
+ connect: async (dc) => {
20
+ if (this._floodControl) {
21
+ if (!this._connectAbort || this._connectAbort.signal.aborted) {
22
+ this._connectAbort = new AbortController();
23
+ }
24
+ this._updateLogPrefix();
25
+ await this._floodControl.wait(this._connectAbort.signal);
26
+ }
15
27
  this._updateLogPrefix();
16
28
  this.log.debug("connecting to %j", dc);
17
29
  return params.transport.connect(dc);
@@ -40,6 +52,14 @@ class PersistentConnection {
40
52
  _inactive = true;
41
53
  _destroyed = false;
42
54
  _usable = false;
55
+ // each connection slot throttles its own connect attempts, mirroring
56
+ // TDLib's per-SessionProxy flood control. a fresh controller has empty
57
+ // limiters, so the first connect always passes immediately.
58
+ _floodControl;
59
+ // aborts a pending flood-control wait when the connection is being
60
+ // closed (manually or for good) — otherwise close() would block until
61
+ // the wait expires, and the connect would still proceed afterwards
62
+ _connectAbort;
43
63
  onWait = new Emitter();
44
64
  onUsable = new Emitter();
45
65
  onError = new Emitter();
@@ -104,6 +124,7 @@ class PersistentConnection {
104
124
  return "reconnect";
105
125
  }
106
126
  async changeTransport(transport) {
127
+ this._connectAbort?.abort();
107
128
  await this._fuman.close();
108
129
  this._codec = transport.packetCodec(this.params.dc);
109
130
  this._codec.setup?.(this.params.crypto, this.log);
@@ -127,6 +148,7 @@ class PersistentConnection {
127
148
  timers.clearTimeout(this._inactivityTimeout);
128
149
  }
129
150
  this._disconnectedManually = true;
151
+ this._connectAbort?.abort();
130
152
  await this._fuman.close();
131
153
  }
132
154
  async destroy() {
@@ -134,6 +156,7 @@ class PersistentConnection {
134
156
  timers.clearTimeout(this._inactivityTimeout);
135
157
  }
136
158
  this._destroyed = true;
159
+ this._connectAbort?.abort();
137
160
  await this._fuman.close();
138
161
  }
139
162
  _rescheduleInactivity() {
@@ -145,6 +168,7 @@ class PersistentConnection {
145
168
  this.log.info("disconnected because of inactivity for %d", this.params.inactivityTimeout);
146
169
  this._inactive = true;
147
170
  this._inactivityTimeout = null;
171
+ this._connectAbort?.abort();
148
172
  Promise.resolve(this._fuman.close()).catch((err) => {
149
173
  this.log.warn("error closing transport: %e", err);
150
174
  });
@@ -48,7 +48,6 @@ class SessionConnection extends persistentConnection.PersistentConnection {
48
48
  onDisconnect = new utils.Emitter();
49
49
  onKeyChange = new utils.Emitter();
50
50
  onTmpKeyChange = new utils.Emitter();
51
- onFloodDone = new utils.Emitter();
52
51
  onRequestAuth = new utils.Emitter();
53
52
  onAuthBegin = new utils.Emitter();
54
53
  onUpdate = new utils.Emitter();
@@ -120,7 +119,6 @@ class SessionConnection extends persistentConnection.PersistentConnection {
120
119
  this.onDisconnect.clear();
121
120
  this.onKeyChange.clear();
122
121
  this.onTmpKeyChange.clear();
123
- this.onFloodDone.clear();
124
122
  this.onRequestAuth.clear();
125
123
  this.onAuthBegin.clear();
126
124
  this.onUpdate.clear();
@@ -184,7 +182,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
184
182
  this.log.error("transport error %d", error.code);
185
183
  this._onAllFailed(`transport error ${error.code}`);
186
184
  if (error.code === 429) {
187
- this._session.onTransportFlood(() => this.onFloodDone.emit());
185
+ this._floodControl?.addMtprotoError();
188
186
  return;
189
187
  }
190
188
  }
@@ -1056,6 +1054,7 @@ class SessionConnection extends persistentConnection.PersistentConnection {
1056
1054
  notifyNetworkChanged(online) {
1057
1055
  this._online = online;
1058
1056
  if (online) {
1057
+ this._floodControl?.notifyNetworkUp();
1059
1058
  if (this._inactive) return;
1060
1059
  this.reconnect();
1061
1060
  } else {
@@ -1113,9 +1112,6 @@ class SessionConnection extends persistentConnection.PersistentConnection {
1113
1112
  this._inactivityPendingFlush = true;
1114
1113
  this._flush();
1115
1114
  }
1116
- flushWhenIdle() {
1117
- this._flushTimer.emitWhenIdle();
1118
- }
1119
1115
  _handleGetStateTimeout = (msgId) => {
1120
1116
  const pending = this._session.pendingGetStateTimeouts.get(msgId);
1121
1117
  if (!pending) {
@@ -1125,13 +1121,12 @@ class SessionConnection extends persistentConnection.PersistentConnection {
1125
1121
  this._onMessageFailed(msgId, "timeout");
1126
1122
  };
1127
1123
  _flush() {
1128
- if (this._disconnectedManually || !this._session._authKey.ready || this._isPfsBindingPending || this._session.current429Timeout) {
1124
+ if (this._disconnectedManually || !this._session._authKey.ready || this._isPfsBindingPending) {
1129
1125
  this.log.debug(
1130
- "skipping flush, connection is not usable (offline = %b, auth key ready = %b, pfs binding pending = %b, 429 timeout = %b)",
1126
+ "skipping flush, connection is not usable (offline = %b, auth key ready = %b, pfs binding pending = %b)",
1131
1127
  this._disconnectedManually,
1132
1128
  this._session._authKey.ready,
1133
- this._isPfsBindingPending,
1134
- this._session.current429Timeout
1129
+ this._isPfsBindingPending
1135
1130
  );
1136
1131
  return;
1137
1132
  }
@@ -43,7 +43,6 @@ export declare class SessionConnection extends PersistentConnection {
43
43
  readonly onDisconnect: Emitter<void>;
44
44
  readonly onKeyChange: Emitter<Uint8Array | null>;
45
45
  readonly onTmpKeyChange: Emitter<[Uint8Array, number] | null>;
46
- readonly onFloodDone: Emitter<void>;
47
46
  readonly onRequestAuth: Emitter<void>;
48
47
  readonly onAuthBegin: Emitter<void>;
49
48
  readonly onUpdate: Emitter<tl.TypeUpdates>;
@@ -87,7 +86,6 @@ export declare class SessionConnection extends PersistentConnection {
87
86
  notifyNetworkChanged(online: boolean): void;
88
87
  private _cancelRpc;
89
88
  protected _onInactivityTimeout(): void;
90
- flushWhenIdle(): void;
91
89
  private _handleGetStateTimeout;
92
90
  private _flush;
93
91
  private _doFlush;
@@ -43,7 +43,6 @@ export declare class SessionConnection extends PersistentConnection {
43
43
  readonly onDisconnect: Emitter<void>;
44
44
  readonly onKeyChange: Emitter<Uint8Array | null>;
45
45
  readonly onTmpKeyChange: Emitter<[Uint8Array, number] | null>;
46
- readonly onFloodDone: Emitter<void>;
47
46
  readonly onRequestAuth: Emitter<void>;
48
47
  readonly onAuthBegin: Emitter<void>;
49
48
  readonly onUpdate: Emitter<tl.TypeUpdates>;
@@ -87,7 +86,6 @@ export declare class SessionConnection extends PersistentConnection {
87
86
  notifyNetworkChanged(online: boolean): void;
88
87
  private _cancelRpc;
89
88
  protected _onInactivityTimeout(): void;
90
- flushWhenIdle(): void;
91
89
  private _handleGetStateTimeout;
92
90
  private _flush;
93
91
  private _doFlush;
@@ -41,7 +41,6 @@ class SessionConnection extends PersistentConnection {
41
41
  onDisconnect = new Emitter();
42
42
  onKeyChange = new Emitter();
43
43
  onTmpKeyChange = new Emitter();
44
- onFloodDone = new Emitter();
45
44
  onRequestAuth = new Emitter();
46
45
  onAuthBegin = new Emitter();
47
46
  onUpdate = new Emitter();
@@ -113,7 +112,6 @@ class SessionConnection extends PersistentConnection {
113
112
  this.onDisconnect.clear();
114
113
  this.onKeyChange.clear();
115
114
  this.onTmpKeyChange.clear();
116
- this.onFloodDone.clear();
117
115
  this.onRequestAuth.clear();
118
116
  this.onAuthBegin.clear();
119
117
  this.onUpdate.clear();
@@ -177,7 +175,7 @@ class SessionConnection extends PersistentConnection {
177
175
  this.log.error("transport error %d", error.code);
178
176
  this._onAllFailed(`transport error ${error.code}`);
179
177
  if (error.code === 429) {
180
- this._session.onTransportFlood(() => this.onFloodDone.emit());
178
+ this._floodControl?.addMtprotoError();
181
179
  return;
182
180
  }
183
181
  }
@@ -1049,6 +1047,7 @@ class SessionConnection extends PersistentConnection {
1049
1047
  notifyNetworkChanged(online) {
1050
1048
  this._online = online;
1051
1049
  if (online) {
1050
+ this._floodControl?.notifyNetworkUp();
1052
1051
  if (this._inactive) return;
1053
1052
  this.reconnect();
1054
1053
  } else {
@@ -1106,9 +1105,6 @@ class SessionConnection extends PersistentConnection {
1106
1105
  this._inactivityPendingFlush = true;
1107
1106
  this._flush();
1108
1107
  }
1109
- flushWhenIdle() {
1110
- this._flushTimer.emitWhenIdle();
1111
- }
1112
1108
  _handleGetStateTimeout = (msgId) => {
1113
1109
  const pending = this._session.pendingGetStateTimeouts.get(msgId);
1114
1110
  if (!pending) {
@@ -1118,13 +1114,12 @@ class SessionConnection extends PersistentConnection {
1118
1114
  this._onMessageFailed(msgId, "timeout");
1119
1115
  };
1120
1116
  _flush() {
1121
- if (this._disconnectedManually || !this._session._authKey.ready || this._isPfsBindingPending || this._session.current429Timeout) {
1117
+ if (this._disconnectedManually || !this._session._authKey.ready || this._isPfsBindingPending) {
1122
1118
  this.log.debug(
1123
- "skipping flush, connection is not usable (offline = %b, auth key ready = %b, pfs binding pending = %b, 429 timeout = %b)",
1119
+ "skipping flush, connection is not usable (offline = %b, auth key ready = %b, pfs binding pending = %b)",
1124
1120
  this._disconnectedManually,
1125
1121
  this._session._authKey.ready,
1126
- this._isPfsBindingPending,
1127
- this._session.current429Timeout
1122
+ this._isPfsBindingPending
1128
1123
  );
1129
1124
  return;
1130
1125
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mtcute/core",
3
3
  "type": "module",
4
- "version": "0.29.7",
4
+ "version": "0.30.0",
5
5
  "description": "Type-safe library for MTProto (Telegram API)",
6
6
  "license": "MIT",
7
7
  "scripts": {},