@mtkruto/node 0.0.835 → 0.0.901
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/client/client.d.ts +23 -3
- package/esm/client/client.js +497 -76
- package/esm/client/client_abstract.d.ts +2 -0
- package/esm/client/client_abstract.js +14 -3
- package/esm/client/client_plain.js +18 -4
- package/esm/constants.d.ts +7 -5
- package/esm/constants.js +10 -6
- package/esm/deps/deno.land/std@0.190.0/encoding/base64.d.ts +11 -0
- package/esm/deps/deno.land/std@0.190.0/encoding/base64.js +140 -0
- package/esm/deps/deno.land/x/q@v0.0.1/mod.d.ts +6 -0
- package/esm/deps/deno.land/x/q@v0.0.1/mod.js +71 -0
- package/esm/deps.d.ts +2 -0
- package/esm/deps.js +2 -0
- package/esm/mod.d.ts +3 -3
- package/esm/mod.js +3 -3
- package/esm/storage/storage.d.ts +18 -0
- package/esm/storage/storage.js +103 -0
- package/esm/tl/1_tl_object.d.ts +0 -1
- package/esm/tl/1_tl_object.js +1 -1
- package/esm/tl/4_tl_writer.d.ts +5 -0
- package/esm/tl/5_rpc_result.d.ts +9 -0
- package/esm/tl/6_message.d.ts +10 -0
- package/esm/tl/{5_message.js → 6_message.js} +2 -2
- package/esm/tl/{6_message_container.d.ts → 7_message_container.d.ts} +1 -1
- package/esm/tl/{6_message_container.js → 7_message_container.js} +2 -2
- package/esm/transport/transport_provider.d.ts +7 -4
- package/esm/transport/transport_provider.js +11 -8
- package/esm/types/3_message.d.ts +5 -1
- package/esm/types/3_message.js +26 -22
- package/esm/utilities/1_message.d.ts +2 -2
- package/esm/utilities/1_message.js +3 -3
- package/esm/utilities/1_password.js +1 -1
- package/package.json +1 -1
- package/script/client/client.d.ts +23 -3
- package/script/client/client.js +497 -76
- package/script/client/client_abstract.d.ts +2 -0
- package/script/client/client_abstract.js +14 -3
- package/script/client/client_plain.js +18 -4
- package/script/constants.d.ts +7 -5
- package/script/constants.js +34 -7
- package/script/deps/deno.land/std@0.190.0/encoding/base64.d.ts +11 -0
- package/script/deps/deno.land/std@0.190.0/encoding/base64.js +145 -0
- package/script/deps/deno.land/x/q@v0.0.1/mod.d.ts +6 -0
- package/script/deps/deno.land/x/q@v0.0.1/mod.js +75 -0
- package/script/deps.d.ts +2 -0
- package/script/deps.js +6 -1
- package/script/mod.d.ts +3 -3
- package/script/mod.js +3 -3
- package/script/storage/storage.d.ts +18 -0
- package/script/storage/storage.js +126 -0
- package/script/tl/1_tl_object.d.ts +0 -1
- package/script/tl/1_tl_object.js +1 -1
- package/script/tl/4_tl_writer.d.ts +5 -0
- package/script/tl/5_rpc_result.d.ts +9 -0
- package/script/tl/6_message.d.ts +10 -0
- package/script/tl/{5_message.js → 6_message.js} +6 -6
- package/script/tl/{6_message_container.d.ts → 7_message_container.d.ts} +1 -1
- package/script/tl/{6_message_container.js → 7_message_container.js} +4 -4
- package/script/transport/transport_provider.d.ts +7 -4
- package/script/transport/transport_provider.js +11 -8
- package/script/types/3_message.d.ts +5 -1
- package/script/types/3_message.js +26 -22
- package/script/utilities/1_message.d.ts +2 -2
- package/script/utilities/1_message.js +9 -9
- package/script/utilities/1_password.js +1 -1
- package/esm/tl/3_tl_writer.d.ts +0 -5
- package/esm/tl/4_rpc_result.d.ts +0 -8
- package/esm/tl/5_message.d.ts +0 -11
- package/script/tl/3_tl_writer.d.ts +0 -5
- package/script/tl/4_rpc_result.d.ts +0 -8
- package/script/tl/5_message.d.ts +0 -11
- /package/esm/tl/{3_tl_writer.js → 4_tl_writer.js} +0 -0
- /package/esm/tl/{4_rpc_result.js → 5_rpc_result.js} +0 -0
- /package/script/tl/{3_tl_writer.js → 4_tl_writer.js} +0 -0
- /package/script/tl/{4_rpc_result.js → 5_rpc_result.js} +0 -0
package/script/client/client.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.Client = exports.ParseMode = exports.restartAuth = void 0;
|
|
26
|
+
exports.Client = exports.ParseMode = exports.restartAuth = exports.getEntity = void 0;
|
|
27
27
|
const deps_js_1 = require("../deps.js");
|
|
28
28
|
const constants_js_1 = require("../constants.js");
|
|
29
29
|
const _0_bigint_js_1 = require("../utilities/0_bigint.js");
|
|
@@ -36,9 +36,9 @@ const _1_tl_object_js_1 = require("../tl/1_tl_object.js");
|
|
|
36
36
|
const types = __importStar(require("../tl/2_types.js"));
|
|
37
37
|
const functions = __importStar(require("../tl/3_functions.js"));
|
|
38
38
|
const _3_tl_reader_js_1 = require("../tl/3_tl_reader.js");
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
39
|
+
const _5_rpc_result_js_1 = require("../tl/5_rpc_result.js");
|
|
40
|
+
const _6_message_js_1 = require("../tl/6_message.js"); // MTProto API message
|
|
41
|
+
const _7_message_container_js_1 = require("../tl/7_message_container.js");
|
|
42
42
|
const client_abstract_js_1 = require("./client_abstract.js");
|
|
43
43
|
const client_plain_js_1 = require("./client_plain.js");
|
|
44
44
|
const storage_memory_js_1 = require("../storage/storage_memory.js");
|
|
@@ -47,8 +47,12 @@ const _0_reply_keyboard_remove_js_1 = require("../types/0_reply_keyboard_remove.
|
|
|
47
47
|
const _0_force_reply_js_1 = require("../types/0_force_reply.js");
|
|
48
48
|
const _2_reply_keyboard_markup_js_1 = require("../types/2_reply_keyboard_markup.js");
|
|
49
49
|
const _2_inline_keyboard_markup_js_1 = require("../types/2_inline_keyboard_markup.js");
|
|
50
|
-
const _3_message_js_1 = require("../types/3_message.js");
|
|
50
|
+
const _3_message_js_1 = require("../types/3_message.js"); // high-level wrapper for Telegram API's message
|
|
51
51
|
const d = (0, deps_js_1.debug)("client");
|
|
52
|
+
const dRecoverUpdateGap = (0, deps_js_1.debug)("client_recoverUpdateGap");
|
|
53
|
+
const dRecoverChannelUpdateGap = (0, deps_js_1.debug)("client_recoverChannelUpdateGap");
|
|
54
|
+
const UPDATE_GAP = Symbol();
|
|
55
|
+
exports.getEntity = Symbol();
|
|
52
56
|
exports.restartAuth = Symbol();
|
|
53
57
|
var ParseMode;
|
|
54
58
|
(function (ParseMode) {
|
|
@@ -114,7 +118,13 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
114
118
|
writable: true,
|
|
115
119
|
value: new Set()
|
|
116
120
|
});
|
|
117
|
-
Object.defineProperty(this, "
|
|
121
|
+
Object.defineProperty(this, "updateState", {
|
|
122
|
+
enumerable: true,
|
|
123
|
+
configurable: true,
|
|
124
|
+
writable: true,
|
|
125
|
+
value: void 0
|
|
126
|
+
});
|
|
127
|
+
Object.defineProperty(this, "updateHandler", {
|
|
118
128
|
enumerable: true,
|
|
119
129
|
configurable: true,
|
|
120
130
|
writable: true,
|
|
@@ -168,6 +178,79 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
168
178
|
writable: true,
|
|
169
179
|
value: false
|
|
170
180
|
});
|
|
181
|
+
Object.defineProperty(this, "messageProcessQueue", {
|
|
182
|
+
enumerable: true,
|
|
183
|
+
configurable: true,
|
|
184
|
+
writable: true,
|
|
185
|
+
value: (0, deps_js_1.queue)(async (message) => {
|
|
186
|
+
let body = message.body;
|
|
187
|
+
if (body instanceof types.GZIPPacked) {
|
|
188
|
+
body = new _3_tl_reader_js_1.TLReader((0, deps_js_1.gunzip)(body.packedData)).readObject();
|
|
189
|
+
}
|
|
190
|
+
d("received %s", body.constructor.name);
|
|
191
|
+
if (body instanceof types.Updates || body instanceof types.TypeUpdate) {
|
|
192
|
+
await this.processUpdates(body);
|
|
193
|
+
}
|
|
194
|
+
else if (message.body instanceof _5_rpc_result_js_1.RPCResult) {
|
|
195
|
+
let result = message.body.result;
|
|
196
|
+
if (result instanceof types.GZIPPacked) {
|
|
197
|
+
result = new _3_tl_reader_js_1.TLReader((0, deps_js_1.gunzip)(result.packedData)).readObject();
|
|
198
|
+
}
|
|
199
|
+
if (result instanceof types.RPCError) {
|
|
200
|
+
d("RPCResult: %d %s", result.errorCode, result.errorMessage);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
d("RPCResult: %s", result.constructor.name);
|
|
204
|
+
}
|
|
205
|
+
if (result instanceof types.Updates || result instanceof types.TypeUpdate) {
|
|
206
|
+
await this.processUpdates(result);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
await this.processResult(result);
|
|
210
|
+
}
|
|
211
|
+
const promise = this.promises.get(message.body.messageId);
|
|
212
|
+
if (promise) {
|
|
213
|
+
if (result instanceof types.RPCError) {
|
|
214
|
+
promise.reject(result);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
promise.resolve(result);
|
|
218
|
+
}
|
|
219
|
+
this.promises.delete(message.body.messageId);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else if (message.body instanceof types.Pong) {
|
|
223
|
+
const promise = this.promises.get(message.body.msgId);
|
|
224
|
+
if (promise) {
|
|
225
|
+
promise.resolve(message.body);
|
|
226
|
+
this.promises.delete(message.body.msgId);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
else if (message.body instanceof types.BadMsgNotification || message.body instanceof types.BadServerSalt) {
|
|
230
|
+
if (message.body instanceof types.BadServerSalt) {
|
|
231
|
+
this.state.salt = message.body.newServerSalt;
|
|
232
|
+
}
|
|
233
|
+
const promise = this.promises.get(message.body.badMsgId);
|
|
234
|
+
if (promise) {
|
|
235
|
+
promise.resolve(message.body);
|
|
236
|
+
this.promises.delete(message.body.badMsgId);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
this.toAcknowledge.add(message.id);
|
|
240
|
+
}, 2)
|
|
241
|
+
});
|
|
242
|
+
Object.defineProperty(this, "updateApplicationMutex", {
|
|
243
|
+
enumerable: true,
|
|
244
|
+
configurable: true,
|
|
245
|
+
writable: true,
|
|
246
|
+
value: new deps_js_1.Mutex()
|
|
247
|
+
});
|
|
248
|
+
Object.defineProperty(this, "updateGapRecoveryMutex", {
|
|
249
|
+
enumerable: true,
|
|
250
|
+
configurable: true,
|
|
251
|
+
writable: true,
|
|
252
|
+
value: new deps_js_1.Mutex()
|
|
253
|
+
});
|
|
171
254
|
this.parseMode = params?.parseMode ?? ParseMode.None;
|
|
172
255
|
this.appVersion = params?.appVersion ?? constants_js_1.DEFAULT_APP_VERSION;
|
|
173
256
|
this.deviceModel = params?.deviceModel ?? constants_js_1.DEFAULT_DEVICE_MODEL;
|
|
@@ -190,6 +273,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
190
273
|
if (await this.storage.getDc() != dc) {
|
|
191
274
|
await this.storage.setDc(dc);
|
|
192
275
|
await this.storage.setAuthKey(null);
|
|
276
|
+
await this.storage.getAuthKey();
|
|
193
277
|
}
|
|
194
278
|
super.setDc(dc);
|
|
195
279
|
}
|
|
@@ -231,12 +315,17 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
231
315
|
}
|
|
232
316
|
await super.connect();
|
|
233
317
|
if (dc == null) {
|
|
234
|
-
await this.storage.setDc(
|
|
318
|
+
await this.storage.setDc(this.transportProvider.initialDc);
|
|
235
319
|
}
|
|
236
320
|
d("enrypted client connected");
|
|
237
321
|
this.receiveLoop();
|
|
238
322
|
this.pingLoop();
|
|
239
323
|
}
|
|
324
|
+
async fetchState(source) {
|
|
325
|
+
const state = await this.invoke(new functions.UpdatesGetState());
|
|
326
|
+
this.updateState = state;
|
|
327
|
+
d("state fetched [%s]", source);
|
|
328
|
+
}
|
|
240
329
|
/**
|
|
241
330
|
* Calls [initConnection](1) and authorizes the client with one of the following:
|
|
242
331
|
*
|
|
@@ -286,6 +375,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
286
375
|
const password = typeof params.password === "string" ? params.password : await params.password();
|
|
287
376
|
const input = await (0, _1_password_js_1.checkPassword)(password, ap);
|
|
288
377
|
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
378
|
+
await this.storage.setAccountType("user");
|
|
289
379
|
d("authorized as user");
|
|
290
380
|
break;
|
|
291
381
|
}
|
|
@@ -308,7 +398,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
308
398
|
}
|
|
309
399
|
};
|
|
310
400
|
try {
|
|
311
|
-
await this.
|
|
401
|
+
await this.fetchState("authorize");
|
|
312
402
|
d("already authorized");
|
|
313
403
|
return;
|
|
314
404
|
}
|
|
@@ -349,6 +439,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
349
439
|
}
|
|
350
440
|
else {
|
|
351
441
|
signedIn = true;
|
|
442
|
+
await this.storage.setAccountType("user");
|
|
352
443
|
d("authorized as user");
|
|
353
444
|
break;
|
|
354
445
|
}
|
|
@@ -383,6 +474,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
383
474
|
}
|
|
384
475
|
else {
|
|
385
476
|
await this.invoke(new functions.AuthImportBotAuthorization({ apiId: this.apiId, apiHash: this.apiHash, botAuthToken: params, flags: 0 }));
|
|
477
|
+
await this.storage.setAccountType("bot");
|
|
386
478
|
d("authorized as bot");
|
|
387
479
|
}
|
|
388
480
|
}
|
|
@@ -410,6 +502,14 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
410
502
|
throw err;
|
|
411
503
|
}
|
|
412
504
|
}
|
|
505
|
+
finally {
|
|
506
|
+
try {
|
|
507
|
+
await this.fetchState("authorize");
|
|
508
|
+
}
|
|
509
|
+
catch (_err) {
|
|
510
|
+
//
|
|
511
|
+
}
|
|
512
|
+
}
|
|
413
513
|
}
|
|
414
514
|
async receiveLoop() {
|
|
415
515
|
if (!this.auth) {
|
|
@@ -440,60 +540,9 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
440
540
|
d("failed to decrypt message: %o", err);
|
|
441
541
|
continue;
|
|
442
542
|
}
|
|
443
|
-
const messages = decrypted instanceof
|
|
543
|
+
const messages = decrypted instanceof _7_message_container_js_1.MessageContainer ? decrypted.messages : [decrypted];
|
|
444
544
|
for (const message of messages) {
|
|
445
|
-
|
|
446
|
-
if (body instanceof types.GZIPPacked) {
|
|
447
|
-
body = new _3_tl_reader_js_1.TLReader((0, deps_js_1.gunzip)(body.packedData)).readObject();
|
|
448
|
-
}
|
|
449
|
-
d("received %s", body.constructor.name);
|
|
450
|
-
if (body instanceof types.Updates) {
|
|
451
|
-
this.processUpdates(body);
|
|
452
|
-
}
|
|
453
|
-
else if (message.body instanceof _4_rpc_result_js_1.RPCResult) {
|
|
454
|
-
let result = message.body.result;
|
|
455
|
-
if (result instanceof types.GZIPPacked) {
|
|
456
|
-
result = new _3_tl_reader_js_1.TLReader((0, deps_js_1.gunzip)(result.packedData)).readObject();
|
|
457
|
-
}
|
|
458
|
-
if (result instanceof types.RPCError) {
|
|
459
|
-
d("RPCResult: %d %s", result.errorCode, result.errorMessage);
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
d("RPCResult: %s", result.constructor.name);
|
|
463
|
-
}
|
|
464
|
-
const promise = this.promises.get(message.body.messageId);
|
|
465
|
-
if (promise) {
|
|
466
|
-
if (result instanceof types.RPCError) {
|
|
467
|
-
promise.reject(result);
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
if (result instanceof types.Updates) {
|
|
471
|
-
await this.processChats(result.chats);
|
|
472
|
-
await this.processUsers(result.users);
|
|
473
|
-
}
|
|
474
|
-
promise.resolve(result);
|
|
475
|
-
}
|
|
476
|
-
this.promises.delete(message.body.messageId);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
else if (message.body instanceof types.Pong) {
|
|
480
|
-
const promise = this.promises.get(message.body.msgId);
|
|
481
|
-
if (promise) {
|
|
482
|
-
promise.resolve(message.body);
|
|
483
|
-
this.promises.delete(message.body.msgId);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
else if (message.body instanceof types.BadMsgNotification || message.body instanceof types.BadServerSalt) {
|
|
487
|
-
if (message.body instanceof types.BadServerSalt) {
|
|
488
|
-
this.state.salt = message.body.newServerSalt;
|
|
489
|
-
}
|
|
490
|
-
const promise = this.promises.get(message.body.badMsgId);
|
|
491
|
-
if (promise) {
|
|
492
|
-
promise.resolve(message.body);
|
|
493
|
-
this.promises.delete(message.body.badMsgId);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
this.toAcknowledge.add(message.id);
|
|
545
|
+
this.messageProcessQueue.push(message);
|
|
497
546
|
}
|
|
498
547
|
}
|
|
499
548
|
}
|
|
@@ -517,7 +566,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
517
566
|
seqNo++;
|
|
518
567
|
this.state.seqNo++;
|
|
519
568
|
}
|
|
520
|
-
const message = new
|
|
569
|
+
const message = new _6_message_js_1.Message((0, _1_message_js_1.getMessageId)(), seqNo, function_);
|
|
521
570
|
await this.transport.send(await (0, _1_message_js_1.encryptMessage)(message, this.auth.key, this.auth.id, this.state.salt, this.sessionId));
|
|
522
571
|
d("invoked %s", function_.constructor.name);
|
|
523
572
|
if (noWait) {
|
|
@@ -542,6 +591,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
542
591
|
async processChats(chats) {
|
|
543
592
|
for (const chat of chats) {
|
|
544
593
|
if (chat instanceof types.Channel && chat.accessHash) {
|
|
594
|
+
await this.storage.setEntity(chat);
|
|
545
595
|
await this.storage.setChannelAccessHash(chat.id, chat.accessHash);
|
|
546
596
|
if (chat.username) {
|
|
547
597
|
await this.storage.updateUsernames("channel", chat.id, [chat.username]);
|
|
@@ -550,11 +600,15 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
550
600
|
await this.storage.updateUsernames("channel", chat.id, chat.usernames.map((v) => v[_1_tl_object_js_1.as](types.Username)).map((v) => v.username));
|
|
551
601
|
}
|
|
552
602
|
}
|
|
603
|
+
else if (chat instanceof types.Chat) {
|
|
604
|
+
await this.storage.setEntity(chat);
|
|
605
|
+
}
|
|
553
606
|
}
|
|
554
607
|
}
|
|
555
608
|
async processUsers(users) {
|
|
556
609
|
for (const user of users) {
|
|
557
610
|
if (user instanceof types.User && user.accessHash) {
|
|
611
|
+
await this.storage.setEntity(user);
|
|
558
612
|
await this.storage.setUserAccessHash(user.id, user.accessHash);
|
|
559
613
|
if (user.username) {
|
|
560
614
|
await this.storage.updateUsernames("user", user.id, [user.username]);
|
|
@@ -565,19 +619,310 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
565
619
|
}
|
|
566
620
|
}
|
|
567
621
|
}
|
|
622
|
+
async applyUpdateNoGap(update, usePts = true) {
|
|
623
|
+
const release = await this.updateApplicationMutex.acquire();
|
|
624
|
+
try {
|
|
625
|
+
if ((update instanceof types.UpdateNewMessage) ||
|
|
626
|
+
(update instanceof types.UpdateDeleteMessages) ||
|
|
627
|
+
(update instanceof types.UpdateReadHistoryInbox) ||
|
|
628
|
+
(update instanceof types.UpdateReadHistoryOutbox) ||
|
|
629
|
+
(update instanceof types.UpdateWebPage) ||
|
|
630
|
+
(update instanceof types.UpdateReadMessagesContents) ||
|
|
631
|
+
(update instanceof types.UpdateEditMessage) ||
|
|
632
|
+
(update instanceof types.UpdateFolderPeers) ||
|
|
633
|
+
(update instanceof types.UpdatePinnedMessages) ||
|
|
634
|
+
(update instanceof types.UpdatePinnedChannelMessages) ||
|
|
635
|
+
(update instanceof types.UpdateShortMessage) ||
|
|
636
|
+
(update instanceof types.UpdateShortChatMessage) ||
|
|
637
|
+
(update instanceof types.UpdateShortSentMessage)) {
|
|
638
|
+
const localState = await this.getLocalState();
|
|
639
|
+
if (localState.pts + update.ptsCount > update.pts) {
|
|
640
|
+
// the update is already applied
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
else if (localState.pts + update.ptsCount < update.pts) {
|
|
644
|
+
// there is an update gap that needs to be filled
|
|
645
|
+
throw UPDATE_GAP;
|
|
646
|
+
}
|
|
647
|
+
localState.pts = update.pts;
|
|
648
|
+
d("applied update with pts %d", update.pts);
|
|
649
|
+
await this.storage.setState(localState);
|
|
650
|
+
}
|
|
651
|
+
else if (usePts &&
|
|
652
|
+
((update instanceof types.UpdateNewChannelMessage) ||
|
|
653
|
+
(update instanceof types.UpdateDeleteChannelMessages) ||
|
|
654
|
+
(update instanceof types.UpdateEditChannelMessage) ||
|
|
655
|
+
(update instanceof types.UpdateChannelWebPage))) {
|
|
656
|
+
const channelId = update instanceof types.UpdateNewChannelMessage || update instanceof types.UpdateEditChannelMessage ? update.message[_1_tl_object_js_1.as](types.Message).peerId[_1_tl_object_js_1.as](types.PeerChannel).channelId : update.channelId;
|
|
657
|
+
let localPts = await this.storage.getChannelPts(channelId);
|
|
658
|
+
if (!localPts) {
|
|
659
|
+
localPts = update.pts - update.ptsCount;
|
|
660
|
+
}
|
|
661
|
+
if (localPts + update.ptsCount > update.pts) {
|
|
662
|
+
// already applied
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
else if (localPts + update.ptsCount < update.pts) {
|
|
666
|
+
// should call channelGetDifference
|
|
667
|
+
throw UPDATE_GAP;
|
|
668
|
+
}
|
|
669
|
+
d("applied update with pts %d", update.pts);
|
|
670
|
+
await this.storage.setChannelPts(channelId, update.pts);
|
|
671
|
+
}
|
|
672
|
+
// apply update (call listeners)
|
|
673
|
+
this.updateHandler?.(this, update);
|
|
674
|
+
}
|
|
675
|
+
finally {
|
|
676
|
+
release();
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
async applyUpdate(update) {
|
|
680
|
+
if (update instanceof types.TypeUpdates &&
|
|
681
|
+
!(update instanceof types.UpdateShortMessage) &&
|
|
682
|
+
!(update instanceof types.UpdateShortChatMessage) &&
|
|
683
|
+
!(update instanceof types.UpdateShortSentMessage)) {
|
|
684
|
+
// other constructors inheriting Updates are not applicable
|
|
685
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
686
|
+
}
|
|
687
|
+
if (update instanceof types.TypeUpdate && update instanceof types.UpdateChannelTooLong) {
|
|
688
|
+
// updateChannelTooLong is not applicable
|
|
689
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
690
|
+
}
|
|
691
|
+
// can't apply updates when filling gap
|
|
692
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
693
|
+
try {
|
|
694
|
+
await this.applyUpdateNoGap(update);
|
|
695
|
+
release();
|
|
696
|
+
}
|
|
697
|
+
catch (err) {
|
|
698
|
+
release();
|
|
699
|
+
if (err == UPDATE_GAP) {
|
|
700
|
+
if ((update instanceof types.UpdateNewChannelMessage) ||
|
|
701
|
+
(update instanceof types.UpdateDeleteChannelMessages) ||
|
|
702
|
+
(update instanceof types.UpdateEditChannelMessage) ||
|
|
703
|
+
(update instanceof types.UpdateChannelWebPage)) {
|
|
704
|
+
const channelId = update instanceof types.UpdateNewChannelMessage || update instanceof types.UpdateEditChannelMessage ? update.message[_1_tl_object_js_1.as](types.Message).peerId[_1_tl_object_js_1.as](types.PeerChannel).channelId : update.channelId;
|
|
705
|
+
await this.recoverChannelUpdateGap(channelId, "applyUpdate");
|
|
706
|
+
}
|
|
707
|
+
else if ((update instanceof types.UpdateNewMessage) ||
|
|
708
|
+
(update instanceof types.UpdateDeleteMessages) ||
|
|
709
|
+
(update instanceof types.UpdateReadHistoryInbox) ||
|
|
710
|
+
(update instanceof types.UpdateReadHistoryOutbox) ||
|
|
711
|
+
(update instanceof types.UpdateWebPage) ||
|
|
712
|
+
(update instanceof types.UpdateReadMessagesContents) ||
|
|
713
|
+
(update instanceof types.UpdateEditMessage) ||
|
|
714
|
+
(update instanceof types.UpdateFolderPeers) ||
|
|
715
|
+
(update instanceof types.UpdatePinnedMessages) ||
|
|
716
|
+
(update instanceof types.UpdatePinnedChannelMessages) ||
|
|
717
|
+
(update instanceof types.UpdateShortMessage) ||
|
|
718
|
+
(update instanceof types.UpdateShortChatMessage) ||
|
|
719
|
+
(update instanceof types.UpdateShortSentMessage)) {
|
|
720
|
+
await this.recoverUpdateGap("applyUpdate");
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
// can't detect update gap from other types of updates
|
|
724
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
725
|
+
}
|
|
726
|
+
// just for integrity
|
|
727
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
728
|
+
try {
|
|
729
|
+
await this.applyUpdateNoGap(update);
|
|
730
|
+
}
|
|
731
|
+
catch (err) {
|
|
732
|
+
if (err == UPDATE_GAP) {
|
|
733
|
+
// the gap must have been filled until now
|
|
734
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
throw err;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
finally {
|
|
741
|
+
release();
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
throw err;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
568
749
|
async processUpdates(updates) {
|
|
569
750
|
try {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
await this.
|
|
751
|
+
if (updates instanceof types.TypeUpdates) {
|
|
752
|
+
if (updates instanceof types.Updates) {
|
|
753
|
+
await this.processChats(updates.chats);
|
|
754
|
+
await this.processUsers(updates.users);
|
|
755
|
+
await this.setUpdateStateDate(updates.date);
|
|
756
|
+
for (const update of updates.updates) {
|
|
757
|
+
await this.processUpdates(update);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
else if (updates instanceof types.UpdateShortMessage ||
|
|
761
|
+
updates instanceof types.UpdateShortChatMessage ||
|
|
762
|
+
updates instanceof types.UpdateShortSentMessage) {
|
|
763
|
+
await this.setUpdateStateDate(updates.date);
|
|
764
|
+
await this.applyUpdate(updates);
|
|
765
|
+
}
|
|
766
|
+
else if (updates instanceof types.UpdatesTooLong) {
|
|
767
|
+
await this.recoverUpdateGap("updatesTooLong");
|
|
768
|
+
}
|
|
769
|
+
else if (updates instanceof types.UpdatesCombined) {
|
|
770
|
+
await this.setUpdateStateDate(updates.date);
|
|
771
|
+
await this.processChats(updates.chats);
|
|
772
|
+
await this.processUsers(updates.users);
|
|
773
|
+
for (const update of updates.updates) {
|
|
774
|
+
await this.processUpdates(update);
|
|
775
|
+
}
|
|
575
776
|
}
|
|
576
777
|
}
|
|
577
|
-
|
|
778
|
+
else if (updates instanceof types.TypeUpdate && updates instanceof types.UpdateChannelTooLong) {
|
|
779
|
+
if (updates.pts != undefined) {
|
|
780
|
+
await this.storage.setChannelPts(updates.channelId, updates.pts);
|
|
781
|
+
}
|
|
782
|
+
await this.recoverChannelUpdateGap(updates.channelId, "updateChannelTooLong");
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
if (updates instanceof types.UpdateUserName) {
|
|
786
|
+
await this.storage.updateUsernames("user", updates.userId, updates.usernames.map((v) => v[_1_tl_object_js_1.as](types.Username)).map((v) => v.username));
|
|
787
|
+
}
|
|
788
|
+
else if (updates instanceof types.UpdatePtsChanged) {
|
|
789
|
+
await this.fetchState("updatePtsChanged");
|
|
790
|
+
if (this.updateState) {
|
|
791
|
+
await this.storage.setState(this.updateState);
|
|
792
|
+
}
|
|
793
|
+
else {
|
|
794
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
await this.applyUpdate(updates);
|
|
798
|
+
}
|
|
578
799
|
}
|
|
579
800
|
catch (err) {
|
|
580
|
-
|
|
801
|
+
d("error processing updates: %O", err);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
async setUpdateStateDate(date) {
|
|
805
|
+
const release = await this.updateApplicationMutex.acquire();
|
|
806
|
+
try {
|
|
807
|
+
const localState = await this.getLocalState();
|
|
808
|
+
localState.date = date;
|
|
809
|
+
await this.storage.setState(localState);
|
|
810
|
+
}
|
|
811
|
+
finally {
|
|
812
|
+
release();
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
async getLocalState() {
|
|
816
|
+
let localState = await this.storage.getState();
|
|
817
|
+
if (!localState) {
|
|
818
|
+
if (this.updateState) {
|
|
819
|
+
localState = this.updateState;
|
|
820
|
+
await this.storage.setState(localState);
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return localState;
|
|
827
|
+
}
|
|
828
|
+
async recoverUpdateGap(source) {
|
|
829
|
+
dRecoverUpdateGap("recovering from update gap [%s]", source);
|
|
830
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
831
|
+
try {
|
|
832
|
+
let state = await this.getLocalState();
|
|
833
|
+
while (true) {
|
|
834
|
+
const difference = await this.invoke(new functions.UpdatesGetDifference({ pts: state.pts, date: state.date, qts: state.qts }));
|
|
835
|
+
if (difference instanceof types.UpdatesDifference || difference instanceof types.UpdatesDifferenceSlice) {
|
|
836
|
+
await this.processChats(difference.chats);
|
|
837
|
+
await this.processUsers(difference.users);
|
|
838
|
+
for (const message of difference.newMessages) {
|
|
839
|
+
await this.applyUpdateNoGap(new types.UpdateNewMessage({ message, pts: 0, ptsCount: 0 }));
|
|
840
|
+
}
|
|
841
|
+
for (const update of difference.otherUpdates) {
|
|
842
|
+
await this.applyUpdateNoGap(update);
|
|
843
|
+
}
|
|
844
|
+
if (difference instanceof types.UpdatesDifference) {
|
|
845
|
+
dRecoverUpdateGap("recovered from update gap");
|
|
846
|
+
break;
|
|
847
|
+
}
|
|
848
|
+
else if (difference instanceof types.UpdatesDifferenceSlice) {
|
|
849
|
+
state = difference.intermediateState[_1_tl_object_js_1.as](types.UpdatesState);
|
|
850
|
+
}
|
|
851
|
+
else {
|
|
852
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
else if (difference instanceof types.UpdatesDifferenceTooLong) {
|
|
856
|
+
// stored messages should be invalidated in case we store messages in the future
|
|
857
|
+
state.pts = difference.pts;
|
|
858
|
+
dRecoverUpdateGap("received differenceTooLong");
|
|
859
|
+
}
|
|
860
|
+
else if (difference instanceof types.UpdatesDifferenceEmpty) {
|
|
861
|
+
await this.setUpdateStateDate(difference.date);
|
|
862
|
+
dRecoverUpdateGap("there was no update gap");
|
|
863
|
+
break;
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
finally {
|
|
871
|
+
release();
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
async recoverChannelUpdateGap(channelId, source) {
|
|
875
|
+
dRecoverChannelUpdateGap("recovering channel update gap [%o, %s]", channelId, source);
|
|
876
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
877
|
+
try {
|
|
878
|
+
const pts_ = await this.storage.getChannelPts(channelId);
|
|
879
|
+
let pts = pts_ == null ? 1 : pts_;
|
|
880
|
+
while (true) {
|
|
881
|
+
const { accessHash } = await this.getInputPeer(constants_js_1.ZERO_CHANNEL_ID + -Number(channelId)).then((v) => v[_1_tl_object_js_1.as](types.InputPeerChannel));
|
|
882
|
+
const difference = await this.invoke(new functions.UpdatesGetChannelDifference({
|
|
883
|
+
pts,
|
|
884
|
+
channel: new types.InputChannel({ channelId, accessHash: accessHash }),
|
|
885
|
+
filter: new types.ChannelMessagesFilterEmpty(),
|
|
886
|
+
limit: await this.storage.getAccountType() == "user" ? constants_js_1.CHANNEL_DIFFERENCE_LIMIT_USER : constants_js_1.CHANNEL_DIFFERENCE_LIMIT_BOT,
|
|
887
|
+
}));
|
|
888
|
+
if (difference instanceof types.UpdatesChannelDifference) {
|
|
889
|
+
await this.processChats(difference.chats);
|
|
890
|
+
await this.processUsers(difference.users);
|
|
891
|
+
for (const message of difference.newMessages) {
|
|
892
|
+
await this.applyUpdateNoGap(new types.UpdateNewChannelMessage({ message, pts: 0, ptsCount: 0 }), false);
|
|
893
|
+
}
|
|
894
|
+
for (const update of difference.otherUpdates) {
|
|
895
|
+
await this.applyUpdateNoGap(update, false);
|
|
896
|
+
}
|
|
897
|
+
await this.storage.setChannelPts(channelId, difference.pts);
|
|
898
|
+
dRecoverChannelUpdateGap("recovered from update gap");
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
901
|
+
else if (difference instanceof types.UpdatesChannelDifferenceTooLong) {
|
|
902
|
+
// invalidate messages
|
|
903
|
+
dRecoverChannelUpdateGap("received channelDifferenceTooLong");
|
|
904
|
+
await this.processChats(difference.chats);
|
|
905
|
+
await this.processUsers(difference.users);
|
|
906
|
+
for (const message of difference.messages) {
|
|
907
|
+
await this.applyUpdateNoGap(new types.UpdateNewChannelMessage({ message, pts: 0, ptsCount: 0 }), false);
|
|
908
|
+
}
|
|
909
|
+
const pts_ = difference.dialog[_1_tl_object_js_1.as](types.Dialog).pts;
|
|
910
|
+
if (pts_ != undefined) {
|
|
911
|
+
pts = pts_;
|
|
912
|
+
}
|
|
913
|
+
else {
|
|
914
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
915
|
+
}
|
|
916
|
+
dRecoverChannelUpdateGap("processed channelDifferenceTooLong");
|
|
917
|
+
}
|
|
918
|
+
else if (difference instanceof types.UpdatesChannelDifferenceEmpty) {
|
|
919
|
+
dRecoverChannelUpdateGap("there was no update gap");
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
finally {
|
|
925
|
+
release();
|
|
581
926
|
}
|
|
582
927
|
}
|
|
583
928
|
async getInputPeer(id) {
|
|
@@ -646,6 +991,50 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
646
991
|
throw new Error("ID format unknown or not implemented");
|
|
647
992
|
}
|
|
648
993
|
}
|
|
994
|
+
[exports.getEntity](peer) {
|
|
995
|
+
const type = peer instanceof types.PeerUser ? "user" : peer instanceof types.PeerChat ? "chat" : peer instanceof types.PeerChannel ? "channel" : (0, _0_control_js_1.UNREACHABLE)();
|
|
996
|
+
const id = peer instanceof types.PeerUser ? peer.userId : peer instanceof types.PeerChat ? peer.chatId : peer instanceof types.PeerChannel ? peer.channelId : (0, _0_control_js_1.UNREACHABLE)();
|
|
997
|
+
return this.storage.getEntity(type, id);
|
|
998
|
+
}
|
|
999
|
+
async processResult(result) {
|
|
1000
|
+
if (result instanceof types.MessagesDialogs ||
|
|
1001
|
+
result instanceof types.MessagesDialogsSlice ||
|
|
1002
|
+
result instanceof types.MessagesMessages ||
|
|
1003
|
+
result instanceof types.MessagesMessagesSlice ||
|
|
1004
|
+
result instanceof types.MessagesChannelMessages ||
|
|
1005
|
+
result instanceof types.MessagesChatFull ||
|
|
1006
|
+
result instanceof types.ContactsFound ||
|
|
1007
|
+
result instanceof types.AccountPrivacyRules ||
|
|
1008
|
+
result instanceof types.ContactsResolvedPeer ||
|
|
1009
|
+
result instanceof types.ChannelsChannelParticipants ||
|
|
1010
|
+
result instanceof types.ChannelsChannelParticipant ||
|
|
1011
|
+
result instanceof types.MessagesPeerDialogs ||
|
|
1012
|
+
result instanceof types.ContactsTopPeers ||
|
|
1013
|
+
result instanceof types.ChannelsAdminLogResults ||
|
|
1014
|
+
result instanceof types.HelpRecentMeURLs ||
|
|
1015
|
+
result instanceof types.MessagesInactiveChats ||
|
|
1016
|
+
result instanceof types.HelpPromoData ||
|
|
1017
|
+
result instanceof types.MessagesMessageViews ||
|
|
1018
|
+
result instanceof types.MessagesDiscussionMessage ||
|
|
1019
|
+
result instanceof types.PhoneGroupCall ||
|
|
1020
|
+
result instanceof types.PhoneGroupParticipants ||
|
|
1021
|
+
result instanceof types.PhoneJoinAsPeers ||
|
|
1022
|
+
result instanceof types.MessagesSponsoredMessages ||
|
|
1023
|
+
result instanceof types.MessagesSearchResultsCalendar ||
|
|
1024
|
+
result instanceof types.ChannelsSendAsPeers ||
|
|
1025
|
+
result instanceof types.UsersUserFull ||
|
|
1026
|
+
result instanceof types.MessagesPeerSettings ||
|
|
1027
|
+
result instanceof types.MessagesMessageReactionsList ||
|
|
1028
|
+
result instanceof types.MessagesForumTopics ||
|
|
1029
|
+
result instanceof types.AccountAutoSaveSettings ||
|
|
1030
|
+
result instanceof types.ChatlistsExportedInvites ||
|
|
1031
|
+
result instanceof types.ChatlistsChatlistInviteAlready ||
|
|
1032
|
+
result instanceof types.ChatlistsChatlistInvite ||
|
|
1033
|
+
result instanceof types.ChatlistsChatlistUpdates) {
|
|
1034
|
+
await this.processChats(result.chats);
|
|
1035
|
+
await this.processUsers(result.users);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
649
1038
|
async sendMessage(chatId, text, params) {
|
|
650
1039
|
const entities_ = params?.entities ?? [];
|
|
651
1040
|
const parseMode = params?.parseMode ?? this.parseMode;
|
|
@@ -691,7 +1080,7 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
691
1080
|
const topMsgId = params?.messageThreadId;
|
|
692
1081
|
const sendAs = params?.sendAs ? await this.getInputPeer(params.sendAs) : undefined;
|
|
693
1082
|
const entities = entities_?.length > 0 ? entities_.map((v) => (0, _0_message_entity_js_1.messageEntityToTlObject)(v)) : undefined;
|
|
694
|
-
const
|
|
1083
|
+
const result = await this.invoke(new functions.MessagesSendMessage({
|
|
695
1084
|
peer,
|
|
696
1085
|
randomId,
|
|
697
1086
|
message,
|
|
@@ -703,16 +1092,48 @@ class Client extends client_abstract_js_1.ClientAbstract {
|
|
|
703
1092
|
sendAs,
|
|
704
1093
|
entities,
|
|
705
1094
|
replyMarkup,
|
|
706
|
-
}))
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
1095
|
+
}));
|
|
1096
|
+
if (result instanceof types.Updates) {
|
|
1097
|
+
for (const update of result.updates) {
|
|
1098
|
+
if (update instanceof types.UpdateNewMessage) {
|
|
1099
|
+
return (0, _3_message_js_1.constructMessage)(update.message[_1_tl_object_js_1.as](types.Message), this[exports.getEntity].bind(this));
|
|
1100
|
+
}
|
|
1101
|
+
else if (update instanceof types.UpdateNewChannelMessage) {
|
|
1102
|
+
return (0, _3_message_js_1.constructMessage)(update.message[_1_tl_object_js_1.as](types.Message), this[exports.getEntity].bind(this));
|
|
1103
|
+
}
|
|
710
1104
|
}
|
|
711
|
-
|
|
712
|
-
|
|
1105
|
+
}
|
|
1106
|
+
else if (result instanceof types.UpdateShortSentMessage || result instanceof types.UpdateShortSentMessage) {
|
|
1107
|
+
const message = await this.getMessage(chatId, result.id);
|
|
1108
|
+
if (message != null) {
|
|
1109
|
+
return message;
|
|
713
1110
|
}
|
|
714
1111
|
}
|
|
715
1112
|
(0, _0_control_js_1.UNREACHABLE)();
|
|
716
1113
|
}
|
|
1114
|
+
async getMessages(chatId, messageIds) {
|
|
1115
|
+
const peer = await this.getInputPeer(chatId);
|
|
1116
|
+
let messages_;
|
|
1117
|
+
if (peer instanceof types.InputPeerChannel) {
|
|
1118
|
+
messages_ = await this.invoke(new functions.ChannelsGetMessages({
|
|
1119
|
+
channel: new types.InputChannel({ channelId: peer.channelId, accessHash: peer.accessHash }),
|
|
1120
|
+
id: messageIds.map((v) => new types.InputMessageID({ id: v })),
|
|
1121
|
+
})).then((v) => v[_1_tl_object_js_1.as](types.MessagesMessages));
|
|
1122
|
+
}
|
|
1123
|
+
else {
|
|
1124
|
+
messages_ = await this.invoke(new functions.MessagesGetMessages({
|
|
1125
|
+
id: messageIds.map((v) => new types.InputMessageID({ id: v })),
|
|
1126
|
+
})).then((v) => v[_1_tl_object_js_1.as](types.MessagesMessages));
|
|
1127
|
+
}
|
|
1128
|
+
const messages = new Array();
|
|
1129
|
+
for (const message_ of messages_.messages) {
|
|
1130
|
+
messages.push(await (0, _3_message_js_1.constructMessage)(message_[_1_tl_object_js_1.as](types.Message), this[exports.getEntity].bind(this)));
|
|
1131
|
+
}
|
|
1132
|
+
return messages;
|
|
1133
|
+
}
|
|
1134
|
+
async getMessage(chatId, messageId) {
|
|
1135
|
+
const messages = await this.getMessages(chatId, [messageId]);
|
|
1136
|
+
return messages[0] ?? null;
|
|
1137
|
+
}
|
|
717
1138
|
}
|
|
718
1139
|
exports.Client = Client;
|