@imessaging/telegram-mtproto 0.6.2 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imessaging/telegram-mtproto",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "Telegram MTProto user-account transport for imessaging",
5
5
  "keywords": [
6
6
  "messaging",
package/src/incoming.ts CHANGED
@@ -51,18 +51,36 @@ export type MtprotoMediaLike = {
51
51
  *
52
52
  * `chatId` берётся из пира, а НЕ из отправителя: в группе они разные, и перепутав их, ответ уехал
53
53
  * бы в личку тому, кто написал в общий чат.
54
+ *
55
+ * ИДЕНТИФИКАТОР ОТДАЁТСЯ МАРКИРОВАННЫМ — тем самым, что знают Bot API, люди и соседние продукты:
56
+ * `-100…` у каналов и супергрупп, `-…` у обычных групп. Внутри MTProto он положительный, и если
57
+ * отдавать его как есть, один и тот же чат в разных системах называется двумя разными числами:
58
+ * замер 06.09.2026 — продукт хранит `-5386451338`, шлюз присылает `5386451338`, и предъявитель
59
+ * не находится. Тот же класс ошибки уже стоил продукту чата-призрака с потерянным знаком.
54
60
  */
55
61
  export function peerToChat(peer: MtprotoPeerLike | undefined): {
56
62
  chatId: string;
57
63
  chatType: IncomingMessage["chatType"];
58
64
  } {
59
65
  if (peer?.channelId !== undefined)
60
- return { chatId: peer.channelId.toString(), chatType: "channel" };
61
- if (peer?.chatId !== undefined) return { chatId: peer.chatId.toString(), chatType: "group" };
66
+ return { chatId: `-100${peer.channelId.toString()}`, chatType: "channel" };
67
+ if (peer?.chatId !== undefined) return { chatId: `-${peer.chatId.toString()}`, chatType: "group" };
62
68
  if (peer?.userId !== undefined) return { chatId: peer.userId.toString(), chatType: "user" };
63
69
  throw new Error("MTProto peer without userId, chatId or channelId");
64
70
  }
65
71
 
72
+ /**
73
+ * Маркированный идентификатор → тот, которым чат зовётся ВНУТРИ MTProto.
74
+ *
75
+ * Нужен на отправке: `InputPeerChat` и `InputPeerChannel` принимают положительное число, а снаружи
76
+ * ходит маркированное. Немаркированное число тоже принимается — тогда вид берётся из вызова.
77
+ */
78
+ export function unmarkPeerId(chatId: string): string {
79
+ if (chatId.startsWith("-100")) return chatId.slice(4);
80
+ if (chatId.startsWith("-")) return chatId.slice(1);
81
+ return chatId;
82
+ }
83
+
66
84
  /**
67
85
  * Что приехало файлом.
68
86
  *
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ export {
7
7
  downloadFromMessage,
8
8
  IncomingDispatcher,
9
9
  peerToChat,
10
+ unmarkPeerId,
10
11
  toIncomingMessage,
11
12
  type DownloadingClient,
12
13
  type MtprotoMediaLike,
@@ -17,7 +17,7 @@ import type {
17
17
  TypingTransport,
18
18
  } from "@imessaging/core";
19
19
  import { isTelegramRecipient, MemoryPeerStore } from "@imessaging/core";
20
- import { peerToChat } from "./incoming";
20
+ import { peerToChat, unmarkPeerId } from "./incoming";
21
21
  import bigInt from "big-integer";
22
22
  import { Api, TelegramClient } from "telegram";
23
23
  import { CustomFile } from "telegram/client/uploads";
@@ -111,6 +111,13 @@ export class TelegramMtprotoTransport
111
111
 
112
112
  async connect(): Promise<void> {
113
113
  await this.client.connect();
114
+ // СОСТОЯНИЕ ОБНОВЛЕНИЙ БЕРЁТСЯ СРАЗУ, и это не украшение.
115
+ //
116
+ // У учётной записи состояние одно на всех: если обновления уже подтвердил кто-то другой —
117
+ // прежний потребитель этой же сессии, — сервер не отдаст их повторно, и подписка будет ждать
118
+ // событий, которые для него доставлены. Снаружи это выглядит как «канал молчит»: соединение
119
+ // живо, отправка работает, приёма нет. Замер 06.09.2026 — сутки такой тишины.
120
+ await this.client.invoke(new Api.updates.GetState()).catch(() => undefined);
114
121
  this.connected = true;
115
122
  }
116
123
 
@@ -336,8 +343,12 @@ export class TelegramMtprotoTransport
336
343
  */
337
344
  private async knownInputPeer(recipient: MessageRecipient): Promise<Api.TypeInputPeer | null> {
338
345
  if (recipient.type === "email" || recipient.type === "username") return null;
346
+ // Обычной группе ни клиент, ни хранилище не нужны: `InputPeerChat` строится из одного номера.
347
+ if (recipient.type === "group") {
348
+ return new Api.InputPeerChat({ chatId: bigInt(unmarkPeerId(recipient.id)) });
349
+ }
339
350
  try {
340
- return await this.client.getInputEntity(bigInt(recipient.id));
351
+ return await this.client.getInputEntity(bigInt(unmarkPeerId(recipient.id)));
341
352
  } catch {
342
353
  return null;
343
354
  }
@@ -399,17 +410,18 @@ export class TelegramMtprotoTransport
399
410
 
400
411
  private toInputPeer(peer: ResolvedPeer): Api.TypeInputPeer {
401
412
  if (peer.type === "group") {
402
- return new Api.InputPeerChat({ chatId: bigInt(peer.id) });
413
+ // У обычной группы access hash не бывает вовсе — ей довольно номера.
414
+ return new Api.InputPeerChat({ chatId: bigInt(unmarkPeerId(peer.id)) });
403
415
  }
404
416
  if (!peer.accessHash) throw new Error(`Cached ${peer.type} peer has no accessHash`);
405
417
  if (peer.type === "user") {
406
418
  return new Api.InputPeerUser({
407
- userId: bigInt(peer.id),
419
+ userId: bigInt(unmarkPeerId(peer.id)),
408
420
  accessHash: bigInt(peer.accessHash),
409
421
  });
410
422
  }
411
423
  return new Api.InputPeerChannel({
412
- channelId: bigInt(peer.id),
424
+ channelId: bigInt(unmarkPeerId(peer.id)),
413
425
  accessHash: bigInt(peer.accessHash),
414
426
  });
415
427
  }