@mtkruto/node 0.152.0 → 0.154.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.
- package/esm/4_constants.d.ts +1 -0
- package/esm/4_constants.d.ts.map +1 -1
- package/esm/4_constants.js +1 -0
- package/esm/client/0_client_abstract.d.ts +1 -1
- package/esm/client/0_client_abstract.d.ts.map +1 -1
- package/esm/client/0_client_abstract.js +2 -2
- package/esm/client/0_password.js +1 -1
- package/esm/client/0_utilities.d.ts +1 -1
- package/esm/client/0_utilities.d.ts.map +1 -1
- package/esm/client/0_utilities.js +4 -4
- package/esm/client/1_client_plain.d.ts +1 -1
- package/esm/client/1_client_plain.d.ts.map +1 -1
- package/esm/client/1_client_plain.js +27 -15
- package/esm/client/2_client_encrypted.d.ts +6 -3
- package/esm/client/2_client_encrypted.d.ts.map +1 -1
- package/esm/client/2_client_encrypted.js +157 -50
- package/esm/client/2_file_manager.js +7 -7
- package/esm/client/2_network_statistics_manager.d.ts +2 -2
- package/esm/client/2_network_statistics_manager.d.ts.map +1 -1
- package/esm/client/2_network_statistics_manager.js +13 -12
- package/esm/client/2_update_manager.d.ts.map +1 -1
- package/esm/client/2_update_manager.js +6 -1
- package/esm/client/6_client.d.ts +2 -0
- package/esm/client/6_client.d.ts.map +1 -1
- package/esm/client/6_client.js +14 -11
- package/esm/client/6_client_dispatcher.js +2 -2
- package/esm/connection/0_get_tls_header.js +5 -5
- package/esm/connection/1_connection_socks5.node.js +3 -3
- package/esm/connection/1_connection_tcp.node.js +3 -3
- package/esm/connection/1_connection_tls.node.js +3 -3
- package/esm/connection/1_connection_web_socket.js +4 -4
- package/esm/session/0_session_state.d.ts +1 -0
- package/esm/session/0_session_state.d.ts.map +1 -1
- package/esm/session/0_session_state.js +8 -4
- package/esm/session/1_session.d.ts +4 -3
- package/esm/session/1_session.d.ts.map +1 -1
- package/esm/session/1_session.js +8 -5
- package/esm/session/2_session_encrypted.d.ts +11 -6
- package/esm/session/2_session_encrypted.d.ts.map +1 -1
- package/esm/session/2_session_encrypted.js +22 -14
- package/esm/session/2_session_plain.js +2 -2
- package/esm/tl/1_tl_writer.js +5 -5
- package/esm/tl/2_message.js +1 -1
- package/esm/transport/1_transport_abridged.js +1 -1
- package/esm/transport/1_transport_intermediate.js +1 -1
- package/esm/transport/1_transport_provider.d.ts +2 -2
- package/esm/transport/1_transport_provider.d.ts.map +1 -1
- package/esm/transport/1_transport_provider.js +5 -5
- package/esm/transport/2_transport_provider_mtproxy.js +2 -2
- package/esm/transport/2_transport_provider_socks5.js +2 -2
- package/esm/transport/2_transport_provider_tcp.js +2 -2
- package/esm/transport/2_transport_provider_web_socket.js +3 -3
- package/esm/types/1_network_statistics.d.ts +1 -1
- package/esm/types/1_network_statistics.d.ts.map +1 -1
- package/esm/types/_file_id.js +1 -1
- package/esm/utilities/0_int.js +1 -1
- package/esm/utilities/1_auth.js +4 -4
- package/esm/utilities/1_crypto.js +7 -7
- package/package.json +1 -1
- package/script/4_constants.d.ts +1 -0
- package/script/4_constants.d.ts.map +1 -1
- package/script/4_constants.js +2 -1
- package/script/client/0_client_abstract.d.ts +1 -1
- package/script/client/0_client_abstract.d.ts.map +1 -1
- package/script/client/0_client_abstract.js +2 -2
- package/script/client/0_password.js +1 -1
- package/script/client/0_utilities.d.ts +1 -1
- package/script/client/0_utilities.d.ts.map +1 -1
- package/script/client/0_utilities.js +5 -5
- package/script/client/1_client_plain.d.ts +1 -1
- package/script/client/1_client_plain.d.ts.map +1 -1
- package/script/client/1_client_plain.js +26 -14
- package/script/client/2_client_encrypted.d.ts +6 -3
- package/script/client/2_client_encrypted.d.ts.map +1 -1
- package/script/client/2_client_encrypted.js +157 -50
- package/script/client/2_file_manager.js +7 -7
- package/script/client/2_network_statistics_manager.d.ts +2 -2
- package/script/client/2_network_statistics_manager.d.ts.map +1 -1
- package/script/client/2_network_statistics_manager.js +13 -12
- package/script/client/2_update_manager.d.ts.map +1 -1
- package/script/client/2_update_manager.js +6 -1
- package/script/client/6_client.d.ts +2 -0
- package/script/client/6_client.d.ts.map +1 -1
- package/script/client/6_client.js +14 -11
- package/script/client/6_client_dispatcher.js +2 -2
- package/script/connection/0_get_tls_header.js +5 -5
- package/script/connection/1_connection_socks5.node.js +3 -3
- package/script/connection/1_connection_tcp.node.js +3 -3
- package/script/connection/1_connection_tls.node.js +3 -3
- package/script/connection/1_connection_web_socket.js +4 -4
- package/script/session/0_session_state.d.ts +1 -0
- package/script/session/0_session_state.d.ts.map +1 -1
- package/script/session/0_session_state.js +8 -4
- package/script/session/1_session.d.ts +4 -3
- package/script/session/1_session.d.ts.map +1 -1
- package/script/session/1_session.js +8 -5
- package/script/session/2_session_encrypted.d.ts +11 -6
- package/script/session/2_session_encrypted.d.ts.map +1 -1
- package/script/session/2_session_encrypted.js +22 -14
- package/script/session/2_session_plain.js +2 -2
- package/script/tl/1_tl_writer.js +5 -5
- package/script/tl/2_message.js +1 -1
- package/script/transport/1_transport_abridged.js +1 -1
- package/script/transport/1_transport_intermediate.js +1 -1
- package/script/transport/1_transport_provider.d.ts +2 -2
- package/script/transport/1_transport_provider.d.ts.map +1 -1
- package/script/transport/1_transport_provider.js +5 -5
- package/script/transport/2_transport_provider_mtproxy.js +2 -2
- package/script/transport/2_transport_provider_socks5.js +2 -2
- package/script/transport/2_transport_provider_tcp.js +2 -2
- package/script/transport/2_transport_provider_web_socket.js +3 -3
- package/script/types/1_network_statistics.d.ts +1 -1
- package/script/types/1_network_statistics.d.ts.map +1 -1
- package/script/types/_file_id.js +1 -1
- package/script/utilities/0_int.js +1 -1
- package/script/utilities/1_auth.js +4 -4
- package/script/utilities/1_crypto.js +7 -7
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
19
19
|
*/
|
|
20
20
|
var _a;
|
|
21
|
-
import {
|
|
22
|
-
import { getLogger } from "../1_utilities.js";
|
|
23
|
-
import { Api, Mtproto, X } from "../2_tl.js";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
21
|
+
import { concat, delay, ige256Encrypt, SECOND } from "../0_deps.js";
|
|
22
|
+
import { drop, fromUnixTimestamp, getLogger, getRandomId, intFromBytes, mod, sha1, toUnixTimestamp } from "../1_utilities.js";
|
|
23
|
+
import { Api, Mtproto, serializeMessage, TLWriter, X } from "../2_tl.js";
|
|
24
|
+
import { APP_VERSION, DEVICE_MODEL, LANG_CODE, LANG_PACK, SYSTEM_LANG_CODE, SYSTEM_VERSION, TEMPORARY_AUTH_KEY_TTL } from "../4_constants.js";
|
|
25
|
+
import { ConnectionNotInited, InputError } from "../4_errors.js";
|
|
26
26
|
import { constructTelegramError } from "../4_errors.js";
|
|
27
27
|
import { SessionEncrypted, SessionError } from "../4_session.js";
|
|
28
28
|
import { ClientAbstract } from "./0_client_abstract.js";
|
|
29
|
-
import {
|
|
29
|
+
import { isMediaFunction, repr } from "./0_utilities.js";
|
|
30
30
|
import { ClientPlain } from "./1_client_plain.js";
|
|
31
31
|
// global ClientEncrypted ID counter for logs
|
|
32
32
|
let id = 0;
|
|
@@ -35,62 +35,146 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
35
35
|
static #AUTH_KEY_CREATION_MAX_TRIES = 10;
|
|
36
36
|
handlers = {};
|
|
37
37
|
#L;
|
|
38
|
-
#
|
|
38
|
+
#dc;
|
|
39
|
+
#apiId;
|
|
40
|
+
#params;
|
|
41
|
+
#authKey = new Uint8Array();
|
|
42
|
+
#authKeyId = 0n;
|
|
43
|
+
#temporaryAuthKey = new Uint8Array();
|
|
44
|
+
#temporaryAuthKeyExpiresIn = 0;
|
|
39
45
|
session;
|
|
40
46
|
#sentRequests = new Map();
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#deviceModel;
|
|
44
|
-
#langCode;
|
|
45
|
-
#langPack;
|
|
46
|
-
#systemLangCode;
|
|
47
|
-
#systemVersion;
|
|
48
|
-
#disableUpdates;
|
|
47
|
+
#isAuthKeyBound = false;
|
|
48
|
+
#isPerfectForwardSecrecyEnabled = false;
|
|
49
49
|
constructor(dc, apiId, params) {
|
|
50
50
|
super();
|
|
51
51
|
this.#L = getLogger("ClientEncrypted").client(id++);
|
|
52
|
-
this.#
|
|
52
|
+
this.#dc = dc;
|
|
53
|
+
this.#apiId = apiId;
|
|
54
|
+
this.#params = params;
|
|
55
|
+
this.#isPerfectForwardSecrecyEnabled = params?.isPerfectForwardSecrecyEnabled ?? false;
|
|
53
56
|
this.session = new SessionEncrypted(dc, params);
|
|
57
|
+
this.session.handlers.onTransportError = this.#onTransportError.bind(this);
|
|
54
58
|
this.session.handlers.onUpdate = this.#onUpdate.bind(this);
|
|
55
59
|
this.session.handlers.onNewServerSalt = this.#onNewServerSalt.bind(this);
|
|
56
60
|
this.session.handlers.onMessageFailed = this.#onMessageFailed.bind(this);
|
|
57
61
|
this.session.handlers.onRpcError = this.#onRpcError.bind(this);
|
|
58
62
|
this.session.handlers.onRpcResult = this.#onRpcResult.bind(this);
|
|
59
63
|
this.session.handlers.onPong = this.#onPong.bind(this);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
}
|
|
65
|
+
async #encryptMessage(message) {
|
|
66
|
+
const payloadWriter = new TLWriter();
|
|
67
|
+
payloadWriter.writeInt64(getRandomId());
|
|
68
|
+
payloadWriter.writeInt64(getRandomId());
|
|
69
|
+
payloadWriter.write(await serializeMessage(message));
|
|
70
|
+
let payload = payloadWriter.buffer;
|
|
71
|
+
const payloadSha1 = await sha1(payload);
|
|
72
|
+
const messageKey = payloadSha1.subarray(4, 20);
|
|
73
|
+
payloadWriter.write(new Uint8Array(mod(-payload.length, 16)));
|
|
74
|
+
payload = payloadWriter.buffer;
|
|
75
|
+
const sha1A = await sha1(concat([messageKey, this.#authKey.subarray(0, 32)]));
|
|
76
|
+
const sha1B = await sha1(concat([this.#authKey.slice(32, 48), messageKey, this.#authKey.slice(48, 64)]));
|
|
77
|
+
const sha1C = await sha1(concat([this.#authKey.slice(64, 96), messageKey]));
|
|
78
|
+
const sha1D = await sha1(concat([messageKey, this.#authKey.slice(96, 128)]));
|
|
79
|
+
const encryptionKey = concat([sha1A.slice(0, 8), sha1B.slice(8, 20), sha1C.slice(4, 16)]);
|
|
80
|
+
const encryptionIv = concat([sha1A.slice(8, 20), sha1B.slice(0, 8), sha1C.slice(16, 20), sha1D.slice(0, 8)]);
|
|
81
|
+
const encrypted = ige256Encrypt(payload, encryptionKey, encryptionIv);
|
|
82
|
+
const messageWriter = new TLWriter();
|
|
83
|
+
messageWriter.writeInt64(this.#authKeyId);
|
|
84
|
+
messageWriter.write(messageKey);
|
|
85
|
+
messageWriter.write(encrypted);
|
|
86
|
+
return messageWriter.buffer;
|
|
68
87
|
}
|
|
69
88
|
async connect() {
|
|
70
|
-
if (!this.authKey.
|
|
89
|
+
if (!this.authKey.byteLength) {
|
|
71
90
|
await this.#createAuthKey();
|
|
72
91
|
}
|
|
92
|
+
else if (this.#isPerfectForwardSecrecyEnabled) {
|
|
93
|
+
this.#L.debug("creating temporary auth key");
|
|
94
|
+
await this.#createAuthKeyInner(true);
|
|
95
|
+
}
|
|
73
96
|
await super.connect();
|
|
97
|
+
if (this.#isPerfectForwardSecrecyEnabled) {
|
|
98
|
+
this.#isAuthKeyBound = false;
|
|
99
|
+
await this.#bindTemporaryAuthKey();
|
|
100
|
+
drop(this.#refreshTemporaryAuthKey());
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
this.#isAuthKeyBound = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async #bindTemporaryAuthKey() {
|
|
107
|
+
const nonce = getRandomId();
|
|
108
|
+
const expires_at = toUnixTimestamp(new Date()) + TEMPORARY_AUTH_KEY_TTL;
|
|
109
|
+
this.#temporaryAuthKeyExpiresIn = fromUnixTimestamp(expires_at).getTime() - Date.now();
|
|
110
|
+
const object = {
|
|
111
|
+
_: "bind_auth_key_inner",
|
|
112
|
+
perm_auth_key_id: this.#authKeyId,
|
|
113
|
+
nonce,
|
|
114
|
+
expires_at,
|
|
115
|
+
temp_auth_key_id: this.session.authKeyId,
|
|
116
|
+
temp_session_id: this.session.id,
|
|
117
|
+
};
|
|
118
|
+
const encrypted_message = await this.#encryptMessage({
|
|
119
|
+
_: "message",
|
|
120
|
+
seqno: 0,
|
|
121
|
+
msg_id: this.session.previewNextMessageId(),
|
|
122
|
+
body: Mtproto.serializeObject(object),
|
|
123
|
+
});
|
|
124
|
+
await this.invoke({
|
|
125
|
+
_: "auth.bindTempAuthKey",
|
|
126
|
+
perm_auth_key_id: this.#authKeyId,
|
|
127
|
+
nonce,
|
|
128
|
+
encrypted_message,
|
|
129
|
+
expires_at,
|
|
130
|
+
}), this.#isAuthKeyBound = true;
|
|
131
|
+
}
|
|
132
|
+
#temporaryAuthKeyTimeoutController;
|
|
133
|
+
async #refreshTemporaryAuthKey() {
|
|
134
|
+
this.#temporaryAuthKeyTimeoutController?.abort();
|
|
135
|
+
const controller = this.#temporaryAuthKeyTimeoutController = new AbortController();
|
|
136
|
+
await delay(Math.max(0, this.#temporaryAuthKeyExpiresIn - 5 * SECOND), { signal: controller.signal });
|
|
137
|
+
if (this.#temporaryAuthKeyTimeoutController !== controller) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.#temporaryAuthKeyTimeoutController = undefined;
|
|
141
|
+
this.#L.debug("reconnecting with a new temporary auth key");
|
|
142
|
+
this.disconnect();
|
|
143
|
+
drop(this.connect());
|
|
74
144
|
}
|
|
75
145
|
disconnect() {
|
|
76
146
|
super.disconnect();
|
|
147
|
+
this.#temporaryAuthKeyTimeoutController?.abort();
|
|
148
|
+
this.#temporaryAuthKeyTimeoutController = undefined;
|
|
77
149
|
this.lastRequest = undefined;
|
|
78
150
|
}
|
|
79
151
|
#createAuthKeyPromise;
|
|
80
152
|
#createAuthKey() {
|
|
81
|
-
return this.#createAuthKeyPromise ??= this.#createAuthKeyInner().finally(() => {
|
|
153
|
+
return this.#createAuthKeyPromise ??= (this.#isPerfectForwardSecrecyEnabled ? Promise.all([this.#createAuthKeyInner(false), this.#createAuthKeyInner(true)]) : this.#createAuthKeyInner(false)).finally(() => {
|
|
82
154
|
this.#createAuthKeyPromise = undefined;
|
|
83
155
|
});
|
|
84
156
|
}
|
|
85
|
-
async #createAuthKeyInner() {
|
|
157
|
+
async #createAuthKeyInner(isTemporary) {
|
|
86
158
|
let lastErr;
|
|
87
159
|
let errored = false;
|
|
160
|
+
const plain = new ClientPlain(this.#dc, this.#params);
|
|
88
161
|
for (let i = 0; i < _a.#AUTH_KEY_CREATION_MAX_TRIES; ++i) {
|
|
89
162
|
try {
|
|
90
|
-
await
|
|
91
|
-
const [authKey, serverSalt] = await
|
|
92
|
-
|
|
93
|
-
|
|
163
|
+
await plain.connect();
|
|
164
|
+
const [authKey, serverSalt] = await plain.createAuthKey(isTemporary);
|
|
165
|
+
if (isTemporary) {
|
|
166
|
+
this.#temporaryAuthKey = authKey;
|
|
167
|
+
await this.session.setAuthKey(this.#temporaryAuthKey);
|
|
168
|
+
this.session.serverSalt = serverSalt;
|
|
169
|
+
this.#isConnectionInited = false;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
await this.setAuthKey(authKey);
|
|
173
|
+
}
|
|
174
|
+
if (!this.#isPerfectForwardSecrecyEnabled) {
|
|
175
|
+
await this.session.setAuthKey(authKey);
|
|
176
|
+
this.session.serverSalt = serverSalt;
|
|
177
|
+
}
|
|
94
178
|
errored = false;
|
|
95
179
|
break;
|
|
96
180
|
}
|
|
@@ -103,7 +187,7 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
103
187
|
this.#L.error("failed to create auth key:", err);
|
|
104
188
|
}
|
|
105
189
|
finally {
|
|
106
|
-
|
|
190
|
+
plain.disconnect();
|
|
107
191
|
}
|
|
108
192
|
}
|
|
109
193
|
if (errored) {
|
|
@@ -111,12 +195,19 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
111
195
|
}
|
|
112
196
|
}
|
|
113
197
|
get authKey() {
|
|
114
|
-
return this.session.authKey;
|
|
198
|
+
return this.#isPerfectForwardSecrecyEnabled ? this.#authKey : this.session.authKey;
|
|
115
199
|
}
|
|
116
200
|
async setAuthKey(authKey) {
|
|
117
|
-
|
|
201
|
+
if (this.#isPerfectForwardSecrecyEnabled) {
|
|
202
|
+
const hash = await sha1(authKey);
|
|
203
|
+
this.#authKeyId = intFromBytes(hash.slice(-8));
|
|
204
|
+
this.#authKey = authKey;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
await this.session.setAuthKey(authKey);
|
|
208
|
+
}
|
|
118
209
|
}
|
|
119
|
-
#
|
|
210
|
+
#isConnectionInited = false;
|
|
120
211
|
lastRequest;
|
|
121
212
|
async #send(function_) {
|
|
122
213
|
this.lastRequest = new Date();
|
|
@@ -125,27 +216,27 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
125
216
|
body = Mtproto.serializeObject(function_);
|
|
126
217
|
}
|
|
127
218
|
else {
|
|
128
|
-
if (this.#disableUpdates && !
|
|
219
|
+
if (this.#isAuthKeyBound && this.#params?.disableUpdates && !isMediaFunction(function_)) {
|
|
129
220
|
function_ = { _: "invokeWithoutUpdates", query: function_ };
|
|
130
221
|
}
|
|
131
|
-
if (!this.#
|
|
222
|
+
if (this.#isAuthKeyBound && !this.#isConnectionInited) {
|
|
132
223
|
if (!this.#apiId) {
|
|
133
224
|
throw new InputError("apiId not set");
|
|
134
225
|
}
|
|
135
226
|
function_ = {
|
|
136
227
|
_: "initConnection",
|
|
137
228
|
api_id: this.#apiId,
|
|
138
|
-
app_version: this.#appVersion,
|
|
139
|
-
device_model: this.#deviceModel,
|
|
140
|
-
lang_code: this.#langCode,
|
|
141
|
-
lang_pack: this.#langPack,
|
|
229
|
+
app_version: this.#params?.appVersion ?? APP_VERSION,
|
|
230
|
+
device_model: this.#params?.deviceModel ?? DEVICE_MODEL,
|
|
231
|
+
lang_code: this.#params?.langCode ?? LANG_CODE,
|
|
232
|
+
lang_pack: this.#params?.langPack ?? LANG_PACK,
|
|
142
233
|
query: {
|
|
143
234
|
_: "invokeWithLayer",
|
|
144
235
|
layer: Api.LAYER,
|
|
145
236
|
query: function_,
|
|
146
237
|
},
|
|
147
|
-
system_lang_code: this.#systemLangCode,
|
|
148
|
-
system_version: this.#systemVersion,
|
|
238
|
+
system_lang_code: this.#params?.systemLangCode ?? SYSTEM_LANG_CODE,
|
|
239
|
+
system_version: this.#params?.systemVersion ?? SYSTEM_VERSION,
|
|
149
240
|
};
|
|
150
241
|
}
|
|
151
242
|
body = Api.serializeObject(function_);
|
|
@@ -190,6 +281,17 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
190
281
|
this.#sentRequests.set(messageId, sentRequest);
|
|
191
282
|
return await sentRequest.promiseWithResolvers.promise;
|
|
192
283
|
}
|
|
284
|
+
async #onTransportError(transportError) {
|
|
285
|
+
this.#L.error("transport error:", transportError);
|
|
286
|
+
if (!this.#isPerfectForwardSecrecyEnabled) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (transportError.code === -404) {
|
|
290
|
+
this.#L.debug("reconnecting with a new temporary auth key");
|
|
291
|
+
this.disconnect();
|
|
292
|
+
await this.connect();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
193
295
|
async #onUpdate(body) {
|
|
194
296
|
let type;
|
|
195
297
|
try {
|
|
@@ -197,18 +299,18 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
197
299
|
}
|
|
198
300
|
catch (err) {
|
|
199
301
|
this.#L.error("failed to deserialize update:", err);
|
|
200
|
-
this.handlers.onDeserializationError?.();
|
|
302
|
+
await this.handlers.onDeserializationError?.();
|
|
201
303
|
return;
|
|
202
304
|
}
|
|
203
305
|
if (Api.isOfEnum("Update", type) || Api.isOfEnum("Updates", type)) {
|
|
204
|
-
this.handlers.onUpdate?.(type);
|
|
306
|
+
await this.handlers.onUpdate?.(type);
|
|
205
307
|
}
|
|
206
308
|
else {
|
|
207
309
|
this.#L.warning("received unknown type:", repr(type));
|
|
208
310
|
}
|
|
209
311
|
}
|
|
210
312
|
#onNewServerSalt(serverSalt) {
|
|
211
|
-
this.handlers.onNewServerSalt?.(serverSalt);
|
|
313
|
+
drop(this.handlers.onNewServerSalt?.(serverSalt));
|
|
212
314
|
}
|
|
213
315
|
async #onMessageFailed(msgId, error) {
|
|
214
316
|
const request = this.#sentRequests.get(msgId);
|
|
@@ -223,13 +325,18 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
223
325
|
}
|
|
224
326
|
}
|
|
225
327
|
async #onRpcError(msgId, error) {
|
|
328
|
+
if (error.error_message === "AUTH_KEY_PERM_EMPTY" || error.error_message === "ENCRYPTED_MESSAGE_INVALID") {
|
|
329
|
+
this.#L.debug("reconnecting with a new temporary auth key because of", error.error_message);
|
|
330
|
+
this.disconnect();
|
|
331
|
+
await this.connect();
|
|
332
|
+
}
|
|
226
333
|
const request = this.#sentRequests.get(msgId);
|
|
227
334
|
this.#L.debug("received rpc_error with req_msg_id =", msgId, "for", request === undefined ? "unknown" : "known", "request");
|
|
228
335
|
if (request) {
|
|
229
336
|
this.#sentRequests.delete(msgId);
|
|
230
337
|
const reason = constructTelegramError(error, request.call);
|
|
231
338
|
if (reason instanceof ConnectionNotInited) {
|
|
232
|
-
this.#
|
|
339
|
+
this.#isConnectionInited = false;
|
|
233
340
|
await this.#resend(request);
|
|
234
341
|
}
|
|
235
342
|
else {
|
|
@@ -251,15 +358,15 @@ export class ClientEncrypted extends ClientAbstract {
|
|
|
251
358
|
catch (err) {
|
|
252
359
|
sentRequest.promiseWithResolvers.reject(err);
|
|
253
360
|
this.#L.error("failed to deserialize rpc_result body:", err);
|
|
254
|
-
this.handlers.onDeserializationError?.();
|
|
361
|
+
await this.handlers.onDeserializationError?.();
|
|
255
362
|
return;
|
|
256
363
|
}
|
|
257
364
|
finally {
|
|
258
365
|
this.#sentRequests.delete(msgId);
|
|
259
366
|
}
|
|
260
367
|
}
|
|
261
|
-
if (!this.#
|
|
262
|
-
this.#
|
|
368
|
+
if (!this.#isConnectionInited) {
|
|
369
|
+
this.#isConnectionInited = true;
|
|
263
370
|
}
|
|
264
371
|
}
|
|
265
372
|
#onPong(pong) {
|
|
@@ -67,7 +67,7 @@ export class FileManager {
|
|
|
67
67
|
_a.validateChunkSize(chunkSize, _a.#UPLOAD_MAX_CHUNK_SIZE);
|
|
68
68
|
const mustTrackProgress = params?.progressId !== undefined;
|
|
69
69
|
const fileId = params?.progressId !== undefined ? BigInt(params.progressId) : getRandomId();
|
|
70
|
-
const isBig = contents instanceof Uint8Array ? contents.
|
|
70
|
+
const isBig = contents instanceof Uint8Array ? contents.byteLength > _a.#BIG_FILE_THRESHOLD : true;
|
|
71
71
|
const whatIsUploaded = contents instanceof Uint8Array ? (isBig ? "big file" : "file") + " of size " + size : "stream";
|
|
72
72
|
this.#Lupload.debug("uploading " + whatIsUploaded + " with chunk size of " + chunkSize + " and pool size of " + poolSize + " and file ID of " + fileId);
|
|
73
73
|
let result;
|
|
@@ -104,7 +104,7 @@ export class FileManager {
|
|
|
104
104
|
}
|
|
105
105
|
promises.push(this.#uploadPart(fileId, part.totalParts, !part.isSmall, part.part, part.bytes, signal).then(() => {
|
|
106
106
|
if (mustTrackProgress) {
|
|
107
|
-
uploaded += part.bytes.
|
|
107
|
+
uploaded += part.bytes.byteLength;
|
|
108
108
|
this.#c.handleUpdate({
|
|
109
109
|
type: "uploadProgress",
|
|
110
110
|
uploadProgress: {
|
|
@@ -147,7 +147,7 @@ export class FileManager {
|
|
|
147
147
|
const start = part * chunkSize;
|
|
148
148
|
const end = start + chunkSize;
|
|
149
149
|
const bytes = buffer.subarray(start, end);
|
|
150
|
-
if (!bytes.
|
|
150
|
+
if (!bytes.byteLength) {
|
|
151
151
|
break main;
|
|
152
152
|
}
|
|
153
153
|
if (!started) {
|
|
@@ -162,13 +162,13 @@ export class FileManager {
|
|
|
162
162
|
}
|
|
163
163
|
promises.push(this.#uploadPart(fileId, partCount, isBig, part++, bytes, signal).then(() => {
|
|
164
164
|
if (mustTrackProgress) {
|
|
165
|
-
uploaded += bytes.
|
|
165
|
+
uploaded += bytes.byteLength;
|
|
166
166
|
this.#c.handleUpdate({
|
|
167
167
|
type: "uploadProgress",
|
|
168
168
|
uploadProgress: {
|
|
169
169
|
id: String(fileId),
|
|
170
170
|
uploaded,
|
|
171
|
-
total: buffer.
|
|
171
|
+
total: buffer.byteLength,
|
|
172
172
|
isUploaded: false,
|
|
173
173
|
},
|
|
174
174
|
});
|
|
@@ -364,7 +364,7 @@ export class FileManager {
|
|
|
364
364
|
signal?.throwIfAborted();
|
|
365
365
|
}
|
|
366
366
|
++part;
|
|
367
|
-
if (file.bytes.
|
|
367
|
+
if (file.bytes.byteLength < limit) {
|
|
368
368
|
if (id !== null) {
|
|
369
369
|
await this.#c.storage.setFilePartCount(id, part + 1, chunkSize);
|
|
370
370
|
signal?.throwIfAborted();
|
|
@@ -372,7 +372,7 @@ export class FileManager {
|
|
|
372
372
|
break;
|
|
373
373
|
}
|
|
374
374
|
else {
|
|
375
|
-
offset += BigInt(file.bytes.
|
|
375
|
+
offset += BigInt(file.bytes.byteLength);
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
378
|
else {
|
|
@@ -26,12 +26,12 @@ export declare class NetworkStatisticsManager {
|
|
|
26
26
|
sent: number;
|
|
27
27
|
received: number;
|
|
28
28
|
};
|
|
29
|
-
|
|
29
|
+
media: {
|
|
30
30
|
sent: number;
|
|
31
31
|
received: number;
|
|
32
32
|
};
|
|
33
33
|
}>;
|
|
34
|
-
getTransportReadWriteCallback(
|
|
34
|
+
getTransportReadWriteCallback(isMedia: boolean): {
|
|
35
35
|
read: (count: number) => void;
|
|
36
36
|
write: (count: number) => void;
|
|
37
37
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"2_network_statistics_manager.d.ts","sourceRoot":"","sources":["../../src/client/2_network_statistics_manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"2_network_statistics_manager.d.ts","sourceRoot":"","sources":["../../src/client/2_network_statistics_manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAEtC,qBAAa,wBAAwB;;gBAIvB,CAAC,EAAE,CAAC;IAKV,oBAAoB;;;;;;;;;;IAmB1B,6BAA6B,CAAC,OAAO,EAAE,OAAO;sBAE5B,MAAM;uBAKL,MAAM;;CA2B1B"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* You should have received a copy of the GNU Lesser General Public License
|
|
18
18
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
19
19
|
*/
|
|
20
|
+
import { drop } from "../utilities/0_misc.js";
|
|
20
21
|
import { getLogger } from "../utilities/1_logger.js";
|
|
21
22
|
export class NetworkStatisticsManager {
|
|
22
23
|
#c;
|
|
@@ -26,34 +27,34 @@ export class NetworkStatisticsManager {
|
|
|
26
27
|
this.#L = getLogger("NetworkStatisticsManager");
|
|
27
28
|
}
|
|
28
29
|
async getNetworkStatistics() {
|
|
29
|
-
const [messagesRead, messagesWrite,
|
|
30
|
+
const [messagesRead, messagesWrite, mediaRead, mediaWrite] = await Promise.all([
|
|
30
31
|
this.#c.storage.get(["netstat_messages_read"]),
|
|
31
32
|
this.#c.storage.get(["netstat_messages_write"]),
|
|
32
|
-
this.#c.storage.get(["
|
|
33
|
-
this.#c.storage.get(["
|
|
33
|
+
this.#c.storage.get(["netstat_media_read"]),
|
|
34
|
+
this.#c.storage.get(["netstat_media_write"]),
|
|
34
35
|
]);
|
|
35
36
|
const messages = {
|
|
36
37
|
sent: Number(messagesWrite || 0),
|
|
37
38
|
received: Number(messagesRead || 0),
|
|
38
39
|
};
|
|
39
|
-
const
|
|
40
|
-
sent: Number(
|
|
41
|
-
received: Number(
|
|
40
|
+
const media = {
|
|
41
|
+
sent: Number(mediaWrite || 0),
|
|
42
|
+
received: Number(mediaRead || 0),
|
|
42
43
|
};
|
|
43
|
-
return { messages,
|
|
44
|
+
return { messages, media };
|
|
44
45
|
}
|
|
45
46
|
#pendingWrites = {};
|
|
46
|
-
getTransportReadWriteCallback(
|
|
47
|
+
getTransportReadWriteCallback(isMedia) {
|
|
47
48
|
return {
|
|
48
49
|
read: (count) => {
|
|
49
|
-
const key =
|
|
50
|
+
const key = isMedia ? "netstat_media_read" : "netstat_messages_read";
|
|
50
51
|
this.#pendingWrites[key] = (this.#pendingWrites[key] ?? 0) + count;
|
|
51
|
-
this.#write();
|
|
52
|
+
drop(this.#write());
|
|
52
53
|
},
|
|
53
54
|
write: (count) => {
|
|
54
|
-
const key =
|
|
55
|
+
const key = isMedia ? "netstat_media_write" : "netstat_messages_write";
|
|
55
56
|
this.#pendingWrites[key] = (this.#pendingWrites[key] ?? 0) + count;
|
|
56
|
-
this.#write();
|
|
57
|
+
drop(this.#write());
|
|
57
58
|
},
|
|
58
59
|
};
|
|
59
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"2_update_manager.d.ts","sourceRoot":"","sources":["../../src/client/2_update_manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EAAiC,KAAK,EAAmB,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAEtC,KAAK,aAAa,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAE/E,MAAM,MAAM,SAAS,GACjB,GAAG,CAAC,gBAAgB,GACpB,GAAG,CAAC,oBAAoB,GACxB,GAAG,CAAC,sBAAsB,GAC1B,GAAG,CAAC,uBAAuB,GAC3B,GAAG,CAAC,2BAA2B,GAC/B,GAAG,CAAC,oBAAoB,GACxB,GAAG,CAAC,iBAAiB,GACrB,GAAG,CAAC,oBAAoB,GACxB,GAAG,CAAC,iBAAiB,GACrB,GAAG,CAAC,0BAA0B,GAC9B,GAAG,CAAC,aAAa,CAAC;AAEtB,MAAM,MAAM,gBAAgB,GACxB,GAAG,CAAC,uBAAuB,GAC3B,GAAG,CAAC,wBAAwB,GAC5B,GAAG,CAAC,2BAA2B,GAC/B,GAAG,CAAC,oBAAoB,CAAC;AAE7B,MAAM,MAAM,SAAS,GACjB,GAAG,CAAC,yBAAyB,GAC7B,GAAG,CAAC,qBAAqB,GACzB,GAAG,CAAC,gBAAgB,GACpB,GAAG,CAAC,qBAAqB,GACzB,GAAG,CAAC,wBAAwB,GAC5B,GAAG,CAAC,4BAA4B,GAChC,GAAG,CAAC,kBAAkB,GACtB,GAAG,CAAC,wBAAwB,GAC5B,GAAG,CAAC,yBAAyB,GAC7B,GAAG,CAAC,wBAAwB,GAC5B,GAAG,CAAC,2BAA2B,GAC/B,GAAG,CAAC,4BAA4B,GAChC,GAAG,CAAC,8BAA8B,CAAC;AAEvC,qBAAa,aAAa;;IACxB,MAAM,CAAC,QAAQ,CAAC,SAAS,KAAK;IAC9B,MAAM,CAAC,QAAQ,CAAC,WAAW,MAAM;gBAarB,CAAC,EAAE,CAAC;IAYhB,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS;IAIjD,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS;IAIjD,MAAM,CAAC,kBAAkB,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,OAAO,GAAG,CAAC,IAAI,gBAAgB;IAuCvE,UAAU,CAAC,MAAM,EAAE,MAAM;IA0D/B,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,gBAAgB;IAM9D,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI;IAqBpB,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,gBAAgB;IAoDhD,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,gBAAgB;IAM9D,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI;IAsB1B,oBAAoB,CAAC,KAAK,EAAE,MAAM;IA6JlC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,GAAE,GAAG,CAAC,SAAS,GAAG,IAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI;IAsMvH,gBAAgB,CAAC,MAAM,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"2_update_manager.d.ts","sourceRoot":"","sources":["../../src/client/2_update_manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -624,7 +624,12 @@ export class UpdateManager {
|
|
|
624
624
|
continue;
|
|
625
625
|
}
|
|
626
626
|
else {
|
|
627
|
-
|
|
627
|
+
if (this.#c.isDisconnected()) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
throw err;
|
|
632
|
+
}
|
|
628
633
|
}
|
|
629
634
|
}
|
|
630
635
|
if (Api.is("updates.difference", difference) || Api.is("updates.differenceSlice", difference)) {
|
package/esm/client/6_client.d.ts
CHANGED
|
@@ -80,6 +80,8 @@ export interface ClientParams extends ClientPlainParams {
|
|
|
80
80
|
authString?: string;
|
|
81
81
|
/** The first DC to connect to. This is commonly used to decide whether to connect to test or production servers. It is not necessarily the DC that the client will directly connect to or is currently connected to. Defaults to the default initial DC. */
|
|
82
82
|
initialDc?: DC;
|
|
83
|
+
/** Whether perfect forward secrecy should be enabled. Defaults to `false`. */
|
|
84
|
+
isPerfectForwardSecrecyEnabled?: boolean;
|
|
83
85
|
}
|
|
84
86
|
/** An MTKruto client. */
|
|
85
87
|
export declare class Client<C extends Context = Context> extends Composer<C> implements ClientGeneric {
|