@mtkruto/node 0.0.977 → 0.0.979
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/3_client.d.ts +106 -18
- package/esm/client/3_client.js +193 -142
- package/esm/constants.d.ts +1 -1
- package/esm/constants.js +1 -1
- package/esm/utilities/1_misc.d.ts +1 -0
- package/esm/utilities/1_misc.js +7 -0
- package/package.json +1 -1
- package/script/client/3_client.d.ts +106 -18
- package/script/client/3_client.js +192 -141
- package/script/constants.d.ts +1 -1
- package/script/constants.js +1 -1
- package/script/utilities/1_misc.d.ts +1 -0
- package/script/utilities/1_misc.js +9 -1
package/esm/client/3_client.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare enum ParseMode {
|
|
|
23
23
|
export interface AuthorizeUserParams<S = string> {
|
|
24
24
|
phone: S | (() => MaybePromise<S>);
|
|
25
25
|
code: S | (() => MaybePromise<S>);
|
|
26
|
-
password: S | (() => MaybePromise<S>);
|
|
26
|
+
password: S | ((hint: string | null) => MaybePromise<S>);
|
|
27
27
|
}
|
|
28
28
|
export type UpdateHandler = null | ((client: Client, update: types.TypeUpdate) => MaybePromise<void>);
|
|
29
29
|
export interface ClientParams {
|
|
@@ -68,12 +68,69 @@ export interface ClientParams {
|
|
|
68
68
|
*/
|
|
69
69
|
autoStart?: boolean;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* A chat identifier as provided by MTKruto or a string starting with a @ that is followed by a username.
|
|
73
|
+
*/
|
|
74
|
+
export type ChatID = number | string;
|
|
75
|
+
export interface SendMessagesParams {
|
|
76
|
+
/**
|
|
77
|
+
* The parse mode to use. If not provided, the default parse mode will be used.
|
|
78
|
+
*/
|
|
79
|
+
parseMode?: ParseMode;
|
|
80
|
+
/**
|
|
81
|
+
* The message's entities.
|
|
82
|
+
*/
|
|
83
|
+
entities?: MessageEntity[];
|
|
84
|
+
/**
|
|
85
|
+
* Whether to disable web page previews in the message that is to be sent.
|
|
86
|
+
*/
|
|
87
|
+
disableWebPagePreview?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Whether to send the message in a silent way without making a sound on the recipients' clients.
|
|
90
|
+
*/
|
|
91
|
+
disableNotification?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Whether to protect the contents of the message from copying and forwarding.
|
|
94
|
+
*/
|
|
95
|
+
protectContent?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* The identifier of a message to reply to.
|
|
98
|
+
*/
|
|
99
|
+
replyToMessageId?: number;
|
|
100
|
+
/**
|
|
101
|
+
* The identifier of a thread to send the message to.
|
|
102
|
+
*/
|
|
103
|
+
messageThreadId?: number;
|
|
104
|
+
/**
|
|
105
|
+
* The identifier of the chat to send the message on behalf of.
|
|
106
|
+
*/
|
|
107
|
+
sendAs?: ChatID;
|
|
108
|
+
/**
|
|
109
|
+
* The reply markup of the message.
|
|
110
|
+
*/
|
|
111
|
+
replyMarkup?: InlineKeyboardMarkup | ReplyKeyboardMarkup | ReplyKeyboardRemove | ForceReply;
|
|
112
|
+
}
|
|
71
113
|
export interface ForwardMessagesParams {
|
|
72
114
|
messageThreadId?: number;
|
|
115
|
+
/**
|
|
116
|
+
* Whether to forward the message in a silent way without making a sound on the recipients' clients.
|
|
117
|
+
*/
|
|
73
118
|
disableNotification?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Whether to protect the contents of the forwarded message from copying and forwarding.
|
|
121
|
+
*/
|
|
74
122
|
protectContent?: boolean;
|
|
75
|
-
|
|
123
|
+
/**
|
|
124
|
+
* The identifier of the chat to forward the message on behalf of.
|
|
125
|
+
*/
|
|
126
|
+
sendAs?: ChatID;
|
|
127
|
+
/**
|
|
128
|
+
* Whether to not include the original sender of the message that is going to be forwarded.
|
|
129
|
+
*/
|
|
76
130
|
dropSenderName?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Whether to not include the original caption of the message that is going to be forwarded.
|
|
133
|
+
*/
|
|
77
134
|
dropCaption?: boolean;
|
|
78
135
|
}
|
|
79
136
|
export declare class Client extends ClientAbstract {
|
|
@@ -178,22 +235,53 @@ export declare class Client extends ClientAbstract {
|
|
|
178
235
|
[getEntity](peer: types.PeerChannel): Promise<types.Channel | null>;
|
|
179
236
|
processResult(result: ReadObject): Promise<void>;
|
|
180
237
|
private updatesToMessages;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
238
|
+
/**
|
|
239
|
+
* Send a text message.
|
|
240
|
+
*
|
|
241
|
+
* @param chatId The chat to send the message to.
|
|
242
|
+
* @param text The message's text.
|
|
243
|
+
*/
|
|
244
|
+
sendMessage(chatId: ChatID, text: string, params?: SendMessagesParams): Promise<Message>;
|
|
245
|
+
/**
|
|
246
|
+
* Retrieve multiple messages.
|
|
247
|
+
*
|
|
248
|
+
* @param chatId The identifier of the chat to retrieve the messages from.
|
|
249
|
+
* @param messageIds The identifiers of the messages to retrieve.
|
|
250
|
+
*/
|
|
251
|
+
getMessages(chatId_: ChatID, messageIds: number[]): Promise<Omit<Message, "replyToMessage">[]>;
|
|
252
|
+
/**
|
|
253
|
+
* Retrieve a single message.
|
|
254
|
+
*
|
|
255
|
+
* @param chatId The identifier of the chat to retrieve the message from.
|
|
256
|
+
* @param messageId The identifier of the message to retrieve.
|
|
257
|
+
*/
|
|
258
|
+
getMessage(chatId: ChatID, messageId: number): Promise<Omit<Message, "replyToMessage"> | null>;
|
|
194
259
|
private downloadInner;
|
|
195
|
-
|
|
260
|
+
/**
|
|
261
|
+
* Download a file.
|
|
262
|
+
*
|
|
263
|
+
* @param fileId The identifier of the file to download.
|
|
264
|
+
*/
|
|
265
|
+
download(fileId: string): Promise<AsyncGenerator<Uint8Array, void, unknown>>;
|
|
196
266
|
[getStickerSetName](inputStickerSet: types.InputStickerSetID, hash?: number): Promise<string>;
|
|
197
|
-
|
|
198
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Forward multiple messages.
|
|
269
|
+
*
|
|
270
|
+
* @param from The identifier of the chat to forward the messages from.
|
|
271
|
+
* @param to The identifier of the chat to forward the messages to.
|
|
272
|
+
* @param messageIds The identifiers of the messages to forward.
|
|
273
|
+
*/
|
|
274
|
+
forwardMessages(from: ChatID, to: ChatID, messageIds: number[], params?: ForwardMessagesParams): Promise<Message[]>;
|
|
275
|
+
/**
|
|
276
|
+
* Forward a single message.
|
|
277
|
+
*
|
|
278
|
+
* @param from The identifier of the chat to forward the message from.
|
|
279
|
+
* @param to The identifier of the chat to forward the message to.
|
|
280
|
+
* @param messageId The identifier of the message to forward.
|
|
281
|
+
*/
|
|
282
|
+
forwardMessage(from: ChatID, to: ChatID, messageId: number, params?: ForwardMessagesParams): Promise<Message>;
|
|
283
|
+
/**
|
|
284
|
+
* Get information on the currently authorized user.
|
|
285
|
+
*/
|
|
286
|
+
getMe(): Promise<import("../types/1_user.js").User>;
|
|
199
287
|
}
|
package/esm/client/3_client.js
CHANGED
|
@@ -23,9 +23,9 @@ import { parseHtml } from "./0_html.js";
|
|
|
23
23
|
import { checkPassword } from "./0_password.js";
|
|
24
24
|
import { ClientAbstract } from "./1_client_abstract.js";
|
|
25
25
|
import { ClientPlain } from "./2_client_plain.js";
|
|
26
|
-
import { drop } from "../utilities/1_misc.js";
|
|
26
|
+
import { drop, mustPrompt, mustPromptOneOf } from "../utilities/1_misc.js";
|
|
27
27
|
import { getChannelChatId, peerToChatId } from "./0_utilities.js";
|
|
28
|
-
import {
|
|
28
|
+
import { constructUser } from "../types/1_user.js";
|
|
29
29
|
const d = debug("Client");
|
|
30
30
|
const dGap = debug("Client/recoverUpdateGap");
|
|
31
31
|
const dGapC = debug("Client/recoverChannelUpdateGap");
|
|
@@ -318,65 +318,32 @@ export class Client extends ClientAbstract {
|
|
|
318
318
|
throw new Error("apiHash not set");
|
|
319
319
|
}
|
|
320
320
|
if (typeof params === "undefined") {
|
|
321
|
-
const
|
|
322
|
-
if (
|
|
323
|
-
params =
|
|
324
|
-
phone: phoneNumberOrBotToken,
|
|
325
|
-
code: () => String(mustPromptNumber("Enter the verification code:")),
|
|
326
|
-
password: () => mustPrompt("Enter the account password:"),
|
|
327
|
-
};
|
|
321
|
+
const loginType = mustPromptOneOf("Do you want to login as bot [b] or user [u]?", ["b", "u"]);
|
|
322
|
+
if (loginType == "b") {
|
|
323
|
+
params = mustPrompt("Bot token:");
|
|
328
324
|
}
|
|
329
325
|
else {
|
|
330
|
-
params =
|
|
326
|
+
params = { phone: () => mustPrompt("Phone number:"), code: () => mustPrompt("Verification code:"), password: () => mustPrompt(`Password:`) };
|
|
331
327
|
}
|
|
332
328
|
}
|
|
333
329
|
dAuth("authorizing with %s", typeof params === "string" ? "bot token" : params instanceof types.AuthExportedAuthorization ? "exported authorization" : "AuthorizeUserParams");
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
params = params;
|
|
350
|
-
if (err instanceof types.RPCError && err.errorMessage == "SESSION_PASSWORD_NEEDED") {
|
|
351
|
-
while (true) {
|
|
352
|
-
const ap = await this.invoke(new functions.AccountGetPassword());
|
|
353
|
-
if (ap.currentAlgo instanceof types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) {
|
|
354
|
-
try {
|
|
355
|
-
const password = typeof params.password === "string" ? params.password : await params.password();
|
|
356
|
-
const input = await checkPassword(password, ap);
|
|
357
|
-
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
358
|
-
await this.storage.setAccountType("user");
|
|
359
|
-
dAuth("authorized as user");
|
|
360
|
-
break;
|
|
361
|
-
}
|
|
362
|
-
catch (err) {
|
|
363
|
-
if (err instanceof types.RPCError && err.errorMessage == "PASSWORD_HASH_INVALID") {
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
throw err;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
throw new Error(`Handling ${ap.currentAlgo?.constructor.name} not implemented`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
throw err;
|
|
378
|
-
}
|
|
330
|
+
const initConnection = async () => {
|
|
331
|
+
await this.invoke(new functions.InitConnection({
|
|
332
|
+
apiId: this.apiId,
|
|
333
|
+
appVersion: this.appVersion,
|
|
334
|
+
deviceModel: this.deviceModel,
|
|
335
|
+
langCode: this.langCode,
|
|
336
|
+
langPack: this.langPack,
|
|
337
|
+
query: new functions.InvokeWithLayer({
|
|
338
|
+
layer: LAYER,
|
|
339
|
+
query: new functions.HelpGetConfig(),
|
|
340
|
+
}),
|
|
341
|
+
systemLangCode: this.systemLangCode,
|
|
342
|
+
systemVersion: this.systemVersion,
|
|
343
|
+
}));
|
|
344
|
+
d("connection inited");
|
|
379
345
|
};
|
|
346
|
+
await initConnection();
|
|
380
347
|
try {
|
|
381
348
|
await this.fetchState("authorize");
|
|
382
349
|
d("already authorized");
|
|
@@ -387,102 +354,129 @@ export class Client extends ClientAbstract {
|
|
|
387
354
|
throw err;
|
|
388
355
|
}
|
|
389
356
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
phoneNumber = typeof params.phone === "string" ? params.phone : await params.phone();
|
|
405
|
-
const sentCode = await this.invoke(new functions.AuthSendCode({
|
|
406
|
-
apiId: this.apiId,
|
|
407
|
-
apiHash: this.apiHash,
|
|
408
|
-
phoneNumber,
|
|
409
|
-
settings: new types.CodeSettings({}),
|
|
410
|
-
}));
|
|
411
|
-
dAuth("verification code sent");
|
|
412
|
-
if (sentCode instanceof types.AuthSentCode) {
|
|
413
|
-
while (true) {
|
|
414
|
-
const phoneCode = typeof params.code === "string" ? params.code : await params.code();
|
|
415
|
-
try {
|
|
416
|
-
const auth = await this.invoke(new functions.AuthSignIn({ phoneNumber, phoneCode, phoneCodeHash: sentCode.phoneCodeHash }));
|
|
417
|
-
if (auth instanceof types.AuthAuthorizationSignUpRequired) {
|
|
418
|
-
throw new Error("Sign up not supported");
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
signedIn = true;
|
|
422
|
-
await this.storage.setAccountType("user");
|
|
423
|
-
dAuth("authorized as user");
|
|
424
|
-
break;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
catch (err) {
|
|
428
|
-
if (err instanceof types.RPCError && err.errorMessage == "PHONE_CODE_INVALID") {
|
|
429
|
-
continue;
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
throw err;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
throw new Error(`Handling ${sentCode.constructor.name} not implemented`);
|
|
439
|
-
}
|
|
357
|
+
if (typeof params === "string") {
|
|
358
|
+
while (true) {
|
|
359
|
+
try {
|
|
360
|
+
await this.invoke(new functions.AuthImportBotAuthorization({ apiId: this.apiId, apiHash: this.apiHash, botAuthToken: params, flags: 0 }));
|
|
361
|
+
await this.storage.setAccountType("bot");
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
if (err instanceof types.RPCError) {
|
|
366
|
+
const match = err.errorMessage.match(/MIGRATE_(\d)$/);
|
|
367
|
+
if (match) {
|
|
368
|
+
await this[handleMigrationError](err);
|
|
369
|
+
await initConnection();
|
|
370
|
+
continue;
|
|
440
371
|
}
|
|
441
|
-
|
|
442
|
-
|
|
372
|
+
else {
|
|
373
|
+
throw err;
|
|
443
374
|
}
|
|
444
375
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
376
|
+
else {
|
|
377
|
+
throw err;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
dAuth("authorized as bot");
|
|
382
|
+
await this.fetchState("authorize");
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
if (params instanceof types.AuthExportedAuthorization) {
|
|
386
|
+
await this.invoke(new functions.AuthImportAuthorization({ id: params.id, bytes: params.bytes }));
|
|
387
|
+
dAuth("authorization imported");
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
let phone;
|
|
391
|
+
let sentCode;
|
|
392
|
+
while (true) {
|
|
393
|
+
try {
|
|
394
|
+
phone = typeof params.phone === "string" ? params.phone : await params.phone();
|
|
395
|
+
const sendCode = () => this.invoke(new functions.AuthSendCode({
|
|
396
|
+
phoneNumber: phone,
|
|
397
|
+
apiId: this.apiId,
|
|
398
|
+
apiHash: this.apiHash,
|
|
399
|
+
settings: new types.CodeSettings(),
|
|
400
|
+
})).then((v) => v[as](types.AuthSentCode));
|
|
401
|
+
try {
|
|
402
|
+
sentCode = await sendCode();
|
|
403
|
+
}
|
|
404
|
+
catch (err) {
|
|
405
|
+
if (err instanceof types.RPCError) {
|
|
406
|
+
const match = err.errorMessage.match(/MIGRATE_(\d)$/);
|
|
407
|
+
if (match) {
|
|
408
|
+
await this[handleMigrationError](err);
|
|
409
|
+
await initConnection();
|
|
410
|
+
sentCode = await sendCode();
|
|
448
411
|
}
|
|
449
412
|
else {
|
|
450
413
|
throw err;
|
|
451
414
|
}
|
|
452
415
|
}
|
|
416
|
+
else {
|
|
417
|
+
throw err;
|
|
418
|
+
}
|
|
453
419
|
}
|
|
420
|
+
break;
|
|
454
421
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
422
|
+
catch (err) {
|
|
423
|
+
if (err instanceof types.RPCError && err.errorMessage == "PHONE_NUMBER_INVALID") {
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
throw err;
|
|
428
|
+
}
|
|
459
429
|
}
|
|
460
430
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
431
|
+
dAuth("verification code sent");
|
|
432
|
+
let err;
|
|
433
|
+
while (true) {
|
|
434
|
+
const code = typeof params.code === "string" ? params.code : await params.code();
|
|
435
|
+
try {
|
|
436
|
+
await this.invoke(new functions.AuthSignIn({
|
|
437
|
+
phoneNumber: phone,
|
|
438
|
+
phoneCode: code,
|
|
439
|
+
phoneCodeHash: sentCode.phoneCodeHash,
|
|
440
|
+
}));
|
|
441
|
+
await this.storage.setAccountType("user");
|
|
442
|
+
dAuth("authorized as user");
|
|
443
|
+
await this.fetchState("authorize");
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
catch (err_) {
|
|
447
|
+
if (err_ instanceof types.RPCError && err_.errorMessage == "PHONE_CODE_INVALID") {
|
|
448
|
+
continue;
|
|
471
449
|
}
|
|
472
450
|
else {
|
|
473
|
-
|
|
451
|
+
err = err_;
|
|
452
|
+
break;
|
|
474
453
|
}
|
|
475
454
|
}
|
|
476
|
-
else {
|
|
477
|
-
throw err;
|
|
478
|
-
}
|
|
479
455
|
}
|
|
480
|
-
|
|
456
|
+
if (!(err instanceof types.RPCError && err.errorMessage == "SESSION_PASSWORD_NEEDED")) {
|
|
457
|
+
throw err;
|
|
458
|
+
}
|
|
459
|
+
while (true) {
|
|
460
|
+
const ap = await this.invoke(new functions.AccountGetPassword());
|
|
461
|
+
if (!(ap.currentAlgo instanceof types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow)) {
|
|
462
|
+
throw new Error(`Handling ${ap.currentAlgo?.constructor.name} not implemented`);
|
|
463
|
+
}
|
|
481
464
|
try {
|
|
465
|
+
const password = typeof params.password === "string" ? params.password : await params.password(ap.hint ?? null);
|
|
466
|
+
const input = await checkPassword(password, ap);
|
|
467
|
+
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
468
|
+
await this.storage.setAccountType("user");
|
|
469
|
+
dAuth("authorized as user");
|
|
482
470
|
await this.fetchState("authorize");
|
|
471
|
+
break;
|
|
483
472
|
}
|
|
484
|
-
catch (
|
|
485
|
-
|
|
473
|
+
catch (err) {
|
|
474
|
+
if (err instanceof types.RPCError && err.errorMessage == "PASSWORD_HASH_INVALID") {
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
throw err;
|
|
479
|
+
}
|
|
486
480
|
}
|
|
487
481
|
}
|
|
488
482
|
}
|
|
@@ -491,6 +485,16 @@ export class Client extends ClientAbstract {
|
|
|
491
485
|
*/
|
|
492
486
|
async start(params) {
|
|
493
487
|
await this.connect();
|
|
488
|
+
try {
|
|
489
|
+
await this.fetchState("authorize");
|
|
490
|
+
d("already authorized");
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
catch (err) {
|
|
494
|
+
if (!(err instanceof types.RPCError) || err.errorMessage != "AUTH_KEY_UNREGISTERED") {
|
|
495
|
+
throw err;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
494
498
|
await this.authorize(params);
|
|
495
499
|
}
|
|
496
500
|
async receiveLoop() {
|
|
@@ -1142,6 +1146,12 @@ export class Client extends ClientAbstract {
|
|
|
1142
1146
|
}
|
|
1143
1147
|
return messages;
|
|
1144
1148
|
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Send a text message.
|
|
1151
|
+
*
|
|
1152
|
+
* @param chatId The chat to send the message to.
|
|
1153
|
+
* @param text The message's text.
|
|
1154
|
+
*/
|
|
1145
1155
|
async sendMessage(chatId, text, params) {
|
|
1146
1156
|
const entities_ = params?.entities ?? [];
|
|
1147
1157
|
const parseMode = params?.parseMode ?? this.parseMode;
|
|
@@ -1201,6 +1211,12 @@ export class Client extends ClientAbstract {
|
|
|
1201
1211
|
}));
|
|
1202
1212
|
return await this.updatesToMessages(chatId, result).then((v) => v[0]);
|
|
1203
1213
|
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Retrieve multiple messages.
|
|
1216
|
+
*
|
|
1217
|
+
* @param chatId The identifier of the chat to retrieve the messages from.
|
|
1218
|
+
* @param messageIds The identifiers of the messages to retrieve.
|
|
1219
|
+
*/
|
|
1204
1220
|
async getMessages(chatId_, messageIds) {
|
|
1205
1221
|
const peer = await this.getInputPeer(chatId_);
|
|
1206
1222
|
let messages_ = new Array();
|
|
@@ -1236,6 +1252,12 @@ export class Client extends ClientAbstract {
|
|
|
1236
1252
|
}
|
|
1237
1253
|
return messages;
|
|
1238
1254
|
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Retrieve a single message.
|
|
1257
|
+
*
|
|
1258
|
+
* @param chatId The identifier of the chat to retrieve the message from.
|
|
1259
|
+
* @param messageId The identifier of the message to retrieve.
|
|
1260
|
+
*/
|
|
1239
1261
|
async getMessage(chatId, messageId) {
|
|
1240
1262
|
const messages = await this.getMessages(chatId, [messageId]);
|
|
1241
1263
|
return messages[0] ?? null;
|
|
@@ -1279,24 +1301,29 @@ export class Client extends ClientAbstract {
|
|
|
1279
1301
|
}
|
|
1280
1302
|
}
|
|
1281
1303
|
}
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1304
|
+
/**
|
|
1305
|
+
* Download a file.
|
|
1306
|
+
*
|
|
1307
|
+
* @param fileId The identifier of the file to download.
|
|
1308
|
+
*/
|
|
1309
|
+
async download(fileId) {
|
|
1310
|
+
const fileId_ = FileID.decode(fileId);
|
|
1311
|
+
switch (fileId_.fileType) {
|
|
1285
1312
|
case FileType.ChatPhoto: {
|
|
1286
|
-
const big =
|
|
1287
|
-
const peer = await this.getInputPeer(
|
|
1288
|
-
const location = new types.InputPeerPhotoFileLocation({ big: big ? true : undefined, peer, photoId:
|
|
1313
|
+
const big = fileId_.params.thumbnailSource == ThumbnailSource.ChatPhotoBig;
|
|
1314
|
+
const peer = await this.getInputPeer(fileId_.params.chatId);
|
|
1315
|
+
const location = new types.InputPeerPhotoFileLocation({ big: big ? true : undefined, peer, photoId: fileId_.params.mediaId });
|
|
1289
1316
|
return this.downloadInner(location);
|
|
1290
1317
|
}
|
|
1291
1318
|
case FileType.Photo: {
|
|
1292
|
-
if (
|
|
1319
|
+
if (fileId_.params.mediaId == undefined || fileId_.params.accessHash == undefined || fileId_.params.fileReference == undefined || fileId_.params.thumbnailSize == undefined) {
|
|
1293
1320
|
UNREACHABLE();
|
|
1294
1321
|
}
|
|
1295
1322
|
const location = new types.InputPhotoFileLocation({
|
|
1296
|
-
id:
|
|
1297
|
-
accessHash:
|
|
1298
|
-
fileReference:
|
|
1299
|
-
thumbSize:
|
|
1323
|
+
id: fileId_.params.mediaId,
|
|
1324
|
+
accessHash: fileId_.params.accessHash,
|
|
1325
|
+
fileReference: fileId_.params.fileReference,
|
|
1326
|
+
thumbSize: fileId_.params.thumbnailSize,
|
|
1300
1327
|
});
|
|
1301
1328
|
return this.downloadInner(location);
|
|
1302
1329
|
}
|
|
@@ -1316,6 +1343,13 @@ export class Client extends ClientAbstract {
|
|
|
1316
1343
|
return name;
|
|
1317
1344
|
}
|
|
1318
1345
|
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Forward multiple messages.
|
|
1348
|
+
*
|
|
1349
|
+
* @param from The identifier of the chat to forward the messages from.
|
|
1350
|
+
* @param to The identifier of the chat to forward the messages to.
|
|
1351
|
+
* @param messageIds The identifiers of the messages to forward.
|
|
1352
|
+
*/
|
|
1319
1353
|
async forwardMessages(from, to, messageIds, params) {
|
|
1320
1354
|
const result = await this.invoke(new functions.MessagesForwardMessages({
|
|
1321
1355
|
fromPeer: await this.getInputPeer(from),
|
|
@@ -1331,7 +1365,24 @@ export class Client extends ClientAbstract {
|
|
|
1331
1365
|
}));
|
|
1332
1366
|
return await this.updatesToMessages(to, result);
|
|
1333
1367
|
}
|
|
1368
|
+
/**
|
|
1369
|
+
* Forward a single message.
|
|
1370
|
+
*
|
|
1371
|
+
* @param from The identifier of the chat to forward the message from.
|
|
1372
|
+
* @param to The identifier of the chat to forward the message to.
|
|
1373
|
+
* @param messageId The identifier of the message to forward.
|
|
1374
|
+
*/
|
|
1334
1375
|
async forwardMessage(from, to, messageId, params) {
|
|
1335
1376
|
return await this.forwardMessages(from, to, [messageId], params).then((v) => v[0]);
|
|
1336
1377
|
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Get information on the currently authorized user.
|
|
1380
|
+
*/
|
|
1381
|
+
async getMe() {
|
|
1382
|
+
const users = await this.invoke(new functions.UsersGetUsers({ id: [new types.InputUserSelf()] }));
|
|
1383
|
+
if (users.length < 1) {
|
|
1384
|
+
UNREACHABLE();
|
|
1385
|
+
}
|
|
1386
|
+
return constructUser(users[0][as](types.User));
|
|
1387
|
+
}
|
|
1337
1388
|
}
|
package/esm/constants.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare const PUBLIC_KEYS: PublicKeys;
|
|
|
5
5
|
export declare const VECTOR_CONSTRUCTOR = 481674261;
|
|
6
6
|
export declare const INITIAL_DC: DC;
|
|
7
7
|
export declare const LAYER = 160;
|
|
8
|
-
export declare const APP_VERSION = "MTKruto 0.0.
|
|
8
|
+
export declare const APP_VERSION = "MTKruto 0.0.979";
|
|
9
9
|
export declare const DEVICE_MODEL: string;
|
|
10
10
|
export declare const LANG_CODE: string;
|
|
11
11
|
export declare const LANG_PACK = "";
|
package/esm/constants.js
CHANGED
|
@@ -54,7 +54,7 @@ export const PUBLIC_KEYS = Object.freeze([
|
|
|
54
54
|
export const VECTOR_CONSTRUCTOR = 0x1CB5C415;
|
|
55
55
|
export const INITIAL_DC = "2-test";
|
|
56
56
|
export const LAYER = 160;
|
|
57
|
-
export const APP_VERSION = "MTKruto 0.0.
|
|
57
|
+
export const APP_VERSION = "MTKruto 0.0.979";
|
|
58
58
|
// @ts-ignore: lib
|
|
59
59
|
export const DEVICE_MODEL = typeof dntShim.Deno === "undefined" ? typeof navigator === "undefined" ? typeof process === "undefined" ? "Unknown" : process.platform + "-" + process.arch : navigator.userAgent.split(" ")[0] : dntShim.Deno.build.os + "-" + dntShim.Deno.build.arch;
|
|
60
60
|
export const LANG_CODE = typeof navigator === "undefined" ? "en" : navigator.language.split("-")[0];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function drop<T>(promise: Promise<T>): void;
|
|
2
2
|
export declare function mustPrompt(message: string): string;
|
|
3
3
|
export declare function mustPromptNumber(message: string): number;
|
|
4
|
+
export declare function mustPromptOneOf<T extends readonly string[]>(message: string, choices: T): T[number];
|
package/esm/utilities/1_misc.js
CHANGED
|
@@ -19,3 +19,10 @@ export function mustPromptNumber(message) {
|
|
|
19
19
|
}
|
|
20
20
|
return result;
|
|
21
21
|
}
|
|
22
|
+
export function mustPromptOneOf(message, choices) {
|
|
23
|
+
let result = prompt(message);
|
|
24
|
+
while (result == null || !choices.includes(result)) {
|
|
25
|
+
result = prompt(message);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -23,7 +23,7 @@ export declare enum ParseMode {
|
|
|
23
23
|
export interface AuthorizeUserParams<S = string> {
|
|
24
24
|
phone: S | (() => MaybePromise<S>);
|
|
25
25
|
code: S | (() => MaybePromise<S>);
|
|
26
|
-
password: S | (() => MaybePromise<S>);
|
|
26
|
+
password: S | ((hint: string | null) => MaybePromise<S>);
|
|
27
27
|
}
|
|
28
28
|
export type UpdateHandler = null | ((client: Client, update: types.TypeUpdate) => MaybePromise<void>);
|
|
29
29
|
export interface ClientParams {
|
|
@@ -68,12 +68,69 @@ export interface ClientParams {
|
|
|
68
68
|
*/
|
|
69
69
|
autoStart?: boolean;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* A chat identifier as provided by MTKruto or a string starting with a @ that is followed by a username.
|
|
73
|
+
*/
|
|
74
|
+
export type ChatID = number | string;
|
|
75
|
+
export interface SendMessagesParams {
|
|
76
|
+
/**
|
|
77
|
+
* The parse mode to use. If not provided, the default parse mode will be used.
|
|
78
|
+
*/
|
|
79
|
+
parseMode?: ParseMode;
|
|
80
|
+
/**
|
|
81
|
+
* The message's entities.
|
|
82
|
+
*/
|
|
83
|
+
entities?: MessageEntity[];
|
|
84
|
+
/**
|
|
85
|
+
* Whether to disable web page previews in the message that is to be sent.
|
|
86
|
+
*/
|
|
87
|
+
disableWebPagePreview?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Whether to send the message in a silent way without making a sound on the recipients' clients.
|
|
90
|
+
*/
|
|
91
|
+
disableNotification?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Whether to protect the contents of the message from copying and forwarding.
|
|
94
|
+
*/
|
|
95
|
+
protectContent?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* The identifier of a message to reply to.
|
|
98
|
+
*/
|
|
99
|
+
replyToMessageId?: number;
|
|
100
|
+
/**
|
|
101
|
+
* The identifier of a thread to send the message to.
|
|
102
|
+
*/
|
|
103
|
+
messageThreadId?: number;
|
|
104
|
+
/**
|
|
105
|
+
* The identifier of the chat to send the message on behalf of.
|
|
106
|
+
*/
|
|
107
|
+
sendAs?: ChatID;
|
|
108
|
+
/**
|
|
109
|
+
* The reply markup of the message.
|
|
110
|
+
*/
|
|
111
|
+
replyMarkup?: InlineKeyboardMarkup | ReplyKeyboardMarkup | ReplyKeyboardRemove | ForceReply;
|
|
112
|
+
}
|
|
71
113
|
export interface ForwardMessagesParams {
|
|
72
114
|
messageThreadId?: number;
|
|
115
|
+
/**
|
|
116
|
+
* Whether to forward the message in a silent way without making a sound on the recipients' clients.
|
|
117
|
+
*/
|
|
73
118
|
disableNotification?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Whether to protect the contents of the forwarded message from copying and forwarding.
|
|
121
|
+
*/
|
|
74
122
|
protectContent?: boolean;
|
|
75
|
-
|
|
123
|
+
/**
|
|
124
|
+
* The identifier of the chat to forward the message on behalf of.
|
|
125
|
+
*/
|
|
126
|
+
sendAs?: ChatID;
|
|
127
|
+
/**
|
|
128
|
+
* Whether to not include the original sender of the message that is going to be forwarded.
|
|
129
|
+
*/
|
|
76
130
|
dropSenderName?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Whether to not include the original caption of the message that is going to be forwarded.
|
|
133
|
+
*/
|
|
77
134
|
dropCaption?: boolean;
|
|
78
135
|
}
|
|
79
136
|
export declare class Client extends ClientAbstract {
|
|
@@ -178,22 +235,53 @@ export declare class Client extends ClientAbstract {
|
|
|
178
235
|
[getEntity](peer: types.PeerChannel): Promise<types.Channel | null>;
|
|
179
236
|
processResult(result: ReadObject): Promise<void>;
|
|
180
237
|
private updatesToMessages;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
238
|
+
/**
|
|
239
|
+
* Send a text message.
|
|
240
|
+
*
|
|
241
|
+
* @param chatId The chat to send the message to.
|
|
242
|
+
* @param text The message's text.
|
|
243
|
+
*/
|
|
244
|
+
sendMessage(chatId: ChatID, text: string, params?: SendMessagesParams): Promise<Message>;
|
|
245
|
+
/**
|
|
246
|
+
* Retrieve multiple messages.
|
|
247
|
+
*
|
|
248
|
+
* @param chatId The identifier of the chat to retrieve the messages from.
|
|
249
|
+
* @param messageIds The identifiers of the messages to retrieve.
|
|
250
|
+
*/
|
|
251
|
+
getMessages(chatId_: ChatID, messageIds: number[]): Promise<Omit<Message, "replyToMessage">[]>;
|
|
252
|
+
/**
|
|
253
|
+
* Retrieve a single message.
|
|
254
|
+
*
|
|
255
|
+
* @param chatId The identifier of the chat to retrieve the message from.
|
|
256
|
+
* @param messageId The identifier of the message to retrieve.
|
|
257
|
+
*/
|
|
258
|
+
getMessage(chatId: ChatID, messageId: number): Promise<Omit<Message, "replyToMessage"> | null>;
|
|
194
259
|
private downloadInner;
|
|
195
|
-
|
|
260
|
+
/**
|
|
261
|
+
* Download a file.
|
|
262
|
+
*
|
|
263
|
+
* @param fileId The identifier of the file to download.
|
|
264
|
+
*/
|
|
265
|
+
download(fileId: string): Promise<AsyncGenerator<Uint8Array, void, unknown>>;
|
|
196
266
|
[getStickerSetName](inputStickerSet: types.InputStickerSetID, hash?: number): Promise<string>;
|
|
197
|
-
|
|
198
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Forward multiple messages.
|
|
269
|
+
*
|
|
270
|
+
* @param from The identifier of the chat to forward the messages from.
|
|
271
|
+
* @param to The identifier of the chat to forward the messages to.
|
|
272
|
+
* @param messageIds The identifiers of the messages to forward.
|
|
273
|
+
*/
|
|
274
|
+
forwardMessages(from: ChatID, to: ChatID, messageIds: number[], params?: ForwardMessagesParams): Promise<Message[]>;
|
|
275
|
+
/**
|
|
276
|
+
* Forward a single message.
|
|
277
|
+
*
|
|
278
|
+
* @param from The identifier of the chat to forward the message from.
|
|
279
|
+
* @param to The identifier of the chat to forward the message to.
|
|
280
|
+
* @param messageId The identifier of the message to forward.
|
|
281
|
+
*/
|
|
282
|
+
forwardMessage(from: ChatID, to: ChatID, messageId: number, params?: ForwardMessagesParams): Promise<Message>;
|
|
283
|
+
/**
|
|
284
|
+
* Get information on the currently authorized user.
|
|
285
|
+
*/
|
|
286
|
+
getMe(): Promise<import("../types/1_user.js").User>;
|
|
199
287
|
}
|
|
@@ -51,7 +51,7 @@ const _1_client_abstract_js_1 = require("./1_client_abstract.js");
|
|
|
51
51
|
const _2_client_plain_js_1 = require("./2_client_plain.js");
|
|
52
52
|
const _1_misc_js_1 = require("../utilities/1_misc.js");
|
|
53
53
|
const _0_utilities_js_1 = require("./0_utilities.js");
|
|
54
|
-
const
|
|
54
|
+
const _1_user_js_1 = require("../types/1_user.js");
|
|
55
55
|
const d = (0, deps_js_1.debug)("Client");
|
|
56
56
|
const dGap = (0, deps_js_1.debug)("Client/recoverUpdateGap");
|
|
57
57
|
const dGapC = (0, deps_js_1.debug)("Client/recoverChannelUpdateGap");
|
|
@@ -344,65 +344,32 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
344
344
|
throw new Error("apiHash not set");
|
|
345
345
|
}
|
|
346
346
|
if (typeof params === "undefined") {
|
|
347
|
-
const
|
|
348
|
-
if (
|
|
349
|
-
params =
|
|
350
|
-
phone: phoneNumberOrBotToken,
|
|
351
|
-
code: () => String((0, _1_misc_js_2.mustPromptNumber)("Enter the verification code:")),
|
|
352
|
-
password: () => (0, _1_misc_js_2.mustPrompt)("Enter the account password:"),
|
|
353
|
-
};
|
|
347
|
+
const loginType = (0, _1_misc_js_1.mustPromptOneOf)("Do you want to login as bot [b] or user [u]?", ["b", "u"]);
|
|
348
|
+
if (loginType == "b") {
|
|
349
|
+
params = (0, _1_misc_js_1.mustPrompt)("Bot token:");
|
|
354
350
|
}
|
|
355
351
|
else {
|
|
356
|
-
params =
|
|
352
|
+
params = { phone: () => (0, _1_misc_js_1.mustPrompt)("Phone number:"), code: () => (0, _1_misc_js_1.mustPrompt)("Verification code:"), password: () => (0, _1_misc_js_1.mustPrompt)(`Password:`) };
|
|
357
353
|
}
|
|
358
354
|
}
|
|
359
355
|
dAuth("authorizing with %s", typeof params === "string" ? "bot token" : params instanceof types.AuthExportedAuthorization ? "exported authorization" : "AuthorizeUserParams");
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
params = params;
|
|
376
|
-
if (err instanceof types.RPCError && err.errorMessage == "SESSION_PASSWORD_NEEDED") {
|
|
377
|
-
while (true) {
|
|
378
|
-
const ap = await this.invoke(new functions.AccountGetPassword());
|
|
379
|
-
if (ap.currentAlgo instanceof types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) {
|
|
380
|
-
try {
|
|
381
|
-
const password = typeof params.password === "string" ? params.password : await params.password();
|
|
382
|
-
const input = await (0, _0_password_js_1.checkPassword)(password, ap);
|
|
383
|
-
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
384
|
-
await this.storage.setAccountType("user");
|
|
385
|
-
dAuth("authorized as user");
|
|
386
|
-
break;
|
|
387
|
-
}
|
|
388
|
-
catch (err) {
|
|
389
|
-
if (err instanceof types.RPCError && err.errorMessage == "PASSWORD_HASH_INVALID") {
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
else {
|
|
393
|
-
throw err;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
else {
|
|
398
|
-
throw new Error(`Handling ${ap.currentAlgo?.constructor.name} not implemented`);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
throw err;
|
|
404
|
-
}
|
|
356
|
+
const initConnection = async () => {
|
|
357
|
+
await this.invoke(new functions.InitConnection({
|
|
358
|
+
apiId: this.apiId,
|
|
359
|
+
appVersion: this.appVersion,
|
|
360
|
+
deviceModel: this.deviceModel,
|
|
361
|
+
langCode: this.langCode,
|
|
362
|
+
langPack: this.langPack,
|
|
363
|
+
query: new functions.InvokeWithLayer({
|
|
364
|
+
layer: constants_js_1.LAYER,
|
|
365
|
+
query: new functions.HelpGetConfig(),
|
|
366
|
+
}),
|
|
367
|
+
systemLangCode: this.systemLangCode,
|
|
368
|
+
systemVersion: this.systemVersion,
|
|
369
|
+
}));
|
|
370
|
+
d("connection inited");
|
|
405
371
|
};
|
|
372
|
+
await initConnection();
|
|
406
373
|
try {
|
|
407
374
|
await this.fetchState("authorize");
|
|
408
375
|
d("already authorized");
|
|
@@ -413,102 +380,129 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
413
380
|
throw err;
|
|
414
381
|
}
|
|
415
382
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
phoneNumber = typeof params.phone === "string" ? params.phone : await params.phone();
|
|
431
|
-
const sentCode = await this.invoke(new functions.AuthSendCode({
|
|
432
|
-
apiId: this.apiId,
|
|
433
|
-
apiHash: this.apiHash,
|
|
434
|
-
phoneNumber,
|
|
435
|
-
settings: new types.CodeSettings({}),
|
|
436
|
-
}));
|
|
437
|
-
dAuth("verification code sent");
|
|
438
|
-
if (sentCode instanceof types.AuthSentCode) {
|
|
439
|
-
while (true) {
|
|
440
|
-
const phoneCode = typeof params.code === "string" ? params.code : await params.code();
|
|
441
|
-
try {
|
|
442
|
-
const auth = await this.invoke(new functions.AuthSignIn({ phoneNumber, phoneCode, phoneCodeHash: sentCode.phoneCodeHash }));
|
|
443
|
-
if (auth instanceof types.AuthAuthorizationSignUpRequired) {
|
|
444
|
-
throw new Error("Sign up not supported");
|
|
445
|
-
}
|
|
446
|
-
else {
|
|
447
|
-
signedIn = true;
|
|
448
|
-
await this.storage.setAccountType("user");
|
|
449
|
-
dAuth("authorized as user");
|
|
450
|
-
break;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
catch (err) {
|
|
454
|
-
if (err instanceof types.RPCError && err.errorMessage == "PHONE_CODE_INVALID") {
|
|
455
|
-
continue;
|
|
456
|
-
}
|
|
457
|
-
else {
|
|
458
|
-
throw err;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
throw new Error(`Handling ${sentCode.constructor.name} not implemented`);
|
|
465
|
-
}
|
|
383
|
+
if (typeof params === "string") {
|
|
384
|
+
while (true) {
|
|
385
|
+
try {
|
|
386
|
+
await this.invoke(new functions.AuthImportBotAuthorization({ apiId: this.apiId, apiHash: this.apiHash, botAuthToken: params, flags: 0 }));
|
|
387
|
+
await this.storage.setAccountType("bot");
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
catch (err) {
|
|
391
|
+
if (err instanceof types.RPCError) {
|
|
392
|
+
const match = err.errorMessage.match(/MIGRATE_(\d)$/);
|
|
393
|
+
if (match) {
|
|
394
|
+
await this[exports.handleMigrationError](err);
|
|
395
|
+
await initConnection();
|
|
396
|
+
continue;
|
|
466
397
|
}
|
|
467
|
-
|
|
468
|
-
|
|
398
|
+
else {
|
|
399
|
+
throw err;
|
|
469
400
|
}
|
|
470
401
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
402
|
+
else {
|
|
403
|
+
throw err;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
dAuth("authorized as bot");
|
|
408
|
+
await this.fetchState("authorize");
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (params instanceof types.AuthExportedAuthorization) {
|
|
412
|
+
await this.invoke(new functions.AuthImportAuthorization({ id: params.id, bytes: params.bytes }));
|
|
413
|
+
dAuth("authorization imported");
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
let phone;
|
|
417
|
+
let sentCode;
|
|
418
|
+
while (true) {
|
|
419
|
+
try {
|
|
420
|
+
phone = typeof params.phone === "string" ? params.phone : await params.phone();
|
|
421
|
+
const sendCode = () => this.invoke(new functions.AuthSendCode({
|
|
422
|
+
phoneNumber: phone,
|
|
423
|
+
apiId: this.apiId,
|
|
424
|
+
apiHash: this.apiHash,
|
|
425
|
+
settings: new types.CodeSettings(),
|
|
426
|
+
})).then((v) => v[_1_tl_object_js_1.as](types.AuthSentCode));
|
|
427
|
+
try {
|
|
428
|
+
sentCode = await sendCode();
|
|
429
|
+
}
|
|
430
|
+
catch (err) {
|
|
431
|
+
if (err instanceof types.RPCError) {
|
|
432
|
+
const match = err.errorMessage.match(/MIGRATE_(\d)$/);
|
|
433
|
+
if (match) {
|
|
434
|
+
await this[exports.handleMigrationError](err);
|
|
435
|
+
await initConnection();
|
|
436
|
+
sentCode = await sendCode();
|
|
474
437
|
}
|
|
475
438
|
else {
|
|
476
439
|
throw err;
|
|
477
440
|
}
|
|
478
441
|
}
|
|
442
|
+
else {
|
|
443
|
+
throw err;
|
|
444
|
+
}
|
|
479
445
|
}
|
|
446
|
+
break;
|
|
480
447
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
448
|
+
catch (err) {
|
|
449
|
+
if (err instanceof types.RPCError && err.errorMessage == "PHONE_NUMBER_INVALID") {
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
throw err;
|
|
454
|
+
}
|
|
485
455
|
}
|
|
486
456
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
457
|
+
dAuth("verification code sent");
|
|
458
|
+
let err;
|
|
459
|
+
while (true) {
|
|
460
|
+
const code = typeof params.code === "string" ? params.code : await params.code();
|
|
461
|
+
try {
|
|
462
|
+
await this.invoke(new functions.AuthSignIn({
|
|
463
|
+
phoneNumber: phone,
|
|
464
|
+
phoneCode: code,
|
|
465
|
+
phoneCodeHash: sentCode.phoneCodeHash,
|
|
466
|
+
}));
|
|
467
|
+
await this.storage.setAccountType("user");
|
|
468
|
+
dAuth("authorized as user");
|
|
469
|
+
await this.fetchState("authorize");
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
catch (err_) {
|
|
473
|
+
if (err_ instanceof types.RPCError && err_.errorMessage == "PHONE_CODE_INVALID") {
|
|
474
|
+
continue;
|
|
497
475
|
}
|
|
498
476
|
else {
|
|
499
|
-
|
|
477
|
+
err = err_;
|
|
478
|
+
break;
|
|
500
479
|
}
|
|
501
480
|
}
|
|
502
|
-
else {
|
|
503
|
-
throw err;
|
|
504
|
-
}
|
|
505
481
|
}
|
|
506
|
-
|
|
482
|
+
if (!(err instanceof types.RPCError && err.errorMessage == "SESSION_PASSWORD_NEEDED")) {
|
|
483
|
+
throw err;
|
|
484
|
+
}
|
|
485
|
+
while (true) {
|
|
486
|
+
const ap = await this.invoke(new functions.AccountGetPassword());
|
|
487
|
+
if (!(ap.currentAlgo instanceof types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow)) {
|
|
488
|
+
throw new Error(`Handling ${ap.currentAlgo?.constructor.name} not implemented`);
|
|
489
|
+
}
|
|
507
490
|
try {
|
|
491
|
+
const password = typeof params.password === "string" ? params.password : await params.password(ap.hint ?? null);
|
|
492
|
+
const input = await (0, _0_password_js_1.checkPassword)(password, ap);
|
|
493
|
+
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
494
|
+
await this.storage.setAccountType("user");
|
|
495
|
+
dAuth("authorized as user");
|
|
508
496
|
await this.fetchState("authorize");
|
|
497
|
+
break;
|
|
509
498
|
}
|
|
510
|
-
catch (
|
|
511
|
-
|
|
499
|
+
catch (err) {
|
|
500
|
+
if (err instanceof types.RPCError && err.errorMessage == "PASSWORD_HASH_INVALID") {
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
throw err;
|
|
505
|
+
}
|
|
512
506
|
}
|
|
513
507
|
}
|
|
514
508
|
}
|
|
@@ -517,6 +511,16 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
517
511
|
*/
|
|
518
512
|
async start(params) {
|
|
519
513
|
await this.connect();
|
|
514
|
+
try {
|
|
515
|
+
await this.fetchState("authorize");
|
|
516
|
+
d("already authorized");
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
catch (err) {
|
|
520
|
+
if (!(err instanceof types.RPCError) || err.errorMessage != "AUTH_KEY_UNREGISTERED") {
|
|
521
|
+
throw err;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
520
524
|
await this.authorize(params);
|
|
521
525
|
}
|
|
522
526
|
async receiveLoop() {
|
|
@@ -1168,6 +1172,12 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
1168
1172
|
}
|
|
1169
1173
|
return messages;
|
|
1170
1174
|
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Send a text message.
|
|
1177
|
+
*
|
|
1178
|
+
* @param chatId The chat to send the message to.
|
|
1179
|
+
* @param text The message's text.
|
|
1180
|
+
*/
|
|
1171
1181
|
async sendMessage(chatId, text, params) {
|
|
1172
1182
|
const entities_ = params?.entities ?? [];
|
|
1173
1183
|
const parseMode = params?.parseMode ?? this.parseMode;
|
|
@@ -1227,6 +1237,12 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
1227
1237
|
}));
|
|
1228
1238
|
return await this.updatesToMessages(chatId, result).then((v) => v[0]);
|
|
1229
1239
|
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Retrieve multiple messages.
|
|
1242
|
+
*
|
|
1243
|
+
* @param chatId The identifier of the chat to retrieve the messages from.
|
|
1244
|
+
* @param messageIds The identifiers of the messages to retrieve.
|
|
1245
|
+
*/
|
|
1230
1246
|
async getMessages(chatId_, messageIds) {
|
|
1231
1247
|
const peer = await this.getInputPeer(chatId_);
|
|
1232
1248
|
let messages_ = new Array();
|
|
@@ -1262,6 +1278,12 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
1262
1278
|
}
|
|
1263
1279
|
return messages;
|
|
1264
1280
|
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Retrieve a single message.
|
|
1283
|
+
*
|
|
1284
|
+
* @param chatId The identifier of the chat to retrieve the message from.
|
|
1285
|
+
* @param messageId The identifier of the message to retrieve.
|
|
1286
|
+
*/
|
|
1265
1287
|
async getMessage(chatId, messageId) {
|
|
1266
1288
|
const messages = await this.getMessages(chatId, [messageId]);
|
|
1267
1289
|
return messages[0] ?? null;
|
|
@@ -1305,24 +1327,29 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
1305
1327
|
}
|
|
1306
1328
|
}
|
|
1307
1329
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1330
|
+
/**
|
|
1331
|
+
* Download a file.
|
|
1332
|
+
*
|
|
1333
|
+
* @param fileId The identifier of the file to download.
|
|
1334
|
+
*/
|
|
1335
|
+
async download(fileId) {
|
|
1336
|
+
const fileId_ = _0_file_id_js_1.FileID.decode(fileId);
|
|
1337
|
+
switch (fileId_.fileType) {
|
|
1311
1338
|
case _0_file_id_js_1.FileType.ChatPhoto: {
|
|
1312
|
-
const big =
|
|
1313
|
-
const peer = await this.getInputPeer(
|
|
1314
|
-
const location = new types.InputPeerPhotoFileLocation({ big: big ? true : undefined, peer, photoId:
|
|
1339
|
+
const big = fileId_.params.thumbnailSource == _0_file_id_js_1.ThumbnailSource.ChatPhotoBig;
|
|
1340
|
+
const peer = await this.getInputPeer(fileId_.params.chatId);
|
|
1341
|
+
const location = new types.InputPeerPhotoFileLocation({ big: big ? true : undefined, peer, photoId: fileId_.params.mediaId });
|
|
1315
1342
|
return this.downloadInner(location);
|
|
1316
1343
|
}
|
|
1317
1344
|
case _0_file_id_js_1.FileType.Photo: {
|
|
1318
|
-
if (
|
|
1345
|
+
if (fileId_.params.mediaId == undefined || fileId_.params.accessHash == undefined || fileId_.params.fileReference == undefined || fileId_.params.thumbnailSize == undefined) {
|
|
1319
1346
|
(0, _0_control_js_1.UNREACHABLE)();
|
|
1320
1347
|
}
|
|
1321
1348
|
const location = new types.InputPhotoFileLocation({
|
|
1322
|
-
id:
|
|
1323
|
-
accessHash:
|
|
1324
|
-
fileReference:
|
|
1325
|
-
thumbSize:
|
|
1349
|
+
id: fileId_.params.mediaId,
|
|
1350
|
+
accessHash: fileId_.params.accessHash,
|
|
1351
|
+
fileReference: fileId_.params.fileReference,
|
|
1352
|
+
thumbSize: fileId_.params.thumbnailSize,
|
|
1326
1353
|
});
|
|
1327
1354
|
return this.downloadInner(location);
|
|
1328
1355
|
}
|
|
@@ -1342,6 +1369,13 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
1342
1369
|
return name;
|
|
1343
1370
|
}
|
|
1344
1371
|
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Forward multiple messages.
|
|
1374
|
+
*
|
|
1375
|
+
* @param from The identifier of the chat to forward the messages from.
|
|
1376
|
+
* @param to The identifier of the chat to forward the messages to.
|
|
1377
|
+
* @param messageIds The identifiers of the messages to forward.
|
|
1378
|
+
*/
|
|
1345
1379
|
async forwardMessages(from, to, messageIds, params) {
|
|
1346
1380
|
const result = await this.invoke(new functions.MessagesForwardMessages({
|
|
1347
1381
|
fromPeer: await this.getInputPeer(from),
|
|
@@ -1357,8 +1391,25 @@ class Client extends _1_client_abstract_js_1.ClientAbstract {
|
|
|
1357
1391
|
}));
|
|
1358
1392
|
return await this.updatesToMessages(to, result);
|
|
1359
1393
|
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Forward a single message.
|
|
1396
|
+
*
|
|
1397
|
+
* @param from The identifier of the chat to forward the message from.
|
|
1398
|
+
* @param to The identifier of the chat to forward the message to.
|
|
1399
|
+
* @param messageId The identifier of the message to forward.
|
|
1400
|
+
*/
|
|
1360
1401
|
async forwardMessage(from, to, messageId, params) {
|
|
1361
1402
|
return await this.forwardMessages(from, to, [messageId], params).then((v) => v[0]);
|
|
1362
1403
|
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Get information on the currently authorized user.
|
|
1406
|
+
*/
|
|
1407
|
+
async getMe() {
|
|
1408
|
+
const users = await this.invoke(new functions.UsersGetUsers({ id: [new types.InputUserSelf()] }));
|
|
1409
|
+
if (users.length < 1) {
|
|
1410
|
+
(0, _0_control_js_1.UNREACHABLE)();
|
|
1411
|
+
}
|
|
1412
|
+
return (0, _1_user_js_1.constructUser)(users[0][_1_tl_object_js_1.as](types.User));
|
|
1413
|
+
}
|
|
1363
1414
|
}
|
|
1364
1415
|
exports.Client = Client;
|
package/script/constants.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare const PUBLIC_KEYS: PublicKeys;
|
|
|
5
5
|
export declare const VECTOR_CONSTRUCTOR = 481674261;
|
|
6
6
|
export declare const INITIAL_DC: DC;
|
|
7
7
|
export declare const LAYER = 160;
|
|
8
|
-
export declare const APP_VERSION = "MTKruto 0.0.
|
|
8
|
+
export declare const APP_VERSION = "MTKruto 0.0.979";
|
|
9
9
|
export declare const DEVICE_MODEL: string;
|
|
10
10
|
export declare const LANG_CODE: string;
|
|
11
11
|
export declare const LANG_PACK = "";
|
package/script/constants.js
CHANGED
|
@@ -80,7 +80,7 @@ exports.PUBLIC_KEYS = Object.freeze([
|
|
|
80
80
|
exports.VECTOR_CONSTRUCTOR = 0x1CB5C415;
|
|
81
81
|
exports.INITIAL_DC = "2-test";
|
|
82
82
|
exports.LAYER = 160;
|
|
83
|
-
exports.APP_VERSION = "MTKruto 0.0.
|
|
83
|
+
exports.APP_VERSION = "MTKruto 0.0.979";
|
|
84
84
|
// @ts-ignore: lib
|
|
85
85
|
exports.DEVICE_MODEL = typeof dntShim.Deno === "undefined" ? typeof navigator === "undefined" ? typeof process === "undefined" ? "Unknown" : process.platform + "-" + process.arch : navigator.userAgent.split(" ")[0] : dntShim.Deno.build.os + "-" + dntShim.Deno.build.arch;
|
|
86
86
|
exports.LANG_CODE = typeof navigator === "undefined" ? "en" : navigator.language.split("-")[0];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function drop<T>(promise: Promise<T>): void;
|
|
2
2
|
export declare function mustPrompt(message: string): string;
|
|
3
3
|
export declare function mustPromptNumber(message: string): number;
|
|
4
|
+
export declare function mustPromptOneOf<T extends readonly string[]>(message: string, choices: T): T[number];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mustPromptNumber = exports.mustPrompt = exports.drop = void 0;
|
|
3
|
+
exports.mustPromptOneOf = exports.mustPromptNumber = exports.mustPrompt = exports.drop = void 0;
|
|
4
4
|
const _0_control_js_1 = require("./0_control.js");
|
|
5
5
|
function drop(promise) {
|
|
6
6
|
promise.then().catch();
|
|
@@ -25,3 +25,11 @@ function mustPromptNumber(message) {
|
|
|
25
25
|
return result;
|
|
26
26
|
}
|
|
27
27
|
exports.mustPromptNumber = mustPromptNumber;
|
|
28
|
+
function mustPromptOneOf(message, choices) {
|
|
29
|
+
let result = prompt(message);
|
|
30
|
+
while (result == null || !choices.includes(result)) {
|
|
31
|
+
result = prompt(message);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
exports.mustPromptOneOf = mustPromptOneOf;
|