@imessaging/telegram-mtproto 0.7.4 → 0.8.0

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.7.4",
3
+ "version": "0.8.0",
4
4
  "description": "Telegram MTProto user-account transport for imessaging",
5
5
  "keywords": [
6
6
  "messaging",
@@ -31,7 +31,7 @@
31
31
  "test": "bun test"
32
32
  },
33
33
  "dependencies": {
34
- "@imessaging/core": "^0.7.4",
34
+ "@imessaging/core": "^0.8.0",
35
35
  "big-integer": "^1.6.52"
36
36
  },
37
37
  "peerDependencies": {
@@ -0,0 +1,27 @@
1
+ import { Api } from "telegram";
2
+ import type { FormattedText } from "@imessaging/core";
3
+
4
+ /**
5
+ * Выделения FormattedText → сущности MTProto. Смещения у обоих в UTF-16, переводить их не нужно.
6
+ */
7
+ export function toTelegramEntities(ft: FormattedText): Api.TypeMessageEntity[] {
8
+ return ft.entities.map((e) => {
9
+ const base = { offset: e.offset, length: e.length };
10
+ switch (e.type) {
11
+ case "bold":
12
+ return new Api.MessageEntityBold(base);
13
+ case "italic":
14
+ return new Api.MessageEntityItalic(base);
15
+ case "underline":
16
+ return new Api.MessageEntityUnderline(base);
17
+ case "strike":
18
+ return new Api.MessageEntityStrike(base);
19
+ case "code":
20
+ return new Api.MessageEntityCode(base);
21
+ case "pre":
22
+ return new Api.MessageEntityPre({ ...base, language: e.language ?? "" });
23
+ case "link":
24
+ return new Api.MessageEntityTextUrl({ ...base, url: e.url ?? "" });
25
+ }
26
+ });
27
+ }
package/src/incoming.ts CHANGED
@@ -14,9 +14,10 @@ export type MtprotoMessageLike = {
14
14
  message?: string;
15
15
  /** `true` — сообщение отправлено САМОЙ учётной записью. */
16
16
  out?: boolean;
17
- date?: number;
18
- editDate?: number;
19
- groupedId?: { toString(): string };
17
+ // gramjs отдаёт отсутствующее поле как `null`, а не `undefined`: проверки ниже — на оба.
18
+ date?: number | null;
19
+ editDate?: number | null;
20
+ groupedId?: { toString(): string } | null;
20
21
  peerId?: MtprotoPeerLike;
21
22
  fromId?: MtprotoPeerLike;
22
23
  media?: MtprotoMediaLike;
@@ -31,7 +32,7 @@ export type MtprotoMessageLike = {
31
32
  replyMarkup?: { rows?: { buttons?: MtprotoButtonLike[] }[] };
32
33
  replyTo?: {
33
34
  replyToMsgId?: number | string;
34
- replyToTopId?: number | string;
35
+ replyToTopId?: number | string | null;
35
36
  forumTopic?: boolean;
36
37
  };
37
38
  /** Заголовок форварда. Пусто — сообщение своё, не пересланное. */
@@ -269,7 +270,7 @@ export function toIncomingMessage(
269
270
  if (message.replyTo?.forumTopic === true) {
270
271
  threadId = Number(message.replyTo.replyToTopId ?? message.replyTo.replyToMsgId);
271
272
  replyToMessageId =
272
- message.replyTo.replyToTopId === undefined ? undefined : String(message.replyTo.replyToMsgId);
273
+ message.replyTo.replyToTopId == null ? undefined : String(message.replyTo.replyToMsgId);
273
274
  } else {
274
275
  replyToMessageId =
275
276
  message.replyTo?.replyToMsgId === undefined
@@ -292,8 +293,9 @@ export function toIncomingMessage(
292
293
  messageId: String(message.id),
293
294
  albumId: message.groupedId?.toString(),
294
295
  text: message.message ?? "",
295
- sentAt: message.date !== undefined ? new Date(message.date * 1000) : undefined,
296
- editedAt: message.editDate !== undefined ? new Date(message.editDate * 1000) : undefined,
296
+ sentAt: message.date ? new Date(message.date * 1000) : undefined,
297
+ // Непоправленное сообщение приходит с `editDate: null` — это не правка в 1970 году.
298
+ editedAt: message.editDate ? new Date(message.editDate * 1000) : undefined,
297
299
  attachments: collectAttachments(message, chatId),
298
300
  links: collectLinks(message),
299
301
  replyToMessageId,
@@ -17,7 +17,8 @@ import type {
17
17
  TransportStatus,
18
18
  TypingTransport,
19
19
  } from "@imessaging/core";
20
- import { isTelegramRecipient, MemoryPeerStore } from "@imessaging/core";
20
+ import { isTelegramRecipient, MemoryPeerStore, formattedOf } from "@imessaging/core";
21
+ import { toTelegramEntities } from "./entities";
21
22
  import { peerToChat, unmarkPeerId } from "./incoming";
22
23
  import bigInt from "big-integer";
23
24
  import { Api, TelegramClient } from "telegram";
@@ -442,9 +443,15 @@ export class TelegramMtprotoTransport
442
443
  private async sendWithRetry(message: OutboundMessage, retried: boolean): Promise<SendResult> {
443
444
  try {
444
445
  const peer = await this.getInputPeer(message.recipient);
446
+ // С `format` уходят готовые выделения: gramjs тогда не разбирает текст своим markdown вовсе.
447
+ const ft = formattedOf(message);
448
+ const text = ft ? ft.text : message.text;
449
+ const parseMode = ft ? undefined : message.parseMode?.toLowerCase();
450
+ const formattingEntities = ft ? toTelegramEntities(ft) : undefined;
445
451
  const sent = await this.client.sendMessage(peer, {
446
- message: message.text,
447
- parseMode: message.parseMode?.toLowerCase(),
452
+ message: text,
453
+ parseMode,
454
+ formattingEntities,
448
455
  replyTo: message.replyToMessageId ?? message.threadId,
449
456
  });
450
457
  for (const document of message.documents ?? []) {
@@ -604,12 +611,17 @@ export class TelegramMtprotoTransport
604
611
  let peer: Api.TypeInputPeer | null = null;
605
612
  try {
606
613
  peer = await this.getInputPeer(message.recipient);
614
+ const ft = formattedOf(message);
615
+ const text = ft ? ft.text : message.text;
616
+ const parseMode = ft ? undefined : message.parseMode?.toLowerCase();
617
+ const formattingEntities = ft ? toTelegramEntities(ft) : undefined;
607
618
  // Кнопки здесь не передаются — ровно как и при отправке этим транспортом: inline-клавиатуру
608
619
  // MTProto-аккаунт не рисует. Передать их сюда значило бы обещать разметку, которой не будет.
609
620
  await this.client.editMessage(peer, {
610
621
  message: messageId,
611
- text: message.text,
612
- parseMode: message.parseMode?.toLowerCase(),
622
+ text,
623
+ parseMode,
624
+ formattingEntities,
613
625
  });
614
626
  this.lastActivityAt = new Date();
615
627
  return {