@imessaging/telegram-mtproto 0.8.8 → 0.8.10

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.8.8",
3
+ "version": "0.8.10",
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.8.8",
34
+ "@imessaging/core": "^0.8.9",
35
35
  "big-integer": "^1.6.52"
36
36
  },
37
37
  "peerDependencies": {
@@ -7,6 +7,8 @@ import type {
7
7
  DraftTransport,
8
8
  MessageDraft,
9
9
  OutgoingObserverTransport,
10
+ OutgoingReadReceipt,
11
+ OutgoingReadReceiptTransport,
10
12
  ButtonPress,
11
13
  ButtonPressTransport,
12
14
  IncomingAttachment,
@@ -19,6 +21,7 @@ import type {
19
21
  EditResult,
20
22
  MessageReaction,
21
23
  MessageRecipient,
24
+ OutboundButton,
22
25
  OutboundMessage,
23
26
  ReactionTransport,
24
27
  ResolvedPeer,
@@ -34,6 +37,7 @@ import { peerToChat, unmarkPeerId } from "./incoming";
34
37
  import bigInt from "big-integer";
35
38
  import { Api, TelegramClient } from "telegram";
36
39
  import { CustomFile } from "telegram/client/uploads";
40
+ import { Button } from "telegram/tl/custom/button";
37
41
  import { CallbackQuery } from "telegram/events/CallbackQuery";
38
42
  import { NewMessage } from "telegram/events/NewMessage";
39
43
  import { EditedMessage } from "telegram/events/EditedMessage";
@@ -110,6 +114,17 @@ function inputPeerChatId(peer: Api.TypeInputPeer): string {
110
114
  throw new Error(`Unsupported input peer: ${peer.className}`);
111
115
  }
112
116
 
117
+ function toGramJsButtons(buttons?: OutboundButton[][]) {
118
+ if (!buttons || buttons.length === 0) return undefined;
119
+ return buttons.map((row) =>
120
+ row.map((button) => {
121
+ if (button.url) return Button.url(button.text, button.url);
122
+ if (button.callbackData) return Button.inline(button.text, Buffer.from(button.callbackData));
123
+ return Button.text(button.text);
124
+ }),
125
+ );
126
+ }
127
+
113
128
  export class TelegramMtprotoTransport
114
129
  implements
115
130
  ContactTransport,
@@ -119,6 +134,7 @@ export class TelegramMtprotoTransport
119
134
  ButtonPressTransport,
120
135
  IncomingMessageTransport,
121
136
  OutgoingObserverTransport,
137
+ OutgoingReadReceiptTransport,
122
138
  PhoneLookupTransport,
123
139
  ReactionTransport,
124
140
  ReadReceiptTransport,
@@ -137,6 +153,10 @@ export class TelegramMtprotoTransport
137
153
  private outgoingListener: ((event: unknown) => void) | null = null;
138
154
  private readonly outgoingEdits = new OutgoingDispatcher();
139
155
  private outgoingEditListener: ((event: unknown) => void) | null = null;
156
+ private readonly outgoingReads = new Set<
157
+ (receipt: OutgoingReadReceipt) => void | Promise<void>
158
+ >();
159
+ private outgoingReadListener: ((event: unknown) => void) | null = null;
140
160
  /**
141
161
  * Что отправил и поправил сам транспорт: «чат:сообщение» → когда. Своё приходит тем же обновлением
142
162
  * out=true, что и отправленное человеком с телефона, и без этой памяти их не различить.
@@ -426,6 +446,46 @@ export class TelegramMtprotoTransport
426
446
  };
427
447
  }
428
448
 
449
+ /** Прочтение собеседником наших исходящих сообщений. */
450
+ onOutgoingRead(handler: (receipt: OutgoingReadReceipt) => void | Promise<void>): () => void {
451
+ this.outgoingReads.add(handler);
452
+ if (this.outgoingReadListener === null) {
453
+ this.outgoingReadListener = (event: unknown): void => {
454
+ if (event instanceof Api.UpdateReadHistoryOutbox) {
455
+ try {
456
+ const { chatId } = peerToChat(event.peer);
457
+ const receipt: OutgoingReadReceipt = {
458
+ chatId,
459
+ maxMessageId: event.maxId.toString(),
460
+ readAt: new Date(),
461
+ };
462
+ for (const fn of this.outgoingReads) void fn(receipt);
463
+ } catch {
464
+ // неизвестный пир
465
+ }
466
+ } else if (event instanceof Api.UpdateReadChannelOutbox) {
467
+ try {
468
+ const receipt: OutgoingReadReceipt = {
469
+ chatId: `-100${event.channelId.toString()}`,
470
+ maxMessageId: event.maxId.toString(),
471
+ readAt: new Date(),
472
+ };
473
+ for (const fn of this.outgoingReads) void fn(receipt);
474
+ } catch {
475
+ // неизвестный канал
476
+ }
477
+ }
478
+ };
479
+ this.client.addEventHandler(this.outgoingReadListener);
480
+ }
481
+ return () => {
482
+ this.outgoingReads.delete(handler);
483
+ if (this.outgoingReads.size > 0 || this.outgoingReadListener === null) return;
484
+ this.client.removeEventHandler(this.outgoingReadListener, undefined as never);
485
+ this.outgoingReadListener = null;
486
+ };
487
+ }
488
+
429
489
  private async dispatchOwn(
430
490
  dispatcher: OutgoingDispatcher,
431
491
  own: Map<string, number>,
@@ -809,6 +869,7 @@ export class TelegramMtprotoTransport
809
869
  parseMode,
810
870
  formattingEntities,
811
871
  replyTo: message.replyToMessageId ?? message.threadId,
872
+ buttons: toGramJsButtons(message.buttons),
812
873
  });
813
874
  this.rememberOwn(this.ownSent, peer, sent.id);
814
875
  for (const document of message.documents ?? []) {
@@ -975,13 +1036,12 @@ export class TelegramMtprotoTransport
975
1036
  const text = ft ? ft.text : message.text;
976
1037
  const parseMode = ft ? undefined : message.parseMode?.toLowerCase();
977
1038
  const formattingEntities = ft ? toTelegramEntities(ft) : undefined;
978
- // Кнопки здесь не передаются — ровно как и при отправке этим транспортом: inline-клавиатуру
979
- // MTProto-аккаунт не рисует. Передать их сюда значило бы обещать разметку, которой не будет.
980
1039
  await this.client.editMessage(peer, {
981
1040
  message: messageId,
982
1041
  text,
983
1042
  parseMode,
984
1043
  formattingEntities,
1044
+ buttons: toGramJsButtons(message.buttons),
985
1045
  });
986
1046
  this.lastActivityAt = new Date();
987
1047
  return {