@mtcute/core 0.30.0 → 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.
- package/client.cjs +8 -0
- package/client.js +8 -0
- package/highlevel/client.d.cts +63 -1
- package/highlevel/client.d.ts +63 -1
- package/highlevel/methods/files/download-iterable.cjs +80 -45
- package/highlevel/methods/files/download-iterable.js +80 -45
- package/highlevel/methods/files/normalize-input-media.cjs +9 -1
- package/highlevel/methods/files/normalize-input-media.js +10 -2
- package/highlevel/methods/files/upload-file.cjs +6 -1
- package/highlevel/methods/files/upload-file.js +6 -1
- package/highlevel/methods/messages/create-rich-streaming-draft.cjs +39 -0
- package/highlevel/methods/messages/create-rich-streaming-draft.d.cts +42 -0
- package/highlevel/methods/messages/create-rich-streaming-draft.d.ts +42 -0
- package/highlevel/methods/messages/create-rich-streaming-draft.js +34 -0
- package/highlevel/methods/messages/normalize-rich-message.cjs +168 -0
- package/highlevel/methods/messages/normalize-rich-message.d.cts +10 -0
- package/highlevel/methods/messages/normalize-rich-message.d.ts +10 -0
- package/highlevel/methods/messages/normalize-rich-message.js +163 -0
- package/highlevel/methods/messages/send-common.cjs +3 -2
- package/highlevel/methods/messages/send-common.d.cts +4 -1
- package/highlevel/methods/messages/send-common.d.ts +4 -1
- package/highlevel/methods/messages/send-common.js +3 -2
- package/highlevel/methods/messages/send-rich-message.cjs +49 -0
- package/highlevel/methods/messages/send-rich-message.d.cts +38 -0
- package/highlevel/methods/messages/send-rich-message.d.ts +38 -0
- package/highlevel/methods/messages/send-rich-message.js +44 -0
- package/highlevel/methods.d.cts +3 -0
- package/highlevel/methods.d.ts +3 -0
- package/highlevel/types/bots/inline-message/factories.cjs +14 -0
- package/highlevel/types/bots/inline-message/factories.d.cts +9 -1
- package/highlevel/types/bots/inline-message/factories.d.ts +9 -1
- package/highlevel/types/bots/inline-message/factories.js +14 -0
- package/highlevel/types/bots/inline-message/types.d.cts +17 -1
- package/highlevel/types/bots/inline-message/types.d.ts +17 -1
- package/highlevel/types/files/utils.d.cts +9 -0
- package/highlevel/types/files/utils.d.ts +9 -0
- package/highlevel/types/media/input-media/types.d.cts +1 -1
- package/highlevel/types/media/input-media/types.d.ts +1 -1
- package/highlevel/types/messages/index.d.cts +1 -1
- package/highlevel/types/messages/index.d.ts +1 -1
- package/highlevel/types/messages/message.cjs +1 -1
- package/highlevel/types/messages/message.d.cts +1 -1
- package/highlevel/types/messages/message.d.ts +1 -1
- package/highlevel/types/messages/message.js +1 -1
- package/highlevel/types/messages/rich/index.d.cts +4 -0
- package/highlevel/types/messages/rich/index.d.ts +4 -0
- package/highlevel/types/messages/rich/inner.cjs +219 -0
- package/highlevel/types/messages/rich/inner.d.cts +127 -0
- package/highlevel/types/messages/rich/inner.d.ts +127 -0
- package/highlevel/types/messages/rich/inner.js +214 -0
- package/highlevel/types/messages/{rich-message.cjs → rich/rich-message.cjs} +6 -6
- package/highlevel/types/messages/{rich-message.d.cts → rich/rich-message.d.cts} +5 -5
- package/highlevel/types/messages/{rich-message.d.ts → rich/rich-message.d.ts} +5 -5
- package/highlevel/types/messages/{rich-message.js → rich/rich-message.js} +6 -6
- package/highlevel/types/messages/rich/types.d.cts +76 -0
- package/highlevel/types/messages/rich/types.d.ts +76 -0
- package/highlevel/updates/manager.cjs +10 -169
- package/highlevel/updates/manager.js +10 -169
- package/highlevel/utils/entities.cjs +176 -0
- package/highlevel/utils/entities.d.cts +18 -0
- package/highlevel/utils/entities.d.ts +18 -0
- package/highlevel/utils/entities.js +177 -1
- package/highlevel/utils/index.d.cts +1 -0
- package/highlevel/utils/index.d.ts +1 -0
- package/highlevel/utils/walk-page-blocks.cjs +164 -0
- package/highlevel/utils/walk-page-blocks.d.cts +9 -0
- package/highlevel/utils/walk-page-blocks.d.ts +9 -0
- package/highlevel/utils/walk-page-blocks.js +159 -0
- package/index.cjs +3 -1
- package/index.js +3 -1
- package/methods.cjs +4 -0
- package/methods.js +4 -0
- package/network/authorization.cjs +1 -1
- package/network/authorization.js +1 -1
- package/network/delay-gate.cjs +29 -0
- package/network/delay-gate.d.cts +5 -0
- package/network/delay-gate.d.ts +5 -0
- package/network/delay-gate.js +24 -0
- package/network/delay-gate.test.d.cts +1 -0
- package/network/delay-gate.test.d.ts +1 -0
- package/network/message-id-store.cjs +30 -0
- package/network/message-id-store.d.cts +7 -0
- package/network/message-id-store.d.ts +7 -0
- package/network/message-id-store.js +25 -0
- package/network/message-id-store.test.d.cts +1 -0
- package/network/message-id-store.test.d.ts +1 -0
- package/network/middlewares/bundle.cjs +2 -0
- package/network/middlewares/bundle.d.cts +1 -0
- package/network/middlewares/bundle.d.ts +1 -0
- package/network/middlewares/bundle.js +2 -0
- package/network/middlewares/default.cjs +6 -1
- package/network/middlewares/default.js +6 -1
- package/network/middlewares/flood-waiter.test.d.cts +1 -0
- package/network/middlewares/flood-waiter.test.d.ts +1 -0
- package/network/middlewares/internal-errors.test.d.cts +1 -0
- package/network/middlewares/internal-errors.test.d.ts +1 -0
- package/network/middlewares/media-throttle.cjs +65 -0
- package/network/middlewares/media-throttle.d.cts +5 -0
- package/network/middlewares/media-throttle.d.ts +5 -0
- package/network/middlewares/media-throttle.js +60 -0
- package/network/middlewares/media-throttle.test.d.cts +1 -0
- package/network/middlewares/media-throttle.test.d.ts +1 -0
- package/network/middlewares/on-error.test.d.cts +1 -0
- package/network/middlewares/on-error.test.d.ts +1 -0
- package/network/middlewares/on-method.test.d.cts +1 -0
- package/network/middlewares/on-method.test.d.ts +1 -0
- package/network/mtproto-session.cjs +9 -2
- package/network/mtproto-session.d.cts +5 -2
- package/network/mtproto-session.d.ts +5 -2
- package/network/mtproto-session.js +9 -2
- package/network/mtproxy/_fake-tls.cjs +169 -107
- package/network/mtproxy/_fake-tls.js +169 -107
- package/network/mtproxy/_fake-tls.test.d.cts +1 -0
- package/network/mtproxy/_fake-tls.test.d.ts +1 -0
- package/network/multi-session-connection.cjs +7 -0
- package/network/multi-session-connection.d.cts +2 -0
- package/network/multi-session-connection.d.ts +2 -0
- package/network/multi-session-connection.js +7 -0
- package/network/network-manager.cjs +7 -1
- package/network/network-manager.js +7 -1
- package/network/resource-limiter.cjs +60 -0
- package/network/resource-limiter.d.cts +11 -0
- package/network/resource-limiter.d.ts +11 -0
- package/network/resource-limiter.js +55 -0
- package/network/resource-limiter.test.d.cts +1 -0
- package/network/resource-limiter.test.d.ts +1 -0
- package/network/server-salt.cjs +7 -3
- package/network/server-salt.d.cts +2 -0
- package/network/server-salt.d.ts +2 -0
- package/network/server-salt.js +7 -3
- package/network/session-connection.cjs +106 -20
- package/network/session-connection.d.cts +11 -0
- package/network/session-connection.d.ts +11 -0
- package/network/session-connection.js +106 -20
- package/package.json +1 -1
- package/tl/api-schema.json +1 -1
- package/tl/binary/reader.cjs +115 -109
- package/tl/binary/reader.js +115 -109
- package/tl/binary/writer.cjs +243 -245
- package/tl/binary/writer.js +243 -245
- package/tl/index.d.cts +227 -216
- package/tl/index.d.ts +227 -216
- package/tl/inner-tl.cjs +3 -1
- package/tl/inner-tl.js +3 -1
- package/types/utils.d.cts +4 -0
- package/types/utils.d.ts +4 -0
- package/utils.cjs +4 -0
- package/utils.js +5 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Bytes, read } from "@fuman/io";
|
|
2
2
|
import { u8, typed, bigint } from "@fuman/utils";
|
|
3
3
|
const MAX_TLS_PACKET_LENGTH = 2878;
|
|
4
|
+
const MAX_TLS_HELLO_SIZE = 4096;
|
|
4
5
|
const KEY_MOD = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEDn;
|
|
5
6
|
const QUAD_RES_MOD = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEDn;
|
|
6
7
|
const QUAD_RES_POW = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6n;
|
|
@@ -27,7 +28,11 @@ function _isQuadraticResidue(a) {
|
|
|
27
28
|
return r === 1n;
|
|
28
29
|
}
|
|
29
30
|
function executeTlsOperations(h) {
|
|
30
|
-
h.string([22, 3, 1
|
|
31
|
+
h.string([22, 3, 1]);
|
|
32
|
+
h.beginScope();
|
|
33
|
+
h.string([1, 0]);
|
|
34
|
+
h.beginScope();
|
|
35
|
+
h.string([3, 3]);
|
|
31
36
|
h.zero(32);
|
|
32
37
|
h.string([32]);
|
|
33
38
|
h.random(32);
|
|
@@ -65,67 +70,34 @@ function executeTlsOperations(h) {
|
|
|
65
70
|
0,
|
|
66
71
|
53,
|
|
67
72
|
1,
|
|
68
|
-
0
|
|
69
|
-
1,
|
|
70
|
-
147
|
|
73
|
+
0
|
|
71
74
|
]);
|
|
72
|
-
h.grease(2);
|
|
73
|
-
h.string([0, 0, 0, 0]);
|
|
74
|
-
h.beginScope();
|
|
75
75
|
h.beginScope();
|
|
76
|
-
h.
|
|
77
|
-
h.
|
|
78
|
-
h.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
0,
|
|
102
|
-
0,
|
|
103
|
-
16,
|
|
104
|
-
0,
|
|
105
|
-
14,
|
|
106
|
-
0,
|
|
107
|
-
12,
|
|
108
|
-
2,
|
|
109
|
-
104,
|
|
110
|
-
50,
|
|
111
|
-
8,
|
|
112
|
-
104,
|
|
113
|
-
116,
|
|
114
|
-
116,
|
|
115
|
-
112,
|
|
116
|
-
47,
|
|
117
|
-
49,
|
|
118
|
-
46,
|
|
119
|
-
49,
|
|
120
|
-
0,
|
|
121
|
-
5,
|
|
122
|
-
0,
|
|
123
|
-
5,
|
|
124
|
-
1,
|
|
125
|
-
0,
|
|
126
|
-
0,
|
|
127
|
-
0,
|
|
128
|
-
0,
|
|
76
|
+
h.grease(2);
|
|
77
|
+
h.string([0, 0]);
|
|
78
|
+
h.permutation([
|
|
79
|
+
(w) => {
|
|
80
|
+
w.string([0, 0]);
|
|
81
|
+
w.beginScope();
|
|
82
|
+
w.beginScope();
|
|
83
|
+
w.string([0]);
|
|
84
|
+
w.beginScope();
|
|
85
|
+
w.domain();
|
|
86
|
+
w.endScope();
|
|
87
|
+
w.endScope();
|
|
88
|
+
w.endScope();
|
|
89
|
+
},
|
|
90
|
+
(w) => w.string([0, 5, 0, 5, 1, 0, 0, 0, 0]),
|
|
91
|
+
// status_request
|
|
92
|
+
(w) => {
|
|
93
|
+
w.string([0, 10, 0, 12, 0, 10]);
|
|
94
|
+
w.grease(4);
|
|
95
|
+
w.string([17, 236, 0, 29, 0, 23, 0, 24]);
|
|
96
|
+
},
|
|
97
|
+
(w) => w.string([0, 11, 0, 2, 1, 0]),
|
|
98
|
+
// ec_point_formats
|
|
99
|
+
(w) => w.string([
|
|
100
|
+
// signature_algorithms
|
|
129
101
|
0,
|
|
130
102
|
13,
|
|
131
103
|
0,
|
|
@@ -147,27 +119,76 @@ function executeTlsOperations(h) {
|
|
|
147
119
|
8,
|
|
148
120
|
6,
|
|
149
121
|
6,
|
|
150
|
-
1
|
|
122
|
+
1
|
|
123
|
+
]),
|
|
124
|
+
(w) => w.string([
|
|
125
|
+
// application_layer_protocol_negotiation (ALPN)
|
|
151
126
|
0,
|
|
152
|
-
|
|
153
|
-
0,
|
|
154
|
-
0,
|
|
155
|
-
0,
|
|
156
|
-
51,
|
|
127
|
+
16,
|
|
157
128
|
0,
|
|
158
|
-
|
|
129
|
+
14,
|
|
159
130
|
0,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
131
|
+
12,
|
|
132
|
+
2,
|
|
133
|
+
104,
|
|
134
|
+
50,
|
|
135
|
+
8,
|
|
136
|
+
104,
|
|
137
|
+
116,
|
|
138
|
+
116,
|
|
139
|
+
112,
|
|
140
|
+
47,
|
|
141
|
+
49,
|
|
142
|
+
46,
|
|
143
|
+
49
|
|
144
|
+
]),
|
|
145
|
+
(w) => w.string([0, 18, 0, 0]),
|
|
146
|
+
// signed_certificate_timestamp
|
|
147
|
+
(w) => w.string([0, 23, 0, 0]),
|
|
148
|
+
// extended_master_secret
|
|
149
|
+
(w) => w.string([0, 27, 0, 3, 2, 0, 2]),
|
|
150
|
+
// compress_certificate
|
|
151
|
+
(w) => w.string([0, 35, 0, 0]),
|
|
152
|
+
// session_ticket
|
|
153
|
+
(w) => {
|
|
154
|
+
w.string([0, 43, 0, 7, 6]);
|
|
155
|
+
w.grease(6);
|
|
156
|
+
w.string([3, 4, 3, 3]);
|
|
157
|
+
},
|
|
158
|
+
(w) => w.string([0, 45, 0, 2, 1, 1]),
|
|
159
|
+
// psk_key_exchange_modes
|
|
160
|
+
(w) => {
|
|
161
|
+
w.string([0, 51, 4, 239, 4, 237]);
|
|
162
|
+
w.grease(4);
|
|
163
|
+
w.string([0, 1, 0, 17, 236, 4, 192]);
|
|
164
|
+
w.mlKem768Key();
|
|
165
|
+
w.key();
|
|
166
|
+
w.string([0, 29, 0, 32]);
|
|
167
|
+
w.key();
|
|
168
|
+
},
|
|
169
|
+
(w) => w.string([68, 205, 0, 5, 0, 3, 2, 104, 50]),
|
|
170
|
+
// application_settings (ALPS)
|
|
171
|
+
(w) => {
|
|
172
|
+
w.string([254, 13]);
|
|
173
|
+
w.beginScope();
|
|
174
|
+
w.string([0, 0, 1, 0, 1]);
|
|
175
|
+
w.random(1);
|
|
176
|
+
w.string([0, 32]);
|
|
177
|
+
w.random(32);
|
|
178
|
+
w.beginScope();
|
|
179
|
+
w.echPayload();
|
|
180
|
+
w.endScope();
|
|
181
|
+
w.endScope();
|
|
182
|
+
},
|
|
183
|
+
(w) => w.string([255, 1, 0, 1, 0])
|
|
184
|
+
// renegotiation_info
|
|
185
|
+
]);
|
|
169
186
|
h.grease(3);
|
|
170
|
-
h.string([0, 1, 0
|
|
187
|
+
h.string([0, 1, 0]);
|
|
188
|
+
h.padding();
|
|
189
|
+
h.endScope();
|
|
190
|
+
h.endScope();
|
|
191
|
+
h.endScope();
|
|
171
192
|
}
|
|
172
193
|
function initGrease(crypto, size) {
|
|
173
194
|
const buf = crypto.randomBytes(size);
|
|
@@ -182,12 +203,12 @@ function initGrease(crypto, size) {
|
|
|
182
203
|
return buf;
|
|
183
204
|
}
|
|
184
205
|
class TlsHelloWriter {
|
|
185
|
-
constructor(crypto,
|
|
206
|
+
constructor(crypto, domain, grease) {
|
|
186
207
|
this.crypto = crypto;
|
|
187
208
|
this._domain = domain;
|
|
188
|
-
this.buf = u8.alloc(
|
|
209
|
+
this.buf = u8.alloc(MAX_TLS_HELLO_SIZE);
|
|
189
210
|
this.dv = typed.toDataView(this.buf);
|
|
190
|
-
this._grease = initGrease(this.crypto, 7);
|
|
211
|
+
this._grease = grease ?? initGrease(this.crypto, 7);
|
|
191
212
|
}
|
|
192
213
|
buf;
|
|
193
214
|
dv;
|
|
@@ -228,6 +249,24 @@ class TlsHelloWriter {
|
|
|
228
249
|
}
|
|
229
250
|
}
|
|
230
251
|
}
|
|
252
|
+
// fake X25519MLKEM768 hybrid keyshare's ml-kem-768 part: 384 coefficients
|
|
253
|
+
// (mod 3329) packed 3 bytes per 2 coefficients, followed by 32 random bytes
|
|
254
|
+
mlKem768Key() {
|
|
255
|
+
const rnd = this.crypto.randomBytes(384 * 8);
|
|
256
|
+
const dv = typed.toDataView(rnd);
|
|
257
|
+
for (let i = 0; i < 384; i++) {
|
|
258
|
+
const a = dv.getUint32(i * 8, true) % 3329;
|
|
259
|
+
const b = dv.getUint32(i * 8 + 4, true) % 3329;
|
|
260
|
+
this.buf[this.pos++] = a & 255;
|
|
261
|
+
this.buf[this.pos++] = (a >> 8) + ((b & 15) << 4);
|
|
262
|
+
this.buf[this.pos++] = b >> 4;
|
|
263
|
+
}
|
|
264
|
+
this.random(32);
|
|
265
|
+
}
|
|
266
|
+
// GREASE ECH payload: random bytes of length 144/176/208/240
|
|
267
|
+
echPayload() {
|
|
268
|
+
this.random(this._randomInt(4) * 32 + 144);
|
|
269
|
+
}
|
|
231
270
|
beginScope() {
|
|
232
271
|
this._scopes.push(this.pos);
|
|
233
272
|
this.pos += 2;
|
|
@@ -237,29 +276,55 @@ class TlsHelloWriter {
|
|
|
237
276
|
if (begin === void 0) {
|
|
238
277
|
throw new Error("endScope called without beginScope");
|
|
239
278
|
}
|
|
240
|
-
|
|
241
|
-
const size = end - begin - 2;
|
|
242
|
-
this.dv.setUint16(begin, size);
|
|
279
|
+
this.dv.setUint16(begin, this.pos - begin - 2);
|
|
243
280
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
281
|
+
// render each part into its own buffer, then emit them in random order —
|
|
282
|
+
// mimics chrome's per-connection tls extension shuffling
|
|
283
|
+
permutation(parts) {
|
|
284
|
+
const rendered = parts.map((fn) => {
|
|
285
|
+
const sub = new TlsHelloWriter(this.crypto, this._domain, this._grease);
|
|
286
|
+
fn(sub);
|
|
287
|
+
return sub.buf.subarray(0, sub.pos);
|
|
288
|
+
});
|
|
289
|
+
for (let i = rendered.length - 1; i > 0; i--) {
|
|
290
|
+
const j = this._randomInt(i + 1);
|
|
291
|
+
const tmp = rendered[i];
|
|
292
|
+
rendered[i] = rendered[j];
|
|
293
|
+
rendered[j] = tmp;
|
|
294
|
+
}
|
|
295
|
+
for (const part of rendered) {
|
|
296
|
+
this.string(part);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// tls padding extension, only emitted for hellos smaller than 513 bytes
|
|
300
|
+
padding() {
|
|
301
|
+
if (this.pos >= 513) return;
|
|
302
|
+
const size = 513 - this.pos;
|
|
303
|
+
this.string([0, 21]);
|
|
247
304
|
this.beginScope();
|
|
248
|
-
this.zero(
|
|
305
|
+
this.zero(size);
|
|
249
306
|
this.endScope();
|
|
250
|
-
|
|
307
|
+
}
|
|
308
|
+
_randomInt(max) {
|
|
309
|
+
return typed.toDataView(this.crypto.randomBytes(4)).getUint32(0, true) % max;
|
|
310
|
+
}
|
|
311
|
+
async finish(secret) {
|
|
312
|
+
const data = this.buf.subarray(0, this.pos);
|
|
313
|
+
const unixTime = ~~(Date.now() / 1e3);
|
|
314
|
+
const hash = await this.crypto.hmacSha256(data, secret);
|
|
251
315
|
const dv = typed.toDataView(hash);
|
|
252
316
|
const old = dv.getInt32(28, true);
|
|
253
317
|
dv.setInt32(28, old ^ unixTime, true);
|
|
254
|
-
|
|
255
|
-
return
|
|
318
|
+
data.set(hash, 11);
|
|
319
|
+
return data;
|
|
256
320
|
}
|
|
257
321
|
}
|
|
258
322
|
async function generateFakeTlsHeader(domain, secret, crypto) {
|
|
259
|
-
const writer = new TlsHelloWriter(crypto,
|
|
323
|
+
const writer = new TlsHelloWriter(crypto, domain);
|
|
260
324
|
executeTlsOperations(writer);
|
|
261
325
|
return writer.finish(secret);
|
|
262
326
|
}
|
|
327
|
+
const EMPTY_BYTES = Bytes.from(u8.empty);
|
|
263
328
|
class FakeTlsPacketCodec {
|
|
264
329
|
// protected _stream: Buffer = Buffer.alloc(0)
|
|
265
330
|
constructor(_inner) {
|
|
@@ -294,23 +359,20 @@ class FakeTlsPacketCodec {
|
|
|
294
359
|
}
|
|
295
360
|
async decode(reader, eof) {
|
|
296
361
|
if (eof) return null;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (!inner) {
|
|
310
|
-
reader.rewind(5 + length);
|
|
311
|
-
return null;
|
|
362
|
+
while (reader.available >= 5) {
|
|
363
|
+
const header = reader.readSync(3);
|
|
364
|
+
if (header[0] !== 23 || header[1] !== 3 || header[2] !== 3) {
|
|
365
|
+
throw new Error("Invalid TLS header");
|
|
366
|
+
}
|
|
367
|
+
const length = read.uint16be(reader);
|
|
368
|
+
if (reader.available < length) {
|
|
369
|
+
reader.rewind(5);
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
const inner = await this._inner.decode(Bytes.from(reader.readSync(length)), eof);
|
|
373
|
+
if (inner) return inner;
|
|
312
374
|
}
|
|
313
|
-
return
|
|
375
|
+
return this._inner.decode(EMPTY_BYTES, eof);
|
|
314
376
|
}
|
|
315
377
|
reset() {
|
|
316
378
|
this._isFirstTls = true;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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.
|
|
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.
|
|
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 {};
|
package/network/server-salt.cjs
CHANGED
|
@@ -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 =
|
|
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
|
|
37
|
+
}, (salt.validSince - this._getServerTime()) * 1e3);
|
|
34
38
|
}
|
|
35
39
|
_replaceAndScheduleNext() {
|
|
36
40
|
if (this._timer) utils.timers.clearTimeout(this._timer);
|
|
37
|
-
const now =
|
|
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?;
|
package/network/server-salt.d.ts
CHANGED
|
@@ -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?;
|
package/network/server-salt.js
CHANGED
|
@@ -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 =
|
|
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
|
|
30
|
+
}, (salt.validSince - this._getServerTime()) * 1e3);
|
|
27
31
|
}
|
|
28
32
|
_replaceAndScheduleNext() {
|
|
29
33
|
if (this._timer) timers.clearTimeout(this._timer);
|
|
30
|
-
const now =
|
|
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;
|