@mtkruto/node 0.0.834 → 0.0.900
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 +29 -4
- package/esm/client/client.js +528 -71
- package/esm/client/client_abstract.d.ts +1 -1
- package/esm/connection/connection.d.ts +1 -1
- package/esm/constants.d.ts +2 -0
- package/esm/constants.js +2 -0
- 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 +19 -1
- package/esm/storage/storage.js +103 -0
- package/esm/storage/storage_local_storage.d.ts +1 -1
- package/esm/storage/storage_memory.d.ts +1 -1
- package/esm/storage/storage_session_storage.d.ts +1 -1
- 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.d.ts +1 -1
- package/esm/types/0_chat_administrator_rights.d.ts +17 -0
- package/esm/types/0_chat_administrator_rights.js +38 -0
- package/esm/types/0_chat_photo.d.ts +24 -0
- package/esm/types/0_chat_photo.js +28 -0
- package/esm/types/0_force_reply.d.ts +8 -0
- package/esm/types/0_force_reply.js +17 -0
- package/esm/types/0_keyboard_button_poll_type.d.ts +3 -0
- package/esm/types/0_login_url.d.ts +6 -0
- package/esm/types/0_login_url.js +1 -0
- package/esm/types/0_message_entity.d.ts +1 -1
- package/esm/types/0_message_entity.js +2 -2
- package/esm/types/0_reply_keyboard_remove.d.ts +7 -0
- package/esm/types/0_reply_keyboard_remove.js +8 -0
- package/esm/types/0_web_app_info.d.ts +4 -0
- package/esm/types/0_web_app_info.js +3 -0
- package/esm/types/1_chat.d.ts +60 -0
- package/esm/types/1_chat.js +70 -0
- package/esm/types/1_inline_keyboard_button.d.ts +33 -0
- package/esm/types/1_inline_keyboard_button.js +63 -0
- package/esm/types/1_keyboard_button.d.ts +43 -0
- package/esm/types/1_keyboard_button.js +133 -0
- package/esm/types/1_user.d.ts +19 -0
- package/esm/types/1_user.js +25 -0
- package/esm/types/2_inline_keyboard_markup.d.ts +7 -0
- package/esm/types/2_inline_keyboard_markup.js +25 -0
- package/esm/types/2_reply_keyboard_markup.d.ts +12 -0
- package/esm/types/2_reply_keyboard_markup.js +37 -0
- package/esm/types/3_message.d.ts +26 -0
- package/esm/types/3_message.js +91 -0
- package/esm/utilities/0_control.d.ts +1 -0
- package/esm/utilities/0_control.js +3 -0
- package/esm/utilities/0_object.d.ts +1 -0
- package/esm/utilities/0_object.js +14 -0
- package/esm/utilities/0_types.js +1 -0
- 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 +29 -4
- package/script/client/client.js +528 -71
- package/script/client/client_abstract.d.ts +1 -1
- package/script/connection/connection.d.ts +1 -1
- package/script/constants.d.ts +2 -0
- package/script/constants.js +3 -1
- 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 +19 -1
- package/script/storage/storage.js +126 -0
- package/script/storage/storage_local_storage.d.ts +1 -1
- package/script/storage/storage_memory.d.ts +1 -1
- package/script/storage/storage_session_storage.d.ts +1 -1
- 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.d.ts +1 -1
- package/script/types/0_chat_administrator_rights.d.ts +17 -0
- package/script/types/0_chat_administrator_rights.js +66 -0
- package/script/types/0_chat_photo.d.ts +24 -0
- package/script/types/0_chat_photo.js +55 -0
- package/script/types/0_force_reply.d.ts +8 -0
- package/script/types/0_force_reply.js +45 -0
- package/script/types/0_keyboard_button_poll_type.d.ts +3 -0
- package/script/types/0_login_url.d.ts +6 -0
- package/script/types/0_login_url.js +2 -0
- package/script/types/0_message_entity.d.ts +1 -1
- package/script/types/0_message_entity.js +2 -2
- package/script/types/0_reply_keyboard_remove.d.ts +7 -0
- package/script/types/0_reply_keyboard_remove.js +36 -0
- package/script/types/0_web_app_info.d.ts +4 -0
- package/script/types/0_web_app_info.js +7 -0
- package/script/types/1_chat.d.ts +60 -0
- package/script/types/1_chat.js +97 -0
- package/script/types/1_inline_keyboard_button.d.ts +33 -0
- package/script/types/1_inline_keyboard_button.js +91 -0
- package/script/types/1_keyboard_button.d.ts +43 -0
- package/script/types/1_keyboard_button.js +161 -0
- package/script/types/1_user.d.ts +19 -0
- package/script/types/1_user.js +52 -0
- package/script/types/2_inline_keyboard_markup.d.ts +7 -0
- package/script/types/2_inline_keyboard_markup.js +53 -0
- package/script/types/2_reply_keyboard_markup.d.ts +12 -0
- package/script/types/2_reply_keyboard_markup.js +65 -0
- package/script/types/3_message.d.ts +26 -0
- package/script/types/3_message.js +118 -0
- package/script/utilities/0_control.d.ts +1 -0
- package/script/utilities/0_control.js +7 -0
- package/script/utilities/0_object.d.ts +1 -0
- package/script/utilities/0_object.js +18 -0
- package/script/utilities/0_types.js +2 -0
- 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/esm/{types.js → types/0_keyboard_button_poll_type.js} +0 -0
- /package/esm/{types.d.ts → utilities/0_types.d.ts} +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/{types.js → types/0_keyboard_button_poll_type.js} +0 -0
- /package/script/{types.d.ts → utilities/0_types.d.ts} +0 -0
package/esm/client/client.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { debug, gunzip } from "../deps.js";
|
|
2
|
-
import { ackThreshold, DEFAULT_APP_VERSION, DEFAULT_DEVICE_MODEL, DEFAULT_INITIAL_DC, DEFAULT_LANG_CODE, DEFAULT_LANG_PACK, DEFAULT_SYSTEM_LANG_CODE, DEFAULT_SYSTEM_VERSION, LAYER, MAX_CHANNEL_ID, MAX_CHAT_ID, USERNAME_TTL, ZERO_CHANNEL_ID } from "../constants.js";
|
|
1
|
+
import { debug, gunzip, Mutex, queue } from "../deps.js";
|
|
2
|
+
import { ackThreshold, CHANNEL_DIFFERENCE_LIMIT_BOT, CHANNEL_DIFFERENCE_LIMIT_USER, DEFAULT_APP_VERSION, DEFAULT_DEVICE_MODEL, DEFAULT_INITIAL_DC, DEFAULT_LANG_CODE, DEFAULT_LANG_PACK, DEFAULT_SYSTEM_LANG_CODE, DEFAULT_SYSTEM_VERSION, LAYER, MAX_CHANNEL_ID, MAX_CHAT_ID, USERNAME_TTL, ZERO_CHANNEL_ID } from "../constants.js";
|
|
3
3
|
import { bigIntFromBuffer, getRandomBigInt, getRandomId } from "../utilities/0_bigint.js";
|
|
4
|
+
import { UNREACHABLE } from "../utilities/0_control.js";
|
|
5
|
+
import { sha1 } from "../utilities/0_hash.js";
|
|
4
6
|
import { parseHtml } from "../utilities/0_html.js";
|
|
5
7
|
import { decryptMessage, encryptMessage, getMessageId } from "../utilities/1_message.js";
|
|
6
8
|
import { checkPassword } from "../utilities/1_password.js";
|
|
@@ -8,15 +10,23 @@ import { as } from "../tl/1_tl_object.js";
|
|
|
8
10
|
import * as types from "../tl/2_types.js";
|
|
9
11
|
import * as functions from "../tl/3_functions.js";
|
|
10
12
|
import { TLReader } from "../tl/3_tl_reader.js";
|
|
11
|
-
import { RPCResult } from "../tl/
|
|
12
|
-
import { Message } from "../tl/
|
|
13
|
-
import { MessageContainer } from "../tl/
|
|
13
|
+
import { RPCResult } from "../tl/5_rpc_result.js";
|
|
14
|
+
import { Message as Message_ } from "../tl/6_message.js"; // MTProto API message
|
|
15
|
+
import { MessageContainer } from "../tl/7_message_container.js";
|
|
14
16
|
import { ClientAbstract } from "./client_abstract.js";
|
|
15
17
|
import { ClientPlain } from "./client_plain.js";
|
|
16
18
|
import { StorageMemory } from "../storage/storage_memory.js";
|
|
17
|
-
import { sha1 } from "../utilities/0_hash.js";
|
|
18
19
|
import { messageEntityToTlObject } from "../types/0_message_entity.js";
|
|
20
|
+
import { replyKeyboardRemoveToTlObject } from "../types/0_reply_keyboard_remove.js";
|
|
21
|
+
import { forceReplyToTlObject } from "../types/0_force_reply.js";
|
|
22
|
+
import { replyKeyboardMarkupToTlObject } from "../types/2_reply_keyboard_markup.js";
|
|
23
|
+
import { inlineKeyboardMarkupToTlObject } from "../types/2_inline_keyboard_markup.js";
|
|
24
|
+
import { constructMessage } from "../types/3_message.js"; // high-level wrapper for Telegram API's message
|
|
19
25
|
const d = debug("client");
|
|
26
|
+
const dRecoverUpdateGap = debug("client_recoverUpdateGap");
|
|
27
|
+
const dRecoverChannelUpdateGap = debug("client_recoverChannelUpdateGap");
|
|
28
|
+
const UPDATE_GAP = Symbol();
|
|
29
|
+
export const getEntity = Symbol();
|
|
20
30
|
export const restartAuth = Symbol();
|
|
21
31
|
export var ParseMode;
|
|
22
32
|
(function (ParseMode) {
|
|
@@ -82,7 +92,13 @@ export class Client extends ClientAbstract {
|
|
|
82
92
|
writable: true,
|
|
83
93
|
value: new Set()
|
|
84
94
|
});
|
|
85
|
-
Object.defineProperty(this, "
|
|
95
|
+
Object.defineProperty(this, "updateState", {
|
|
96
|
+
enumerable: true,
|
|
97
|
+
configurable: true,
|
|
98
|
+
writable: true,
|
|
99
|
+
value: void 0
|
|
100
|
+
});
|
|
101
|
+
Object.defineProperty(this, "updateHandler", {
|
|
86
102
|
enumerable: true,
|
|
87
103
|
configurable: true,
|
|
88
104
|
writable: true,
|
|
@@ -136,6 +152,79 @@ export class Client extends ClientAbstract {
|
|
|
136
152
|
writable: true,
|
|
137
153
|
value: false
|
|
138
154
|
});
|
|
155
|
+
Object.defineProperty(this, "messageProcessQueue", {
|
|
156
|
+
enumerable: true,
|
|
157
|
+
configurable: true,
|
|
158
|
+
writable: true,
|
|
159
|
+
value: queue(async (message) => {
|
|
160
|
+
let body = message.body;
|
|
161
|
+
if (body instanceof types.GZIPPacked) {
|
|
162
|
+
body = new TLReader(gunzip(body.packedData)).readObject();
|
|
163
|
+
}
|
|
164
|
+
d("received %s", body.constructor.name);
|
|
165
|
+
if (body instanceof types.Updates || body instanceof types.TypeUpdate) {
|
|
166
|
+
await this.processUpdates(body);
|
|
167
|
+
}
|
|
168
|
+
else if (message.body instanceof RPCResult) {
|
|
169
|
+
let result = message.body.result;
|
|
170
|
+
if (result instanceof types.GZIPPacked) {
|
|
171
|
+
result = new TLReader(gunzip(result.packedData)).readObject();
|
|
172
|
+
}
|
|
173
|
+
if (result instanceof types.RPCError) {
|
|
174
|
+
d("RPCResult: %d %s", result.errorCode, result.errorMessage);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
d("RPCResult: %s", result.constructor.name);
|
|
178
|
+
}
|
|
179
|
+
if (result instanceof types.Updates || result instanceof types.TypeUpdate) {
|
|
180
|
+
await this.processUpdates(result);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
await this.processResult(result);
|
|
184
|
+
}
|
|
185
|
+
const promise = this.promises.get(message.body.messageId);
|
|
186
|
+
if (promise) {
|
|
187
|
+
if (result instanceof types.RPCError) {
|
|
188
|
+
promise.reject(result);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
promise.resolve(result);
|
|
192
|
+
}
|
|
193
|
+
this.promises.delete(message.body.messageId);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (message.body instanceof types.Pong) {
|
|
197
|
+
const promise = this.promises.get(message.body.msgId);
|
|
198
|
+
if (promise) {
|
|
199
|
+
promise.resolve(message.body);
|
|
200
|
+
this.promises.delete(message.body.msgId);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else if (message.body instanceof types.BadMsgNotification || message.body instanceof types.BadServerSalt) {
|
|
204
|
+
if (message.body instanceof types.BadServerSalt) {
|
|
205
|
+
this.state.salt = message.body.newServerSalt;
|
|
206
|
+
}
|
|
207
|
+
const promise = this.promises.get(message.body.badMsgId);
|
|
208
|
+
if (promise) {
|
|
209
|
+
promise.resolve(message.body);
|
|
210
|
+
this.promises.delete(message.body.badMsgId);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
this.toAcknowledge.add(message.id);
|
|
214
|
+
}, 2)
|
|
215
|
+
});
|
|
216
|
+
Object.defineProperty(this, "updateApplicationMutex", {
|
|
217
|
+
enumerable: true,
|
|
218
|
+
configurable: true,
|
|
219
|
+
writable: true,
|
|
220
|
+
value: new Mutex()
|
|
221
|
+
});
|
|
222
|
+
Object.defineProperty(this, "updateGapRecoveryMutex", {
|
|
223
|
+
enumerable: true,
|
|
224
|
+
configurable: true,
|
|
225
|
+
writable: true,
|
|
226
|
+
value: new Mutex()
|
|
227
|
+
});
|
|
139
228
|
this.parseMode = params?.parseMode ?? ParseMode.None;
|
|
140
229
|
this.appVersion = params?.appVersion ?? DEFAULT_APP_VERSION;
|
|
141
230
|
this.deviceModel = params?.deviceModel ?? DEFAULT_DEVICE_MODEL;
|
|
@@ -205,6 +294,11 @@ export class Client extends ClientAbstract {
|
|
|
205
294
|
this.receiveLoop();
|
|
206
295
|
this.pingLoop();
|
|
207
296
|
}
|
|
297
|
+
async fetchState(source) {
|
|
298
|
+
const state = await this.invoke(new functions.UpdatesGetState());
|
|
299
|
+
this.updateState = state;
|
|
300
|
+
d("state fetched [%s]", source);
|
|
301
|
+
}
|
|
208
302
|
/**
|
|
209
303
|
* Calls [initConnection](1) and authorizes the client with one of the following:
|
|
210
304
|
*
|
|
@@ -254,6 +348,7 @@ export class Client extends ClientAbstract {
|
|
|
254
348
|
const password = typeof params.password === "string" ? params.password : await params.password();
|
|
255
349
|
const input = await checkPassword(password, ap);
|
|
256
350
|
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
351
|
+
await this.storage.setAccountType("user");
|
|
257
352
|
d("authorized as user");
|
|
258
353
|
break;
|
|
259
354
|
}
|
|
@@ -276,7 +371,7 @@ export class Client extends ClientAbstract {
|
|
|
276
371
|
}
|
|
277
372
|
};
|
|
278
373
|
try {
|
|
279
|
-
await this.
|
|
374
|
+
await this.fetchState("authorize");
|
|
280
375
|
d("already authorized");
|
|
281
376
|
return;
|
|
282
377
|
}
|
|
@@ -317,6 +412,7 @@ export class Client extends ClientAbstract {
|
|
|
317
412
|
}
|
|
318
413
|
else {
|
|
319
414
|
signedIn = true;
|
|
415
|
+
await this.storage.setAccountType("user");
|
|
320
416
|
d("authorized as user");
|
|
321
417
|
break;
|
|
322
418
|
}
|
|
@@ -351,6 +447,7 @@ export class Client extends ClientAbstract {
|
|
|
351
447
|
}
|
|
352
448
|
else {
|
|
353
449
|
await this.invoke(new functions.AuthImportBotAuthorization({ apiId: this.apiId, apiHash: this.apiHash, botAuthToken: params, flags: 0 }));
|
|
450
|
+
await this.storage.setAccountType("bot");
|
|
354
451
|
d("authorized as bot");
|
|
355
452
|
}
|
|
356
453
|
}
|
|
@@ -378,6 +475,14 @@ export class Client extends ClientAbstract {
|
|
|
378
475
|
throw err;
|
|
379
476
|
}
|
|
380
477
|
}
|
|
478
|
+
finally {
|
|
479
|
+
try {
|
|
480
|
+
await this.fetchState("authorize");
|
|
481
|
+
}
|
|
482
|
+
catch (_err) {
|
|
483
|
+
//
|
|
484
|
+
}
|
|
485
|
+
}
|
|
381
486
|
}
|
|
382
487
|
async receiveLoop() {
|
|
383
488
|
if (!this.auth) {
|
|
@@ -410,58 +515,7 @@ export class Client extends ClientAbstract {
|
|
|
410
515
|
}
|
|
411
516
|
const messages = decrypted instanceof MessageContainer ? decrypted.messages : [decrypted];
|
|
412
517
|
for (const message of messages) {
|
|
413
|
-
|
|
414
|
-
if (body instanceof types.GZIPPacked) {
|
|
415
|
-
body = new TLReader(gunzip(body.packedData)).readObject();
|
|
416
|
-
}
|
|
417
|
-
d("received %s", body.constructor.name);
|
|
418
|
-
if (body instanceof types.Updates) {
|
|
419
|
-
this.processUpdates(body);
|
|
420
|
-
}
|
|
421
|
-
else if (message.body instanceof RPCResult) {
|
|
422
|
-
let result = message.body.result;
|
|
423
|
-
if (result instanceof types.GZIPPacked) {
|
|
424
|
-
result = new TLReader(gunzip(result.packedData)).readObject();
|
|
425
|
-
}
|
|
426
|
-
if (result instanceof types.RPCError) {
|
|
427
|
-
d("RPCResult: %d %s", result.errorCode, result.errorMessage);
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
d("RPCResult: %s", result.constructor.name);
|
|
431
|
-
}
|
|
432
|
-
const promise = this.promises.get(message.body.messageId);
|
|
433
|
-
if (promise) {
|
|
434
|
-
if (result instanceof types.RPCError) {
|
|
435
|
-
promise.reject(result);
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
if (result instanceof types.Updates) {
|
|
439
|
-
await this.processChats(result.chats);
|
|
440
|
-
await this.processUsers(result.users);
|
|
441
|
-
}
|
|
442
|
-
promise.resolve(result);
|
|
443
|
-
}
|
|
444
|
-
this.promises.delete(message.body.messageId);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
else if (message.body instanceof types.Pong) {
|
|
448
|
-
const promise = this.promises.get(message.body.msgId);
|
|
449
|
-
if (promise) {
|
|
450
|
-
promise.resolve(message.body);
|
|
451
|
-
this.promises.delete(message.body.msgId);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
else if (message.body instanceof types.BadMsgNotification || message.body instanceof types.BadServerSalt) {
|
|
455
|
-
if (message.body instanceof types.BadServerSalt) {
|
|
456
|
-
this.state.salt = message.body.newServerSalt;
|
|
457
|
-
}
|
|
458
|
-
const promise = this.promises.get(message.body.badMsgId);
|
|
459
|
-
if (promise) {
|
|
460
|
-
promise.resolve(message.body);
|
|
461
|
-
this.promises.delete(message.body.badMsgId);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
this.toAcknowledge.add(message.id);
|
|
518
|
+
this.messageProcessQueue.push(message);
|
|
465
519
|
}
|
|
466
520
|
}
|
|
467
521
|
}
|
|
@@ -485,7 +539,7 @@ export class Client extends ClientAbstract {
|
|
|
485
539
|
seqNo++;
|
|
486
540
|
this.state.seqNo++;
|
|
487
541
|
}
|
|
488
|
-
const message = new
|
|
542
|
+
const message = new Message_(getMessageId(), seqNo, function_);
|
|
489
543
|
await this.transport.send(await encryptMessage(message, this.auth.key, this.auth.id, this.state.salt, this.sessionId));
|
|
490
544
|
d("invoked %s", function_.constructor.name);
|
|
491
545
|
if (noWait) {
|
|
@@ -510,6 +564,7 @@ export class Client extends ClientAbstract {
|
|
|
510
564
|
async processChats(chats) {
|
|
511
565
|
for (const chat of chats) {
|
|
512
566
|
if (chat instanceof types.Channel && chat.accessHash) {
|
|
567
|
+
await this.storage.setEntity(chat);
|
|
513
568
|
await this.storage.setChannelAccessHash(chat.id, chat.accessHash);
|
|
514
569
|
if (chat.username) {
|
|
515
570
|
await this.storage.updateUsernames("channel", chat.id, [chat.username]);
|
|
@@ -518,11 +573,15 @@ export class Client extends ClientAbstract {
|
|
|
518
573
|
await this.storage.updateUsernames("channel", chat.id, chat.usernames.map((v) => v[as](types.Username)).map((v) => v.username));
|
|
519
574
|
}
|
|
520
575
|
}
|
|
576
|
+
else if (chat instanceof types.Chat) {
|
|
577
|
+
await this.storage.setEntity(chat);
|
|
578
|
+
}
|
|
521
579
|
}
|
|
522
580
|
}
|
|
523
581
|
async processUsers(users) {
|
|
524
582
|
for (const user of users) {
|
|
525
583
|
if (user instanceof types.User && user.accessHash) {
|
|
584
|
+
await this.storage.setEntity(user);
|
|
526
585
|
await this.storage.setUserAccessHash(user.id, user.accessHash);
|
|
527
586
|
if (user.username) {
|
|
528
587
|
await this.storage.updateUsernames("user", user.id, [user.username]);
|
|
@@ -533,19 +592,310 @@ export class Client extends ClientAbstract {
|
|
|
533
592
|
}
|
|
534
593
|
}
|
|
535
594
|
}
|
|
595
|
+
async applyUpdateNoGap(update, usePts = true) {
|
|
596
|
+
const release = await this.updateApplicationMutex.acquire();
|
|
597
|
+
try {
|
|
598
|
+
if ((update instanceof types.UpdateNewMessage) ||
|
|
599
|
+
(update instanceof types.UpdateDeleteMessages) ||
|
|
600
|
+
(update instanceof types.UpdateReadHistoryInbox) ||
|
|
601
|
+
(update instanceof types.UpdateReadHistoryOutbox) ||
|
|
602
|
+
(update instanceof types.UpdateWebPage) ||
|
|
603
|
+
(update instanceof types.UpdateReadMessagesContents) ||
|
|
604
|
+
(update instanceof types.UpdateEditMessage) ||
|
|
605
|
+
(update instanceof types.UpdateFolderPeers) ||
|
|
606
|
+
(update instanceof types.UpdatePinnedMessages) ||
|
|
607
|
+
(update instanceof types.UpdatePinnedChannelMessages) ||
|
|
608
|
+
(update instanceof types.UpdateShortMessage) ||
|
|
609
|
+
(update instanceof types.UpdateShortChatMessage) ||
|
|
610
|
+
(update instanceof types.UpdateShortSentMessage)) {
|
|
611
|
+
const localState = await this.getLocalState();
|
|
612
|
+
if (localState.pts + update.ptsCount > update.pts) {
|
|
613
|
+
// the update is already applied
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
else if (localState.pts + update.ptsCount < update.pts) {
|
|
617
|
+
// there is an update gap that needs to be filled
|
|
618
|
+
throw UPDATE_GAP;
|
|
619
|
+
}
|
|
620
|
+
localState.pts = update.pts;
|
|
621
|
+
d("applied update with pts %d", update.pts);
|
|
622
|
+
await this.storage.setState(localState);
|
|
623
|
+
}
|
|
624
|
+
else if (usePts &&
|
|
625
|
+
((update instanceof types.UpdateNewChannelMessage) ||
|
|
626
|
+
(update instanceof types.UpdateDeleteChannelMessages) ||
|
|
627
|
+
(update instanceof types.UpdateEditChannelMessage) ||
|
|
628
|
+
(update instanceof types.UpdateChannelWebPage))) {
|
|
629
|
+
const channelId = update instanceof types.UpdateNewChannelMessage || update instanceof types.UpdateEditChannelMessage ? update.message[as](types.Message).peerId[as](types.PeerChannel).channelId : update.channelId;
|
|
630
|
+
let localPts = await this.storage.getChannelPts(channelId);
|
|
631
|
+
if (!localPts) {
|
|
632
|
+
localPts = update.pts - update.ptsCount;
|
|
633
|
+
}
|
|
634
|
+
if (localPts + update.ptsCount > update.pts) {
|
|
635
|
+
// already applied
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
else if (localPts + update.ptsCount < update.pts) {
|
|
639
|
+
// should call channelGetDifference
|
|
640
|
+
throw UPDATE_GAP;
|
|
641
|
+
}
|
|
642
|
+
d("applied update with pts %d", update.pts);
|
|
643
|
+
await this.storage.setChannelPts(channelId, update.pts);
|
|
644
|
+
}
|
|
645
|
+
// apply update (call listeners)
|
|
646
|
+
this.updateHandler?.(this, update);
|
|
647
|
+
}
|
|
648
|
+
finally {
|
|
649
|
+
release();
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
async applyUpdate(update) {
|
|
653
|
+
if (update instanceof types.TypeUpdates &&
|
|
654
|
+
!(update instanceof types.UpdateShortMessage) &&
|
|
655
|
+
!(update instanceof types.UpdateShortChatMessage) &&
|
|
656
|
+
!(update instanceof types.UpdateShortSentMessage)) {
|
|
657
|
+
// other constructors inheriting Updates are not applicable
|
|
658
|
+
UNREACHABLE();
|
|
659
|
+
}
|
|
660
|
+
if (update instanceof types.TypeUpdate && update instanceof types.UpdateChannelTooLong) {
|
|
661
|
+
// updateChannelTooLong is not applicable
|
|
662
|
+
UNREACHABLE();
|
|
663
|
+
}
|
|
664
|
+
// can't apply updates when filling gap
|
|
665
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
666
|
+
try {
|
|
667
|
+
await this.applyUpdateNoGap(update);
|
|
668
|
+
release();
|
|
669
|
+
}
|
|
670
|
+
catch (err) {
|
|
671
|
+
release();
|
|
672
|
+
if (err == UPDATE_GAP) {
|
|
673
|
+
if ((update instanceof types.UpdateNewChannelMessage) ||
|
|
674
|
+
(update instanceof types.UpdateDeleteChannelMessages) ||
|
|
675
|
+
(update instanceof types.UpdateEditChannelMessage) ||
|
|
676
|
+
(update instanceof types.UpdateChannelWebPage)) {
|
|
677
|
+
const channelId = update instanceof types.UpdateNewChannelMessage || update instanceof types.UpdateEditChannelMessage ? update.message[as](types.Message).peerId[as](types.PeerChannel).channelId : update.channelId;
|
|
678
|
+
await this.recoverChannelUpdateGap(channelId, "applyUpdate");
|
|
679
|
+
}
|
|
680
|
+
else if ((update instanceof types.UpdateNewMessage) ||
|
|
681
|
+
(update instanceof types.UpdateDeleteMessages) ||
|
|
682
|
+
(update instanceof types.UpdateReadHistoryInbox) ||
|
|
683
|
+
(update instanceof types.UpdateReadHistoryOutbox) ||
|
|
684
|
+
(update instanceof types.UpdateWebPage) ||
|
|
685
|
+
(update instanceof types.UpdateReadMessagesContents) ||
|
|
686
|
+
(update instanceof types.UpdateEditMessage) ||
|
|
687
|
+
(update instanceof types.UpdateFolderPeers) ||
|
|
688
|
+
(update instanceof types.UpdatePinnedMessages) ||
|
|
689
|
+
(update instanceof types.UpdatePinnedChannelMessages) ||
|
|
690
|
+
(update instanceof types.UpdateShortMessage) ||
|
|
691
|
+
(update instanceof types.UpdateShortChatMessage) ||
|
|
692
|
+
(update instanceof types.UpdateShortSentMessage)) {
|
|
693
|
+
await this.recoverUpdateGap("applyUpdate");
|
|
694
|
+
}
|
|
695
|
+
else {
|
|
696
|
+
// can't detect update gap from other types of updates
|
|
697
|
+
UNREACHABLE();
|
|
698
|
+
}
|
|
699
|
+
// just for integrity
|
|
700
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
701
|
+
try {
|
|
702
|
+
await this.applyUpdateNoGap(update);
|
|
703
|
+
}
|
|
704
|
+
catch (err) {
|
|
705
|
+
if (err == UPDATE_GAP) {
|
|
706
|
+
// the gap must have been filled until now
|
|
707
|
+
UNREACHABLE();
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
throw err;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
finally {
|
|
714
|
+
release();
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
throw err;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
536
722
|
async processUpdates(updates) {
|
|
537
723
|
try {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
await this.
|
|
724
|
+
if (updates instanceof types.TypeUpdates) {
|
|
725
|
+
if (updates instanceof types.Updates) {
|
|
726
|
+
await this.processChats(updates.chats);
|
|
727
|
+
await this.processUsers(updates.users);
|
|
728
|
+
await this.setUpdateStateDate(updates.date);
|
|
729
|
+
for (const update of updates.updates) {
|
|
730
|
+
await this.processUpdates(update);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
else if (updates instanceof types.UpdateShortMessage ||
|
|
734
|
+
updates instanceof types.UpdateShortChatMessage ||
|
|
735
|
+
updates instanceof types.UpdateShortSentMessage) {
|
|
736
|
+
await this.setUpdateStateDate(updates.date);
|
|
737
|
+
await this.applyUpdate(updates);
|
|
738
|
+
}
|
|
739
|
+
else if (updates instanceof types.UpdatesTooLong) {
|
|
740
|
+
await this.recoverUpdateGap("updatesTooLong");
|
|
741
|
+
}
|
|
742
|
+
else if (updates instanceof types.UpdatesCombined) {
|
|
743
|
+
await this.setUpdateStateDate(updates.date);
|
|
744
|
+
await this.processChats(updates.chats);
|
|
745
|
+
await this.processUsers(updates.users);
|
|
746
|
+
for (const update of updates.updates) {
|
|
747
|
+
await this.processUpdates(update);
|
|
748
|
+
}
|
|
543
749
|
}
|
|
544
750
|
}
|
|
545
|
-
|
|
751
|
+
else if (updates instanceof types.TypeUpdate && updates instanceof types.UpdateChannelTooLong) {
|
|
752
|
+
if (updates.pts != undefined) {
|
|
753
|
+
await this.storage.setChannelPts(updates.channelId, updates.pts);
|
|
754
|
+
}
|
|
755
|
+
await this.recoverChannelUpdateGap(updates.channelId, "updateChannelTooLong");
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
if (updates instanceof types.UpdateUserName) {
|
|
759
|
+
await this.storage.updateUsernames("user", updates.userId, updates.usernames.map((v) => v[as](types.Username)).map((v) => v.username));
|
|
760
|
+
}
|
|
761
|
+
else if (updates instanceof types.UpdatePtsChanged) {
|
|
762
|
+
await this.fetchState("updatePtsChanged");
|
|
763
|
+
if (this.updateState) {
|
|
764
|
+
await this.storage.setState(this.updateState);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
UNREACHABLE();
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
await this.applyUpdate(updates);
|
|
771
|
+
}
|
|
546
772
|
}
|
|
547
773
|
catch (err) {
|
|
548
|
-
|
|
774
|
+
d("error processing updates: %O", err);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
async setUpdateStateDate(date) {
|
|
778
|
+
const release = await this.updateApplicationMutex.acquire();
|
|
779
|
+
try {
|
|
780
|
+
const localState = await this.getLocalState();
|
|
781
|
+
localState.date = date;
|
|
782
|
+
await this.storage.setState(localState);
|
|
783
|
+
}
|
|
784
|
+
finally {
|
|
785
|
+
release();
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
async getLocalState() {
|
|
789
|
+
let localState = await this.storage.getState();
|
|
790
|
+
if (!localState) {
|
|
791
|
+
if (this.updateState) {
|
|
792
|
+
localState = this.updateState;
|
|
793
|
+
await this.storage.setState(localState);
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
UNREACHABLE();
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return localState;
|
|
800
|
+
}
|
|
801
|
+
async recoverUpdateGap(source) {
|
|
802
|
+
dRecoverUpdateGap("recovering from update gap [%s]", source);
|
|
803
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
804
|
+
try {
|
|
805
|
+
let state = await this.getLocalState();
|
|
806
|
+
while (true) {
|
|
807
|
+
const difference = await this.invoke(new functions.UpdatesGetDifference({ pts: state.pts, date: state.date, qts: state.qts }));
|
|
808
|
+
if (difference instanceof types.UpdatesDifference || difference instanceof types.UpdatesDifferenceSlice) {
|
|
809
|
+
await this.processChats(difference.chats);
|
|
810
|
+
await this.processUsers(difference.users);
|
|
811
|
+
for (const message of difference.newMessages) {
|
|
812
|
+
await this.applyUpdateNoGap(new types.UpdateNewMessage({ message, pts: 0, ptsCount: 0 }));
|
|
813
|
+
}
|
|
814
|
+
for (const update of difference.otherUpdates) {
|
|
815
|
+
await this.applyUpdateNoGap(update);
|
|
816
|
+
}
|
|
817
|
+
if (difference instanceof types.UpdatesDifference) {
|
|
818
|
+
dRecoverUpdateGap("recovered from update gap");
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
else if (difference instanceof types.UpdatesDifferenceSlice) {
|
|
822
|
+
state = difference.intermediateState[as](types.UpdatesState);
|
|
823
|
+
}
|
|
824
|
+
else {
|
|
825
|
+
UNREACHABLE();
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
else if (difference instanceof types.UpdatesDifferenceTooLong) {
|
|
829
|
+
// stored messages should be invalidated in case we store messages in the future
|
|
830
|
+
state.pts = difference.pts;
|
|
831
|
+
dRecoverUpdateGap("received differenceTooLong");
|
|
832
|
+
}
|
|
833
|
+
else if (difference instanceof types.UpdatesDifferenceEmpty) {
|
|
834
|
+
await this.setUpdateStateDate(difference.date);
|
|
835
|
+
dRecoverUpdateGap("there was no update gap");
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
else {
|
|
839
|
+
UNREACHABLE();
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
finally {
|
|
844
|
+
release();
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
async recoverChannelUpdateGap(channelId, source) {
|
|
848
|
+
dRecoverChannelUpdateGap("recovering channel update gap [%o, %s]", channelId, source);
|
|
849
|
+
const release = await this.updateGapRecoveryMutex.acquire();
|
|
850
|
+
try {
|
|
851
|
+
const pts_ = await this.storage.getChannelPts(channelId);
|
|
852
|
+
let pts = pts_ == null ? 1 : pts_;
|
|
853
|
+
while (true) {
|
|
854
|
+
const { accessHash } = await this.getInputPeer(ZERO_CHANNEL_ID + -Number(channelId)).then((v) => v[as](types.InputPeerChannel));
|
|
855
|
+
const difference = await this.invoke(new functions.UpdatesGetChannelDifference({
|
|
856
|
+
pts,
|
|
857
|
+
channel: new types.InputChannel({ channelId, accessHash: accessHash }),
|
|
858
|
+
filter: new types.ChannelMessagesFilterEmpty(),
|
|
859
|
+
limit: await this.storage.getAccountType() == "user" ? CHANNEL_DIFFERENCE_LIMIT_USER : CHANNEL_DIFFERENCE_LIMIT_BOT,
|
|
860
|
+
}));
|
|
861
|
+
if (difference instanceof types.UpdatesChannelDifference) {
|
|
862
|
+
await this.processChats(difference.chats);
|
|
863
|
+
await this.processUsers(difference.users);
|
|
864
|
+
for (const message of difference.newMessages) {
|
|
865
|
+
await this.applyUpdateNoGap(new types.UpdateNewChannelMessage({ message, pts: 0, ptsCount: 0 }), false);
|
|
866
|
+
}
|
|
867
|
+
for (const update of difference.otherUpdates) {
|
|
868
|
+
await this.applyUpdateNoGap(update, false);
|
|
869
|
+
}
|
|
870
|
+
await this.storage.setChannelPts(channelId, difference.pts);
|
|
871
|
+
dRecoverChannelUpdateGap("recovered from update gap");
|
|
872
|
+
break;
|
|
873
|
+
}
|
|
874
|
+
else if (difference instanceof types.UpdatesChannelDifferenceTooLong) {
|
|
875
|
+
// invalidate messages
|
|
876
|
+
dRecoverChannelUpdateGap("received channelDifferenceTooLong");
|
|
877
|
+
await this.processChats(difference.chats);
|
|
878
|
+
await this.processUsers(difference.users);
|
|
879
|
+
for (const message of difference.messages) {
|
|
880
|
+
await this.applyUpdateNoGap(new types.UpdateNewChannelMessage({ message, pts: 0, ptsCount: 0 }), false);
|
|
881
|
+
}
|
|
882
|
+
const pts_ = difference.dialog[as](types.Dialog).pts;
|
|
883
|
+
if (pts_ != undefined) {
|
|
884
|
+
pts = pts_;
|
|
885
|
+
}
|
|
886
|
+
else {
|
|
887
|
+
UNREACHABLE();
|
|
888
|
+
}
|
|
889
|
+
dRecoverChannelUpdateGap("processed channelDifferenceTooLong");
|
|
890
|
+
}
|
|
891
|
+
else if (difference instanceof types.UpdatesChannelDifferenceEmpty) {
|
|
892
|
+
dRecoverChannelUpdateGap("there was no update gap");
|
|
893
|
+
break;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
finally {
|
|
898
|
+
release();
|
|
549
899
|
}
|
|
550
900
|
}
|
|
551
901
|
async getInputPeer(id) {
|
|
@@ -581,7 +931,7 @@ export class Client extends ClientAbstract {
|
|
|
581
931
|
channelId = resolved.peer.channelId;
|
|
582
932
|
}
|
|
583
933
|
else {
|
|
584
|
-
|
|
934
|
+
UNREACHABLE();
|
|
585
935
|
}
|
|
586
936
|
}
|
|
587
937
|
if (userId) {
|
|
@@ -593,7 +943,7 @@ export class Client extends ClientAbstract {
|
|
|
593
943
|
return new types.InputPeerChannel({ channelId, accessHash: accessHash ?? 0n });
|
|
594
944
|
}
|
|
595
945
|
else {
|
|
596
|
-
|
|
946
|
+
UNREACHABLE();
|
|
597
947
|
}
|
|
598
948
|
}
|
|
599
949
|
}
|
|
@@ -614,6 +964,50 @@ export class Client extends ClientAbstract {
|
|
|
614
964
|
throw new Error("ID format unknown or not implemented");
|
|
615
965
|
}
|
|
616
966
|
}
|
|
967
|
+
[getEntity](peer) {
|
|
968
|
+
const type = peer instanceof types.PeerUser ? "user" : peer instanceof types.PeerChat ? "chat" : peer instanceof types.PeerChannel ? "channel" : UNREACHABLE();
|
|
969
|
+
const id = peer instanceof types.PeerUser ? peer.userId : peer instanceof types.PeerChat ? peer.chatId : peer instanceof types.PeerChannel ? peer.channelId : UNREACHABLE();
|
|
970
|
+
return this.storage.getEntity(type, id);
|
|
971
|
+
}
|
|
972
|
+
async processResult(result) {
|
|
973
|
+
if (result instanceof types.MessagesDialogs ||
|
|
974
|
+
result instanceof types.MessagesDialogsSlice ||
|
|
975
|
+
result instanceof types.MessagesMessages ||
|
|
976
|
+
result instanceof types.MessagesMessagesSlice ||
|
|
977
|
+
result instanceof types.MessagesChannelMessages ||
|
|
978
|
+
result instanceof types.MessagesChatFull ||
|
|
979
|
+
result instanceof types.ContactsFound ||
|
|
980
|
+
result instanceof types.AccountPrivacyRules ||
|
|
981
|
+
result instanceof types.ContactsResolvedPeer ||
|
|
982
|
+
result instanceof types.ChannelsChannelParticipants ||
|
|
983
|
+
result instanceof types.ChannelsChannelParticipant ||
|
|
984
|
+
result instanceof types.MessagesPeerDialogs ||
|
|
985
|
+
result instanceof types.ContactsTopPeers ||
|
|
986
|
+
result instanceof types.ChannelsAdminLogResults ||
|
|
987
|
+
result instanceof types.HelpRecentMeURLs ||
|
|
988
|
+
result instanceof types.MessagesInactiveChats ||
|
|
989
|
+
result instanceof types.HelpPromoData ||
|
|
990
|
+
result instanceof types.MessagesMessageViews ||
|
|
991
|
+
result instanceof types.MessagesDiscussionMessage ||
|
|
992
|
+
result instanceof types.PhoneGroupCall ||
|
|
993
|
+
result instanceof types.PhoneGroupParticipants ||
|
|
994
|
+
result instanceof types.PhoneJoinAsPeers ||
|
|
995
|
+
result instanceof types.MessagesSponsoredMessages ||
|
|
996
|
+
result instanceof types.MessagesSearchResultsCalendar ||
|
|
997
|
+
result instanceof types.ChannelsSendAsPeers ||
|
|
998
|
+
result instanceof types.UsersUserFull ||
|
|
999
|
+
result instanceof types.MessagesPeerSettings ||
|
|
1000
|
+
result instanceof types.MessagesMessageReactionsList ||
|
|
1001
|
+
result instanceof types.MessagesForumTopics ||
|
|
1002
|
+
result instanceof types.AccountAutoSaveSettings ||
|
|
1003
|
+
result instanceof types.ChatlistsExportedInvites ||
|
|
1004
|
+
result instanceof types.ChatlistsChatlistInviteAlready ||
|
|
1005
|
+
result instanceof types.ChatlistsChatlistInvite ||
|
|
1006
|
+
result instanceof types.ChatlistsChatlistUpdates) {
|
|
1007
|
+
await this.processChats(result.chats);
|
|
1008
|
+
await this.processUsers(result.users);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
617
1011
|
async sendMessage(chatId, text, params) {
|
|
618
1012
|
const entities_ = params?.entities ?? [];
|
|
619
1013
|
const parseMode = params?.parseMode ?? this.parseMode;
|
|
@@ -628,6 +1022,27 @@ export class Client extends ClientAbstract {
|
|
|
628
1022
|
}
|
|
629
1023
|
}
|
|
630
1024
|
}
|
|
1025
|
+
let replyMarkup = undefined;
|
|
1026
|
+
if (params?.replyMarkup) {
|
|
1027
|
+
if ("inlineKeyboard" in params.replyMarkup) {
|
|
1028
|
+
replyMarkup = await inlineKeyboardMarkupToTlObject(params.replyMarkup, async (v) => {
|
|
1029
|
+
const inputPeer = await this.getInputPeer(v).then((v) => v[as](types.InputPeerUser));
|
|
1030
|
+
return new types.InputUser({ userId: inputPeer.userId, accessHash: inputPeer.accessHash });
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
else if ("keyboard" in params.replyMarkup) {
|
|
1034
|
+
replyMarkup = replyKeyboardMarkupToTlObject(params.replyMarkup);
|
|
1035
|
+
}
|
|
1036
|
+
else if ("removeKeyboard" in params.replyMarkup) {
|
|
1037
|
+
replyMarkup = replyKeyboardRemoveToTlObject(params.replyMarkup);
|
|
1038
|
+
}
|
|
1039
|
+
else if ("forceReply" in params.replyMarkup) {
|
|
1040
|
+
replyMarkup = forceReplyToTlObject(params.replyMarkup);
|
|
1041
|
+
}
|
|
1042
|
+
else {
|
|
1043
|
+
throw new Error("The replyMarkup parameter has an unexpected type");
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
631
1046
|
const peer = await this.getInputPeer(chatId);
|
|
632
1047
|
const randomId = getRandomId();
|
|
633
1048
|
const message = text;
|
|
@@ -638,7 +1053,7 @@ export class Client extends ClientAbstract {
|
|
|
638
1053
|
const topMsgId = params?.messageThreadId;
|
|
639
1054
|
const sendAs = params?.sendAs ? await this.getInputPeer(params.sendAs) : undefined;
|
|
640
1055
|
const entities = entities_?.length > 0 ? entities_.map((v) => messageEntityToTlObject(v)) : undefined;
|
|
641
|
-
|
|
1056
|
+
const result = await this.invoke(new functions.MessagesSendMessage({
|
|
642
1057
|
peer,
|
|
643
1058
|
randomId,
|
|
644
1059
|
message,
|
|
@@ -649,6 +1064,48 @@ export class Client extends ClientAbstract {
|
|
|
649
1064
|
topMsgId,
|
|
650
1065
|
sendAs,
|
|
651
1066
|
entities,
|
|
1067
|
+
replyMarkup,
|
|
652
1068
|
}));
|
|
1069
|
+
if (result instanceof types.Updates) {
|
|
1070
|
+
for (const update of result.updates) {
|
|
1071
|
+
if (update instanceof types.UpdateNewMessage) {
|
|
1072
|
+
return constructMessage(update.message[as](types.Message), this[getEntity].bind(this));
|
|
1073
|
+
}
|
|
1074
|
+
else if (update instanceof types.UpdateNewChannelMessage) {
|
|
1075
|
+
return constructMessage(update.message[as](types.Message), this[getEntity].bind(this));
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
else if (result instanceof types.UpdateShortSentMessage || result instanceof types.UpdateShortSentMessage) {
|
|
1080
|
+
const message = await this.getMessage(chatId, result.id);
|
|
1081
|
+
if (message != null) {
|
|
1082
|
+
return message;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
UNREACHABLE();
|
|
1086
|
+
}
|
|
1087
|
+
async getMessages(chatId, messageIds) {
|
|
1088
|
+
const peer = await this.getInputPeer(chatId);
|
|
1089
|
+
let messages_;
|
|
1090
|
+
if (peer instanceof types.InputPeerChannel) {
|
|
1091
|
+
messages_ = await this.invoke(new functions.ChannelsGetMessages({
|
|
1092
|
+
channel: new types.InputChannel({ channelId: peer.channelId, accessHash: peer.accessHash }),
|
|
1093
|
+
id: messageIds.map((v) => new types.InputMessageID({ id: v })),
|
|
1094
|
+
})).then((v) => v[as](types.MessagesMessages));
|
|
1095
|
+
}
|
|
1096
|
+
else {
|
|
1097
|
+
messages_ = await this.invoke(new functions.MessagesGetMessages({
|
|
1098
|
+
id: messageIds.map((v) => new types.InputMessageID({ id: v })),
|
|
1099
|
+
})).then((v) => v[as](types.MessagesMessages));
|
|
1100
|
+
}
|
|
1101
|
+
const messages = new Array();
|
|
1102
|
+
for (const message_ of messages_.messages) {
|
|
1103
|
+
messages.push(await constructMessage(message_[as](types.Message), this[getEntity].bind(this)));
|
|
1104
|
+
}
|
|
1105
|
+
return messages;
|
|
1106
|
+
}
|
|
1107
|
+
async getMessage(chatId, messageId) {
|
|
1108
|
+
const messages = await this.getMessages(chatId, [messageId]);
|
|
1109
|
+
return messages[0] ?? null;
|
|
653
1110
|
}
|
|
654
1111
|
}
|