teleproto 1.225.3 → 1.225.4
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/Version.d.ts +1 -1
- package/Version.js +1 -1
- package/client/TelegramClient.d.ts +18 -6
- package/client/TelegramClient.js +18 -6
- package/client/UpdateManager.d.ts +3 -0
- package/client/UpdateManager.js +33 -0
- package/client/auth.d.ts +3 -0
- package/client/auth.js +25 -16
- package/package.json +1 -1
- package/sessions/StoreSession.js +0 -1
- package/tl/custom/dialog.d.ts +1 -1
- package/tl/custom/dialog.js +2 -1
package/Version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "1.225.
|
|
1
|
+
export declare const version = "1.225.4";
|
package/Version.js
CHANGED
|
@@ -131,11 +131,18 @@ export declare class TelegramClient extends TelegramBaseClient {
|
|
|
131
131
|
/**
|
|
132
132
|
* logs the user using a QR code to be scanned.<br/>
|
|
133
133
|
* this function generates the QR code that needs to be scanned by mobile.
|
|
134
|
+
*
|
|
135
|
+
* The flow can be cancelled at any time (e.g. the user closed the page) by
|
|
136
|
+
* passing an `abortSignal`; once aborted it stops polling for tokens and
|
|
137
|
+
* rejects with an `AbortError`.
|
|
134
138
|
* @example
|
|
135
139
|
* '''ts
|
|
136
140
|
* await client.connect();
|
|
137
|
-
* const
|
|
138
|
-
*
|
|
141
|
+
* const controller = new AbortController();
|
|
142
|
+
* // call controller.abort() to cancel the QR login at any time
|
|
143
|
+
* try {
|
|
144
|
+
* const user = await client.signInUserWithQrCode({ apiId, apiHash },
|
|
145
|
+
* {
|
|
139
146
|
* onError: async function(p1: Error) {
|
|
140
147
|
* console.log("error", p1);
|
|
141
148
|
* // true = stop the authentication processes
|
|
@@ -150,14 +157,19 @@ export declare class TelegramClient extends TelegramBaseClient {
|
|
|
150
157
|
* password: async (hint) => {
|
|
151
158
|
* // password if needed
|
|
152
159
|
* return "1111";
|
|
153
|
-
* }
|
|
160
|
+
* },
|
|
161
|
+
* abortSignal: controller.signal,
|
|
154
162
|
* }
|
|
155
|
-
*
|
|
156
|
-
*
|
|
163
|
+
* );
|
|
164
|
+
* console.log("user is", user);
|
|
165
|
+
* } catch (err) {
|
|
166
|
+
* if (err.name === "AbortError") console.log("QR login cancelled");
|
|
167
|
+
* else throw err;
|
|
168
|
+
* }
|
|
157
169
|
*
|
|
158
170
|
* '''
|
|
159
171
|
* @param apiCredentials - credentials to be used.
|
|
160
|
-
* @param authParams - user auth params.
|
|
172
|
+
* @param authParams - user auth params. Pass `abortSignal` to cancel the flow.
|
|
161
173
|
*/
|
|
162
174
|
signInUserWithQrCode(apiCredentials: authMethods.ApiCredentials, authParams: authMethods.QrCodeAuthParams): Promise<Api.TypeUser>;
|
|
163
175
|
/**
|
package/client/TelegramClient.js
CHANGED
|
@@ -177,11 +177,18 @@ class TelegramClient extends telegramBaseClient_1.TelegramBaseClient {
|
|
|
177
177
|
/**
|
|
178
178
|
* logs the user using a QR code to be scanned.<br/>
|
|
179
179
|
* this function generates the QR code that needs to be scanned by mobile.
|
|
180
|
+
*
|
|
181
|
+
* The flow can be cancelled at any time (e.g. the user closed the page) by
|
|
182
|
+
* passing an `abortSignal`; once aborted it stops polling for tokens and
|
|
183
|
+
* rejects with an `AbortError`.
|
|
180
184
|
* @example
|
|
181
185
|
* '''ts
|
|
182
186
|
* await client.connect();
|
|
183
|
-
* const
|
|
184
|
-
*
|
|
187
|
+
* const controller = new AbortController();
|
|
188
|
+
* // call controller.abort() to cancel the QR login at any time
|
|
189
|
+
* try {
|
|
190
|
+
* const user = await client.signInUserWithQrCode({ apiId, apiHash },
|
|
191
|
+
* {
|
|
185
192
|
* onError: async function(p1: Error) {
|
|
186
193
|
* console.log("error", p1);
|
|
187
194
|
* // true = stop the authentication processes
|
|
@@ -196,14 +203,19 @@ class TelegramClient extends telegramBaseClient_1.TelegramBaseClient {
|
|
|
196
203
|
* password: async (hint) => {
|
|
197
204
|
* // password if needed
|
|
198
205
|
* return "1111";
|
|
199
|
-
* }
|
|
206
|
+
* },
|
|
207
|
+
* abortSignal: controller.signal,
|
|
200
208
|
* }
|
|
201
|
-
*
|
|
202
|
-
*
|
|
209
|
+
* );
|
|
210
|
+
* console.log("user is", user);
|
|
211
|
+
* } catch (err) {
|
|
212
|
+
* if (err.name === "AbortError") console.log("QR login cancelled");
|
|
213
|
+
* else throw err;
|
|
214
|
+
* }
|
|
203
215
|
*
|
|
204
216
|
* '''
|
|
205
217
|
* @param apiCredentials - credentials to be used.
|
|
206
|
-
* @param authParams - user auth params.
|
|
218
|
+
* @param authParams - user auth params. Pass `abortSignal` to cancel the flow.
|
|
207
219
|
*/
|
|
208
220
|
signInUserWithQrCode(apiCredentials, authParams) {
|
|
209
221
|
return authMethods.signInUserWithQrCode(this, apiCredentials, authParams);
|
|
@@ -14,6 +14,8 @@ export declare class UpdateManager {
|
|
|
14
14
|
private globalPtsTimer?;
|
|
15
15
|
private readonly channels;
|
|
16
16
|
private readonly pendingSeq;
|
|
17
|
+
private readonly recentMessageKeys;
|
|
18
|
+
private readonly recentMessageQueue;
|
|
17
19
|
private fetchingDifference;
|
|
18
20
|
private failTimeoutS;
|
|
19
21
|
private failRetryTimer?;
|
|
@@ -38,6 +40,7 @@ export declare class UpdateManager {
|
|
|
38
40
|
private handleShortMessage;
|
|
39
41
|
private feedUpdate;
|
|
40
42
|
private dispatch;
|
|
43
|
+
private isDuplicateMessage;
|
|
41
44
|
private collectEntities;
|
|
42
45
|
private makeGlobalWaiter;
|
|
43
46
|
private getOrCreateChannel;
|
package/client/UpdateManager.js
CHANGED
|
@@ -43,6 +43,7 @@ const NO_UPDATES_TIMEOUT_MS = 15 * 60 * 1000;
|
|
|
43
43
|
const FAIL_DIFFERENCE_INITIAL_S = 1;
|
|
44
44
|
const FAIL_DIFFERENCE_CAP_S = 64;
|
|
45
45
|
const CHANNEL_DIFFERENCE_LIMIT = 100;
|
|
46
|
+
const RECENT_MESSAGE_BUFFER_SIZE = 1000;
|
|
46
47
|
function isCommonPtsUpdate(update) {
|
|
47
48
|
return (update instanceof tl_1.Api.UpdateNewMessage ||
|
|
48
49
|
update instanceof tl_1.Api.UpdateDeleteMessages ||
|
|
@@ -79,6 +80,8 @@ class UpdateManager {
|
|
|
79
80
|
this.lastUpdateTime = 0;
|
|
80
81
|
this.channels = new Map();
|
|
81
82
|
this.pendingSeq = [];
|
|
83
|
+
this.recentMessageKeys = new Set();
|
|
84
|
+
this.recentMessageQueue = [];
|
|
82
85
|
this.fetchingDifference = false;
|
|
83
86
|
this.failTimeoutS = FAIL_DIFFERENCE_INITIAL_S;
|
|
84
87
|
this.channelFailTimeoutS = new Map();
|
|
@@ -306,9 +309,39 @@ class UpdateManager {
|
|
|
306
309
|
}
|
|
307
310
|
dispatch(update, payload) {
|
|
308
311
|
var _a;
|
|
312
|
+
if (this.isDuplicateMessage(update)) {
|
|
313
|
+
this.client._log.debug("Skip duplicate message update (already dispatched)");
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
309
316
|
update._entities = (_a = payload.entities) !== null && _a !== void 0 ? _a : new Map();
|
|
310
317
|
(0, updates_1._dispatchUpdate)(this.client, { update }).catch((e) => this.client._log.error(`Error dispatching update: ${e}`));
|
|
311
318
|
}
|
|
319
|
+
isDuplicateMessage(update) {
|
|
320
|
+
if (!(update instanceof tl_1.Api.UpdateNewMessage) &&
|
|
321
|
+
!(update instanceof tl_1.Api.UpdateNewChannelMessage)) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
const message = update.message;
|
|
325
|
+
if ((message === null || message === void 0 ? void 0 : message.id) == undefined || message.peerId == undefined)
|
|
326
|
+
return false;
|
|
327
|
+
let peerId;
|
|
328
|
+
try {
|
|
329
|
+
peerId = utils.getPeerId(message.peerId);
|
|
330
|
+
}
|
|
331
|
+
catch (_a) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
const key = `${peerId}:${message.id}`;
|
|
335
|
+
if (this.recentMessageKeys.has(key))
|
|
336
|
+
return true;
|
|
337
|
+
this.recentMessageKeys.add(key);
|
|
338
|
+
this.recentMessageQueue.push(key);
|
|
339
|
+
if (this.recentMessageQueue.length > RECENT_MESSAGE_BUFFER_SIZE) {
|
|
340
|
+
const old = this.recentMessageQueue.shift();
|
|
341
|
+
this.recentMessageKeys.delete(old);
|
|
342
|
+
}
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
312
345
|
collectEntities(users, chats) {
|
|
313
346
|
const entities = new Map();
|
|
314
347
|
for (const x of [...users, ...chats]) {
|
package/client/auth.d.ts
CHANGED
|
@@ -86,6 +86,9 @@ export interface QrCodeAuthParams extends UserPasswordAuthParams {
|
|
|
86
86
|
/** when an error happens during auth this function will be called with the error.<br/>
|
|
87
87
|
* if this returns true the auth operation will stop. */
|
|
88
88
|
onError: (err: Error) => Promise<boolean> | void;
|
|
89
|
+
/** an AbortSignal to cancel the QR login flow (e.g. the user closed the page).<br/>
|
|
90
|
+
* when aborted, the flow stops polling and rejects with an `AbortError`. */
|
|
91
|
+
abortSignal?: AbortSignal;
|
|
89
92
|
}
|
|
90
93
|
interface ReturnString {
|
|
91
94
|
(): string;
|
package/client/auth.js
CHANGED
|
@@ -248,17 +248,23 @@ async function signInUser(client, apiCredentials, authParams) {
|
|
|
248
248
|
await authParams.onError(new Error("Auth failed"));
|
|
249
249
|
return client.signInUser(apiCredentials, authParams);
|
|
250
250
|
}
|
|
251
|
+
function qrAbortError() {
|
|
252
|
+
const err = new Error("QR login aborted");
|
|
253
|
+
err.name = "AbortError";
|
|
254
|
+
return err;
|
|
255
|
+
}
|
|
251
256
|
/** @hidden */
|
|
252
257
|
async function signInUserWithQrCode(client, apiCredentials, authParams) {
|
|
253
|
-
let isScanningComplete = false;
|
|
254
258
|
if (authParams.qrCode == undefined) {
|
|
255
259
|
throw new Error("qrCode callback not defined");
|
|
256
260
|
}
|
|
261
|
+
const { abortSignal } = authParams;
|
|
262
|
+
if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)
|
|
263
|
+
throw qrAbortError();
|
|
264
|
+
let isScanningComplete = false;
|
|
265
|
+
const stopped = () => isScanningComplete || !!(abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted);
|
|
257
266
|
const inputPromise = (async () => {
|
|
258
|
-
while (
|
|
259
|
-
if (isScanningComplete) {
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
267
|
+
while (!stopped()) {
|
|
262
268
|
const result = await client.invoke(new tl_1.Api.auth.ExportLoginToken({
|
|
263
269
|
apiId: Number(apiCredentials.apiId),
|
|
264
270
|
apiHash: apiCredentials.apiHash,
|
|
@@ -275,21 +281,24 @@ async function signInUserWithQrCode(client, apiCredentials, authParams) {
|
|
|
275
281
|
await (0, Helpers_1.sleep)(QR_CODE_TIMEOUT);
|
|
276
282
|
}
|
|
277
283
|
})();
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
284
|
+
const Raw = require("../events/Raw").Raw;
|
|
285
|
+
const rawEvent = new Raw({});
|
|
286
|
+
const onUpdate = (update) => {
|
|
287
|
+
if (update instanceof tl_1.Api.UpdateLoginToken)
|
|
288
|
+
resolveUpdate();
|
|
289
|
+
};
|
|
290
|
+
let resolveUpdate;
|
|
291
|
+
const updatePromise = new Promise((resolve) => (resolveUpdate = resolve));
|
|
292
|
+
client.addEventHandler(onUpdate, rawEvent);
|
|
293
|
+
const abortPromise = new Promise((_, reject) => abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.addEventListener("abort", () => reject(qrAbortError()), {
|
|
294
|
+
once: true,
|
|
295
|
+
}));
|
|
285
296
|
try {
|
|
286
|
-
await Promise.race([updatePromise, inputPromise]);
|
|
287
|
-
}
|
|
288
|
-
catch (err) {
|
|
289
|
-
throw err;
|
|
297
|
+
await Promise.race([updatePromise, inputPromise, abortPromise]);
|
|
290
298
|
}
|
|
291
299
|
finally {
|
|
292
300
|
isScanningComplete = true;
|
|
301
|
+
client.removeEventHandler(onUpdate, rawEvent);
|
|
293
302
|
}
|
|
294
303
|
try {
|
|
295
304
|
const result2 = await client.invoke(new tl_1.Api.auth.ExportLoginToken({
|
package/package.json
CHANGED
package/sessions/StoreSession.js
CHANGED
package/tl/custom/dialog.d.ts
CHANGED
package/tl/custom/dialog.js
CHANGED
|
@@ -7,13 +7,14 @@ const draft_1 = require("./draft");
|
|
|
7
7
|
const Helpers_1 = require("../../Helpers");
|
|
8
8
|
class Dialog {
|
|
9
9
|
constructor(client, dialog, entities, message) {
|
|
10
|
+
var _a;
|
|
10
11
|
this._client = client;
|
|
11
12
|
this.dialog = dialog;
|
|
12
13
|
this.pinned = !!dialog.pinned;
|
|
13
14
|
this.folderId = dialog.folderId;
|
|
14
15
|
this.archived = dialog.folderId != undefined;
|
|
15
16
|
this.message = message;
|
|
16
|
-
this.date = this.message.date;
|
|
17
|
+
this.date = (_a = this.message) === null || _a === void 0 ? void 0 : _a.date;
|
|
17
18
|
this.entity = entities.get((0, Utils_1.getPeerId)(dialog.peer));
|
|
18
19
|
this.inputEntity = (0, Utils_1.getInputPeer)(this.entity);
|
|
19
20
|
if (this.entity) {
|