@imessaging/telegram-mtproto 0.6.5 → 0.6.7
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/package.json
CHANGED
|
@@ -231,6 +231,48 @@ export class TelegramMtprotoTransport
|
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
/**
|
|
235
|
+
* ДОГРУЗКА ПРОПУЩЕННОГО. Возвращает число сообщений, отданных подписчикам.
|
|
236
|
+
*
|
|
237
|
+
* Живая подписка теряет часть сообщений — чаще всего в супергруппах с темами: обновление
|
|
238
|
+
* приходит по каналу, которого клиент не помнит, и молча отбрасывается. Замер 07.09.2026:
|
|
239
|
+
* сообщение в теме форума видно по ссылке, а в подписке его нет ни у одного потребителя.
|
|
240
|
+
* Продукт italent живёт с этим давно и добирает последние сообщения опросом — здесь то же
|
|
241
|
+
* самое, только на уровне транспорта, чтобы каждому приложению не изобретать своё.
|
|
242
|
+
*
|
|
243
|
+
* Повторы неизбежны и это нормально: потребитель обязан отсеивать по идентификатору сообщения,
|
|
244
|
+
* а не полагаться на то, что канал не повторится. Он и так повторяется в обычной жизни.
|
|
245
|
+
*/
|
|
246
|
+
async catchUp(options: { limit?: number; dialogs?: number; sinceMs?: number } = {}): Promise<number> {
|
|
247
|
+
const limit = options.limit ?? 20;
|
|
248
|
+
// ГРАНИЦА ПО ВРЕМЕНИ ОБЯЗАТЕЛЬНА ПО СМЫСЛУ: без неё первый же опрос поднимает всю доступную
|
|
249
|
+
// историю каждого диалога и отдаёт её потребителю как новьё. Замер 07.09.2026 — сотни старых
|
|
250
|
+
// сообщений уехали продукту, который их давно разобрал. Догрузка чинит пропажу последних
|
|
251
|
+
// минут, а не восстанавливает архив.
|
|
252
|
+
const since = options.sinceMs ?? Date.now() - 6 * 60 * 60 * 1000;
|
|
253
|
+
const dialogs = await this.client.getDialogs({ limit: options.dialogs ?? 200 });
|
|
254
|
+
let dispatched = 0;
|
|
255
|
+
for (const dialog of dialogs) {
|
|
256
|
+
if (!dialog.isGroup && !dialog.isChannel) continue;
|
|
257
|
+
const entity = dialog.entity;
|
|
258
|
+
if (!entity) continue;
|
|
259
|
+
const messages = await this.client.getMessages(entity, { limit }).catch(() => []);
|
|
260
|
+
// От старых к новым: порядок обработки должен совпадать с тем, в каком они пришли бы живьём.
|
|
261
|
+
for (const message of [...messages].reverse()) {
|
|
262
|
+
const at = (message as { date?: number }).date;
|
|
263
|
+
if (typeof at === "number" && at * 1000 < since) continue;
|
|
264
|
+
const delivered = await this.incoming.dispatch(
|
|
265
|
+
message as unknown as MtprotoMessageLike,
|
|
266
|
+
this.id,
|
|
267
|
+
this.options.accountId,
|
|
268
|
+
);
|
|
269
|
+
if (delivered) dispatched += 1;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
this.lastActivityAt = new Date();
|
|
273
|
+
return dispatched;
|
|
274
|
+
}
|
|
275
|
+
|
|
234
276
|
private stopListeningIfIdle(): void {
|
|
235
277
|
if (this.incoming.size > 0 || this.incomingListener === null) return;
|
|
236
278
|
this.client.removeEventHandler(this.incomingListener, new NewMessage({}));
|