@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.
Files changed (117) hide show
  1. package/esm/4_constants.d.ts +1 -0
  2. package/esm/4_constants.d.ts.map +1 -1
  3. package/esm/4_constants.js +1 -0
  4. package/esm/client/0_client_abstract.d.ts +1 -1
  5. package/esm/client/0_client_abstract.d.ts.map +1 -1
  6. package/esm/client/0_client_abstract.js +2 -2
  7. package/esm/client/0_password.js +1 -1
  8. package/esm/client/0_utilities.d.ts +1 -1
  9. package/esm/client/0_utilities.d.ts.map +1 -1
  10. package/esm/client/0_utilities.js +4 -4
  11. package/esm/client/1_client_plain.d.ts +1 -1
  12. package/esm/client/1_client_plain.d.ts.map +1 -1
  13. package/esm/client/1_client_plain.js +27 -15
  14. package/esm/client/2_client_encrypted.d.ts +6 -3
  15. package/esm/client/2_client_encrypted.d.ts.map +1 -1
  16. package/esm/client/2_client_encrypted.js +157 -50
  17. package/esm/client/2_file_manager.js +7 -7
  18. package/esm/client/2_network_statistics_manager.d.ts +2 -2
  19. package/esm/client/2_network_statistics_manager.d.ts.map +1 -1
  20. package/esm/client/2_network_statistics_manager.js +13 -12
  21. package/esm/client/2_update_manager.d.ts.map +1 -1
  22. package/esm/client/2_update_manager.js +6 -1
  23. package/esm/client/6_client.d.ts +2 -0
  24. package/esm/client/6_client.d.ts.map +1 -1
  25. package/esm/client/6_client.js +14 -11
  26. package/esm/client/6_client_dispatcher.js +2 -2
  27. package/esm/connection/0_get_tls_header.js +5 -5
  28. package/esm/connection/1_connection_socks5.node.js +3 -3
  29. package/esm/connection/1_connection_tcp.node.js +3 -3
  30. package/esm/connection/1_connection_tls.node.js +3 -3
  31. package/esm/connection/1_connection_web_socket.js +4 -4
  32. package/esm/session/0_session_state.d.ts +1 -0
  33. package/esm/session/0_session_state.d.ts.map +1 -1
  34. package/esm/session/0_session_state.js +8 -4
  35. package/esm/session/1_session.d.ts +4 -3
  36. package/esm/session/1_session.d.ts.map +1 -1
  37. package/esm/session/1_session.js +8 -5
  38. package/esm/session/2_session_encrypted.d.ts +11 -6
  39. package/esm/session/2_session_encrypted.d.ts.map +1 -1
  40. package/esm/session/2_session_encrypted.js +22 -14
  41. package/esm/session/2_session_plain.js +2 -2
  42. package/esm/tl/1_tl_writer.js +5 -5
  43. package/esm/tl/2_message.js +1 -1
  44. package/esm/transport/1_transport_abridged.js +1 -1
  45. package/esm/transport/1_transport_intermediate.js +1 -1
  46. package/esm/transport/1_transport_provider.d.ts +2 -2
  47. package/esm/transport/1_transport_provider.d.ts.map +1 -1
  48. package/esm/transport/1_transport_provider.js +5 -5
  49. package/esm/transport/2_transport_provider_mtproxy.js +2 -2
  50. package/esm/transport/2_transport_provider_socks5.js +2 -2
  51. package/esm/transport/2_transport_provider_tcp.js +2 -2
  52. package/esm/transport/2_transport_provider_web_socket.js +3 -3
  53. package/esm/types/1_network_statistics.d.ts +1 -1
  54. package/esm/types/1_network_statistics.d.ts.map +1 -1
  55. package/esm/types/_file_id.js +1 -1
  56. package/esm/utilities/0_int.js +1 -1
  57. package/esm/utilities/1_auth.js +4 -4
  58. package/esm/utilities/1_crypto.js +7 -7
  59. package/package.json +1 -1
  60. package/script/4_constants.d.ts +1 -0
  61. package/script/4_constants.d.ts.map +1 -1
  62. package/script/4_constants.js +2 -1
  63. package/script/client/0_client_abstract.d.ts +1 -1
  64. package/script/client/0_client_abstract.d.ts.map +1 -1
  65. package/script/client/0_client_abstract.js +2 -2
  66. package/script/client/0_password.js +1 -1
  67. package/script/client/0_utilities.d.ts +1 -1
  68. package/script/client/0_utilities.d.ts.map +1 -1
  69. package/script/client/0_utilities.js +5 -5
  70. package/script/client/1_client_plain.d.ts +1 -1
  71. package/script/client/1_client_plain.d.ts.map +1 -1
  72. package/script/client/1_client_plain.js +26 -14
  73. package/script/client/2_client_encrypted.d.ts +6 -3
  74. package/script/client/2_client_encrypted.d.ts.map +1 -1
  75. package/script/client/2_client_encrypted.js +157 -50
  76. package/script/client/2_file_manager.js +7 -7
  77. package/script/client/2_network_statistics_manager.d.ts +2 -2
  78. package/script/client/2_network_statistics_manager.d.ts.map +1 -1
  79. package/script/client/2_network_statistics_manager.js +13 -12
  80. package/script/client/2_update_manager.d.ts.map +1 -1
  81. package/script/client/2_update_manager.js +6 -1
  82. package/script/client/6_client.d.ts +2 -0
  83. package/script/client/6_client.d.ts.map +1 -1
  84. package/script/client/6_client.js +14 -11
  85. package/script/client/6_client_dispatcher.js +2 -2
  86. package/script/connection/0_get_tls_header.js +5 -5
  87. package/script/connection/1_connection_socks5.node.js +3 -3
  88. package/script/connection/1_connection_tcp.node.js +3 -3
  89. package/script/connection/1_connection_tls.node.js +3 -3
  90. package/script/connection/1_connection_web_socket.js +4 -4
  91. package/script/session/0_session_state.d.ts +1 -0
  92. package/script/session/0_session_state.d.ts.map +1 -1
  93. package/script/session/0_session_state.js +8 -4
  94. package/script/session/1_session.d.ts +4 -3
  95. package/script/session/1_session.d.ts.map +1 -1
  96. package/script/session/1_session.js +8 -5
  97. package/script/session/2_session_encrypted.d.ts +11 -6
  98. package/script/session/2_session_encrypted.d.ts.map +1 -1
  99. package/script/session/2_session_encrypted.js +22 -14
  100. package/script/session/2_session_plain.js +2 -2
  101. package/script/tl/1_tl_writer.js +5 -5
  102. package/script/tl/2_message.js +1 -1
  103. package/script/transport/1_transport_abridged.js +1 -1
  104. package/script/transport/1_transport_intermediate.js +1 -1
  105. package/script/transport/1_transport_provider.d.ts +2 -2
  106. package/script/transport/1_transport_provider.d.ts.map +1 -1
  107. package/script/transport/1_transport_provider.js +5 -5
  108. package/script/transport/2_transport_provider_mtproxy.js +2 -2
  109. package/script/transport/2_transport_provider_socks5.js +2 -2
  110. package/script/transport/2_transport_provider_tcp.js +2 -2
  111. package/script/transport/2_transport_provider_web_socket.js +3 -3
  112. package/script/types/1_network_statistics.d.ts +1 -1
  113. package/script/types/1_network_statistics.d.ts.map +1 -1
  114. package/script/types/_file_id.js +1 -1
  115. package/script/utilities/0_int.js +1 -1
  116. package/script/utilities/1_auth.js +4 -4
  117. 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 { InputError } from "../0_errors.js";
22
- import { getLogger } from "../1_utilities.js";
23
- import { Api, Mtproto, X } from "../2_tl.js";
24
- import { ConnectionNotInited } from "../3_errors.js";
25
- import { APP_VERSION, DEVICE_MODEL, LANG_CODE, LANG_PACK, SYSTEM_LANG_CODE, SYSTEM_VERSION } from "../4_constants.js";
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 { isCdnFunction, repr } from "./0_utilities.js";
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
- #plain;
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
- #apiId;
42
- #appVersion;
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.#plain = new ClientPlain(dc, params);
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
- this.#apiId = apiId;
61
- this.#appVersion = params?.appVersion ?? APP_VERSION;
62
- this.#deviceModel = params?.deviceModel ?? DEVICE_MODEL;
63
- this.#langCode = params?.langCode ?? LANG_CODE;
64
- this.#langPack = params?.langPack ?? LANG_PACK;
65
- this.#systemLangCode = params?.systemLangCode ?? SYSTEM_LANG_CODE;
66
- this.#systemVersion = params?.systemVersion ?? SYSTEM_VERSION;
67
- this.#disableUpdates = params?.disableUpdates ?? false;
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.length) {
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 this.#plain.connect();
91
- const [authKey, serverSalt] = await this.#plain.createAuthKey();
92
- await this.setAuthKey(authKey);
93
- this.serverSalt = serverSalt;
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
- this.#plain.disconnect();
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
- await this.session.setAuthKey(authKey);
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
- #connectionInited = false;
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 && !isCdnFunction(function_)) {
219
+ if (this.#isAuthKeyBound && this.#params?.disableUpdates && !isMediaFunction(function_)) {
129
220
  function_ = { _: "invokeWithoutUpdates", query: function_ };
130
221
  }
131
- if (!this.#connectionInited) {
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.#connectionInited = false;
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.#connectionInited) {
262
- this.#connectionInited = true;
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.length > _a.#BIG_FILE_THRESHOLD : true;
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.length;
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.length) {
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.length;
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.length,
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.length < limit) {
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.length);
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
- cdn: {
29
+ media: {
30
30
  sent: number;
31
31
  received: number;
32
32
  };
33
33
  }>;
34
- getTransportReadWriteCallback(isCcdn: boolean): {
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;AAGH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAEtC,qBAAa,wBAAwB;;gBAIvB,CAAC,EAAE,CAAC;IAKV,oBAAoB;;;;;;;;;;IAmB1B,6BAA6B,CAAC,MAAM,EAAE,OAAO;sBAE3B,MAAM;uBAKL,MAAM;;CA2B1B"}
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, cdnRead, cdnWrite] = await Promise.all([
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(["netstat_cdn_read"]),
33
- this.#c.storage.get(["netstat_cdn_write"]),
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 cdn = {
40
- sent: Number(cdnWrite || 0),
41
- received: Number(cdnRead || 0),
40
+ const media = {
41
+ sent: Number(mediaWrite || 0),
42
+ received: Number(mediaRead || 0),
42
43
  };
43
- return { messages, cdn };
44
+ return { messages, media };
44
45
  }
45
46
  #pendingWrites = {};
46
- getTransportReadWriteCallback(isCcdn) {
47
+ getTransportReadWriteCallback(isMedia) {
47
48
  return {
48
49
  read: (count) => {
49
- const key = isCcdn ? "netstat_cdn_read" : "netstat_messages_read";
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 = isCcdn ? "netstat_cdn_write" : "netstat_messages_write";
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":"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"}
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
- throw err;
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)) {
@@ -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 {