@coffer-org/plugin-telegram 2.1.1 → 2.2.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/dist/runtime/bot.js
CHANGED
|
@@ -7,6 +7,7 @@ import { NewMessage } from 'teleproto/events/index.js';
|
|
|
7
7
|
import { handleIncoming, loadGatePolicy, makeLiveChannel, chunk } from '@coffer-org/plugin-orchestrator/runtime';
|
|
8
8
|
import { recordUser, recordAssistant, buildChain } from "./chain-store.js";
|
|
9
9
|
import { loadBotConfig, hasCredentials, loadReasoningDisplay } from "./config.js";
|
|
10
|
+
import { saveUploadBytes } from '@coffer-org/server/uploads';
|
|
10
11
|
import { getLogger } from '@coffer-org/sdk/logger';
|
|
11
12
|
const log = getLogger('telegram');
|
|
12
13
|
const FALLBACK_REPLY_WINDOW_MS = 1_800_000;
|
|
@@ -77,6 +78,25 @@ export function makeReplyFactory(t, display) {
|
|
|
77
78
|
return display === 'separate' ? ch : { ...ch, segment() { } };
|
|
78
79
|
};
|
|
79
80
|
}
|
|
81
|
+
function mediaInfo(message) {
|
|
82
|
+
const media = message.media;
|
|
83
|
+
if (!media)
|
|
84
|
+
return null;
|
|
85
|
+
const documentName = media.document?.attributes?.find((a) => typeof a.fileName === 'string')?.fileName;
|
|
86
|
+
if (media.document)
|
|
87
|
+
return { mime: media.document.mimeType, label: documentName ? path.basename(documentName) : 'attachment' };
|
|
88
|
+
if (media.photo)
|
|
89
|
+
return { mime: 'image/jpeg', label: 'photo.jpg' };
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
async function downloadAttachment(tg, message, info) {
|
|
93
|
+
const downloaded = await tg.downloadMedia(message, {});
|
|
94
|
+
if (!downloaded || typeof downloaded === 'string')
|
|
95
|
+
throw new Error('Telegram returned no in-memory media bytes');
|
|
96
|
+
const bytes = Buffer.isBuffer(downloaded) ? downloaded : Buffer.from(downloaded);
|
|
97
|
+
const stored = await saveUploadBytes(bytes, { originalName: info.label, mime: info.mime });
|
|
98
|
+
return { name: stored.name, ...(stored.mime ? { mime: stored.mime } : {}), size: stored.size, label: info.label };
|
|
99
|
+
}
|
|
80
100
|
function loadSessionString(file) {
|
|
81
101
|
try {
|
|
82
102
|
return fs.readFileSync(file, 'utf-8');
|
|
@@ -182,7 +202,8 @@ export async function startBot(opts = {}) {
|
|
|
182
202
|
if (message.senderId && meId && message.senderId.toString() === meId)
|
|
183
203
|
return;
|
|
184
204
|
const text = (message.text || message.message || '').trim();
|
|
185
|
-
|
|
205
|
+
const attachmentInfo = mediaInfo(message);
|
|
206
|
+
if (!text && !attachmentInfo)
|
|
186
207
|
return;
|
|
187
208
|
let chatLabel = String(event.chatId ?? '?');
|
|
188
209
|
let peer = event.chatId;
|
|
@@ -194,7 +215,7 @@ export async function startBot(opts = {}) {
|
|
|
194
215
|
}
|
|
195
216
|
catch {
|
|
196
217
|
}
|
|
197
|
-
log.info(`msg [${chatLabel}]: ${text.slice(0, 80)}`);
|
|
218
|
+
log.info(`msg [${chatLabel}]: ${(text || `[${attachmentInfo?.label ?? 'attachment'}]`).slice(0, 80)}`);
|
|
198
219
|
const stopTyping = startTypingPeer(peer);
|
|
199
220
|
try {
|
|
200
221
|
const chatId = String(event.chatId ?? '?');
|
|
@@ -235,6 +256,25 @@ export async function startBot(opts = {}) {
|
|
|
235
256
|
}
|
|
236
257
|
};
|
|
237
258
|
const messages = await buildChain(incomingMsgId, { chatId, fetch, botId: meId ?? '' });
|
|
259
|
+
let preparedMessages;
|
|
260
|
+
const prepareAttachments = attachmentInfo
|
|
261
|
+
? async () => {
|
|
262
|
+
if (preparedMessages)
|
|
263
|
+
return preparedMessages;
|
|
264
|
+
const attachment = await downloadAttachment(tg, message, attachmentInfo);
|
|
265
|
+
await recordUser({
|
|
266
|
+
chatId,
|
|
267
|
+
msgId: incomingMsgId,
|
|
268
|
+
sender: displayName,
|
|
269
|
+
text,
|
|
270
|
+
attachments: [attachment],
|
|
271
|
+
ts: message.date ?? 0,
|
|
272
|
+
replyToId,
|
|
273
|
+
});
|
|
274
|
+
preparedMessages = messages.map((m, i) => i === messages.length - 1 ? { ...m, attachments: [attachment] } : m);
|
|
275
|
+
return preparedMessages;
|
|
276
|
+
}
|
|
277
|
+
: undefined;
|
|
238
278
|
const reasoningDisplay = await loadReasoningDisplay();
|
|
239
279
|
const connector = {
|
|
240
280
|
id: 'telegram',
|
|
@@ -259,6 +299,7 @@ export async function startBot(opts = {}) {
|
|
|
259
299
|
channelSystem: TELEGRAM_FORMAT,
|
|
260
300
|
sender: { id: userId, displayName },
|
|
261
301
|
messages,
|
|
302
|
+
...(prepareAttachments ? { prepareAttachments } : {}),
|
|
262
303
|
});
|
|
263
304
|
}
|
|
264
305
|
finally {
|
|
@@ -4,7 +4,7 @@ const log = getLogger('telegram');
|
|
|
4
4
|
const CONNECTOR = 'telegram';
|
|
5
5
|
const DEFAULT_MAX_DEPTH = 30;
|
|
6
6
|
export async function recordUser(m) {
|
|
7
|
-
await putThreadMessage({ connector: CONNECTOR, chatId: m.chatId, msgId: m.msgId, role: 'user', sender: m.sender ?? null, text: m.text, ts: m.ts, replyToId: m.replyToId });
|
|
7
|
+
await putThreadMessage({ connector: CONNECTOR, chatId: m.chatId, msgId: m.msgId, role: 'user', sender: m.sender ?? null, attachments: m.attachments, text: m.text, ts: m.ts, replyToId: m.replyToId });
|
|
8
8
|
}
|
|
9
9
|
export async function recordAssistant(m) {
|
|
10
10
|
if (m.botMsgId == null)
|
|
@@ -36,7 +36,14 @@ export async function buildChain(headMsgId, opts) {
|
|
|
36
36
|
stored = { msgId: cur, role, sender: null, text: fetched.text, ts: fetched.date, replyToId: fetched.replyToId };
|
|
37
37
|
}
|
|
38
38
|
if (stored.role !== 'reasoning') {
|
|
39
|
-
acc.push({
|
|
39
|
+
acc.push({
|
|
40
|
+
role: stored.role,
|
|
41
|
+
content: stored.text,
|
|
42
|
+
sender: stored.sender,
|
|
43
|
+
...(stored.attachments ? { attachments: stored.attachments } : {}),
|
|
44
|
+
msgId: stored.msgId,
|
|
45
|
+
ts: stored.ts,
|
|
46
|
+
});
|
|
40
47
|
}
|
|
41
48
|
cur = stored.replyToId;
|
|
42
49
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffer-org/plugin-telegram",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=24"
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"test": "node --import tsx --test \"src/runtime/*.test.ts\""
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@coffer-org/plugin-orchestrator": "^2.
|
|
28
|
+
"@coffer-org/plugin-orchestrator": "^2.2.0",
|
|
29
29
|
"@coffer-org/sdk": "^2.1.1",
|
|
30
|
-
"@coffer-org/server": "^2.
|
|
30
|
+
"@coffer-org/server": "^2.3.0",
|
|
31
31
|
"input": "^1.0.1",
|
|
32
32
|
"teleproto": "^1.228.1"
|
|
33
33
|
},
|