@coffer-org/plugin-telegram 2.1.1 → 2.2.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.
@@ -77,6 +77,25 @@ export function makeReplyFactory(t, display) {
77
77
  return display === 'separate' ? ch : { ...ch, segment() { } };
78
78
  };
79
79
  }
80
+ function mediaInfo(message) {
81
+ const media = message.media;
82
+ if (!media)
83
+ return null;
84
+ const documentName = media.document?.attributes?.find((a) => typeof a.fileName === 'string')?.fileName;
85
+ if (media.document)
86
+ return { mime: media.document.mimeType, label: documentName ? path.basename(documentName) : 'attachment' };
87
+ if (media.photo)
88
+ return { mime: 'image/jpeg', label: 'photo.jpg' };
89
+ return null;
90
+ }
91
+ async function downloadAttachment(tg, message, info, materializer) {
92
+ const downloaded = await tg.downloadMedia(message, {});
93
+ if (!downloaded || typeof downloaded === 'string')
94
+ throw new Error('Telegram returned no in-memory media bytes');
95
+ const bytes = Buffer.isBuffer(downloaded) ? downloaded : Buffer.from(downloaded);
96
+ const stored = await materializer.store(bytes, { originalName: info.label, mime: info.mime });
97
+ return { ...stored, label: info.label };
98
+ }
80
99
  function loadSessionString(file) {
81
100
  try {
82
101
  return fs.readFileSync(file, 'utf-8');
@@ -182,7 +201,8 @@ export async function startBot(opts = {}) {
182
201
  if (message.senderId && meId && message.senderId.toString() === meId)
183
202
  return;
184
203
  const text = (message.text || message.message || '').trim();
185
- if (!text)
204
+ const attachmentInfo = mediaInfo(message);
205
+ if (!text && !attachmentInfo)
186
206
  return;
187
207
  let chatLabel = String(event.chatId ?? '?');
188
208
  let peer = event.chatId;
@@ -194,7 +214,7 @@ export async function startBot(opts = {}) {
194
214
  }
195
215
  catch {
196
216
  }
197
- log.info(`msg [${chatLabel}]: ${text.slice(0, 80)}`);
217
+ log.info(`msg [${chatLabel}]: ${(text || `[${attachmentInfo?.label ?? 'attachment'}]`).slice(0, 80)}`);
198
218
  const stopTyping = startTypingPeer(peer);
199
219
  try {
200
220
  const chatId = String(event.chatId ?? '?');
@@ -235,6 +255,25 @@ export async function startBot(opts = {}) {
235
255
  }
236
256
  };
237
257
  const messages = await buildChain(incomingMsgId, { chatId, fetch, botId: meId ?? '' });
258
+ let preparedMessages;
259
+ const prepareAttachments = attachmentInfo
260
+ ? async (materializer) => {
261
+ if (preparedMessages)
262
+ return preparedMessages;
263
+ const attachment = await downloadAttachment(tg, message, attachmentInfo, materializer);
264
+ await recordUser({
265
+ chatId,
266
+ msgId: incomingMsgId,
267
+ sender: displayName,
268
+ text,
269
+ attachments: [attachment],
270
+ ts: message.date ?? 0,
271
+ replyToId,
272
+ });
273
+ preparedMessages = messages.map((m, i) => i === messages.length - 1 ? { ...m, attachments: [attachment] } : m);
274
+ return preparedMessages;
275
+ }
276
+ : undefined;
238
277
  const reasoningDisplay = await loadReasoningDisplay();
239
278
  const connector = {
240
279
  id: 'telegram',
@@ -259,6 +298,7 @@ export async function startBot(opts = {}) {
259
298
  channelSystem: TELEGRAM_FORMAT,
260
299
  sender: { id: userId, displayName },
261
300
  messages,
301
+ ...(prepareAttachments ? { prepareAttachments } : {}),
262
302
  });
263
303
  }
264
304
  finally {
@@ -10,6 +10,7 @@ export declare function recordUser(m: {
10
10
  msgId: string;
11
11
  sender?: string | null;
12
12
  text: string;
13
+ attachments?: NonNullable<ConvMessage['attachments']>;
13
14
  ts: number;
14
15
  replyToId: string | null;
15
16
  }): Promise<void>;
@@ -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({ role: stored.role, content: stored.text, sender: stored.sender, msgId: stored.msgId, ts: stored.ts });
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.1.1",
3
+ "version": "2.2.1",
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.1.1",
28
+ "@coffer-org/plugin-orchestrator": "^2.2.1",
29
29
  "@coffer-org/sdk": "^2.1.1",
30
- "@coffer-org/server": "^2.2.2",
30
+ "@coffer-org/server": "^2.3.0",
31
31
  "input": "^1.0.1",
32
32
  "teleproto": "^1.228.1"
33
33
  },