@imessaging/telegram-mtproto 0.1.0 → 0.3.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.
|
|
3
|
+
"version": "0.3.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.
|
|
34
|
+
"@imessaging/core": "0.3.0",
|
|
35
35
|
"big-integer": "^1.6.52"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
EditableMessage,
|
|
3
|
+
EditableMessageTransport,
|
|
4
|
+
EditResult,
|
|
2
5
|
MessageRecipient,
|
|
3
|
-
MessageTransport,
|
|
4
6
|
OutboundMessage,
|
|
5
7
|
ResolvedPeer,
|
|
6
8
|
SendResult,
|
|
7
9
|
TelegramPeerStore,
|
|
8
10
|
TransportStatus,
|
|
9
11
|
} from "@imessaging/core";
|
|
10
|
-
import { MemoryPeerStore } from "@imessaging/core";
|
|
12
|
+
import { isTelegramRecipient, MemoryPeerStore } from "@imessaging/core";
|
|
11
13
|
import bigInt from "big-integer";
|
|
12
14
|
import { Api, TelegramClient } from "telegram";
|
|
13
15
|
import { CustomFile } from "telegram/client/uploads";
|
|
@@ -52,7 +54,7 @@ function isChannel(chat: Api.TypeChat): chat is Api.Channel {
|
|
|
52
54
|
return chat.className === "Channel";
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
export class TelegramMtprotoTransport implements
|
|
57
|
+
export class TelegramMtprotoTransport implements EditableMessageTransport {
|
|
56
58
|
readonly id: string;
|
|
57
59
|
private readonly client: TelegramClient;
|
|
58
60
|
private readonly peerStore: TelegramPeerStore;
|
|
@@ -96,6 +98,22 @@ export class TelegramMtprotoTransport implements MessageTransport {
|
|
|
96
98
|
return this.sendWithRetry(message, false);
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Правка отправленного сообщения.
|
|
103
|
+
*
|
|
104
|
+
* Зачем она есть. Карточка в рабочем чате живёт долго и по ходу дела меняет состояние: слать на
|
|
105
|
+
* каждое изменение новое сообщение значит закапывать чат и заставлять человека искать, какое из
|
|
106
|
+
* них последнее. Правится то же самое.
|
|
107
|
+
*
|
|
108
|
+
* Идентификатор сообщения в Telegram нумеруется В ПРЕДЕЛАХ чата, поэтому получатель обязателен
|
|
109
|
+
* и адрес разрешается тем же путём, что при отправке, — включая сброс кеша и повтор на протухшем
|
|
110
|
+
* адресе.
|
|
111
|
+
*/
|
|
112
|
+
async edit(message: EditableMessage): Promise<EditResult> {
|
|
113
|
+
this.assertConnected();
|
|
114
|
+
return this.editWithRetry(message, false);
|
|
115
|
+
}
|
|
116
|
+
|
|
99
117
|
async getStatus(): Promise<TransportStatus> {
|
|
100
118
|
return {
|
|
101
119
|
connected: this.connected && Boolean(this.client.connected),
|
|
@@ -149,6 +167,11 @@ export class TelegramMtprotoTransport implements MessageTransport {
|
|
|
149
167
|
}
|
|
150
168
|
|
|
151
169
|
private async resolvePeer(recipient: MessageRecipient): Promise<ResolvedPeer> {
|
|
170
|
+
// Почтовый получатель сюда доходить не должен: разрешать адрес как @username бессмысленно, а
|
|
171
|
+
// сообщение об отказе тогда врало бы про Telegram.
|
|
172
|
+
if (!isTelegramRecipient(recipient)) {
|
|
173
|
+
throw new Error("Telegram MTProto cannot send email");
|
|
174
|
+
}
|
|
152
175
|
if (recipient.type !== "username" && !recipient.username) {
|
|
153
176
|
throw new Error(
|
|
154
177
|
`Cannot resolve uncached Telegram ${recipient.type} ${recipient.id} without a username`,
|
|
@@ -227,6 +250,35 @@ export class TelegramMtprotoTransport implements MessageTransport {
|
|
|
227
250
|
}
|
|
228
251
|
}
|
|
229
252
|
|
|
253
|
+
private async editWithRetry(message: EditableMessage, retried: boolean): Promise<EditResult> {
|
|
254
|
+
const messageId = Number(message.messageId);
|
|
255
|
+
if (!Number.isSafeInteger(messageId) || messageId <= 0) {
|
|
256
|
+
throw new Error(`Telegram message id must be a positive integer: ${message.messageId}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
let peer: Api.TypeInputPeer | null = null;
|
|
260
|
+
try {
|
|
261
|
+
peer = await this.getInputPeer(message.recipient);
|
|
262
|
+
// Кнопки здесь не передаются — ровно как и при отправке этим транспортом: inline-клавиатуру
|
|
263
|
+
// MTProto-аккаунт не рисует. Передать их сюда значило бы обещать разметку, которой не будет.
|
|
264
|
+
await this.client.editMessage(peer, {
|
|
265
|
+
message: messageId,
|
|
266
|
+
text: message.text,
|
|
267
|
+
parseMode: message.parseMode?.toLowerCase(),
|
|
268
|
+
});
|
|
269
|
+
this.lastActivityAt = new Date();
|
|
270
|
+
return {
|
|
271
|
+
transportId: this.id,
|
|
272
|
+
messageId: message.messageId,
|
|
273
|
+
recipientId: this.getPeerId(peer),
|
|
274
|
+
};
|
|
275
|
+
} catch (error: unknown) {
|
|
276
|
+
if (retried || !this.isInvalidPeerError(error)) throw error;
|
|
277
|
+
await this.peerStore.delete(this.options.accountId, message.recipient);
|
|
278
|
+
return this.editWithRetry(message, true);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
230
282
|
private isInvalidPeerError(error: unknown): boolean {
|
|
231
283
|
if (typeof error !== "object" || error === null) return false;
|
|
232
284
|
const telegramError = error as TelegramRpcError;
|