@imessaging/telegram-mtproto 0.6.0 → 0.6.1

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.0",
3
+ "version": "0.6.1",
4
4
  "description": "Telegram MTProto user-account transport for imessaging",
5
5
  "keywords": [
6
6
  "messaging",
package/src/incoming.ts CHANGED
@@ -18,6 +18,13 @@ export type MtprotoMessageLike = {
18
18
  fromId?: MtprotoPeerLike;
19
19
  media?: MtprotoMediaLike;
20
20
  replyTo?: { replyToMsgId?: number | string };
21
+ /**
22
+ * Отправитель целиком — его приносит обновление вместе с `accessHash`.
23
+ *
24
+ * Нужен не ради имени: по одному номеру ответить нельзя, пока собеседник клиенту неизвестен, а
25
+ * `accessHash` живёт только здесь. Поле необязательное: в обновлении его может не быть.
26
+ */
27
+ sender?: { username?: string; accessHash?: { toString(): string } | string | number };
21
28
  };
22
29
 
23
30
  export type MtprotoMediaLike = {
@@ -110,6 +117,9 @@ export function toIncomingMessage(
110
117
  chatId,
111
118
  chatType,
112
119
  senderId,
120
+ // Имя отправителя: по нему отвечают, когда номер клиенту неизвестен, и по нему же продукты
121
+ // связывают человека со своей учётной записью.
122
+ senderUsername: message.sender?.username,
113
123
  messageId: String(message.id),
114
124
  text: message.message ?? "",
115
125
  attachments: collectAttachments(message, chatId),
@@ -17,6 +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
21
  import bigInt from "big-integer";
21
22
  import { Api, TelegramClient } from "telegram";
22
23
  import { CustomFile } from "telegram/client/uploads";
@@ -167,12 +168,46 @@ export class TelegramMtprotoTransport
167
168
  const message = (event as { message?: MtprotoMessageLike }).message;
168
169
  if (!message) return;
169
170
  this.lastActivityAt = new Date();
171
+ // Собеседника запоминаем СРАЗУ: ответить ему по одному номеру нельзя, `accessHash` приносит
172
+ // только это обновление, и к следующему ходу его уже негде взять.
173
+ void this.rememberSender(message);
170
174
  void this.incoming.dispatch(message, this.id, this.options.accountId);
171
175
  };
172
176
  this.incomingListener = listener;
173
177
  this.client.addEventHandler(listener, new NewMessage({}));
174
178
  }
175
179
 
180
+ /**
181
+ * Запомнить написавшего нам человека.
182
+ *
183
+ * Отказ здесь ничего не ломает и не сообщается: приём сообщения важнее, чем возможность
184
+ * ответить по номеру, а без записи остаётся ответ по имени.
185
+ */
186
+ private async rememberSender(message: MtprotoMessageLike): Promise<void> {
187
+ try {
188
+ const hash = message.sender?.accessHash;
189
+ if (hash === undefined || hash === null) return;
190
+ const { chatId, chatType } = peerToChat(message.peerId);
191
+ // В группе отправитель и чат — разные пиры, и запись сложила бы одно вместо другого.
192
+ if (chatType !== "user") return;
193
+ const recipient = { type: "user", id: chatId } as const;
194
+ await this.peerStore.set(
195
+ this.options.accountId,
196
+ recipient,
197
+ {
198
+ type: "user",
199
+ id: chatId,
200
+ accessHash: String(hash),
201
+ username: message.sender?.username,
202
+ resolvedAt: new Date().toISOString(),
203
+ },
204
+ this.options.peerTtlSeconds,
205
+ );
206
+ } catch {
207
+ // приём важнее записи
208
+ }
209
+ }
210
+
176
211
  private stopListeningIfIdle(): void {
177
212
  if (this.incoming.size > 0 || this.incomingListener === null) return;
178
213
  this.client.removeEventHandler(this.incomingListener, new NewMessage({}));