@elizaos/plugin-telegram 1.0.10 → 1.6.2
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/environment.d.ts +1 -5
- package/dist/index.js +323 -82
- package/dist/index.js.map +1 -1
- package/dist/messageManager.d.ts +46 -2
- package/dist/utils.d.ts +8 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
Role,
|
|
20
20
|
Service,
|
|
21
21
|
createUniqueUuid as createUniqueUuid2,
|
|
22
|
-
logger as
|
|
22
|
+
logger as logger3
|
|
23
23
|
} from "@elizaos/core";
|
|
24
24
|
import { Telegraf } from "telegraf";
|
|
25
25
|
|
|
@@ -28,13 +28,15 @@ import {
|
|
|
28
28
|
ChannelType,
|
|
29
29
|
EventType,
|
|
30
30
|
ModelType,
|
|
31
|
+
ServiceType,
|
|
31
32
|
createUniqueUuid,
|
|
32
|
-
logger
|
|
33
|
+
logger as logger2
|
|
33
34
|
} from "@elizaos/core";
|
|
34
35
|
import { Markup as Markup2 } from "telegraf";
|
|
35
36
|
|
|
36
37
|
// src/utils.ts
|
|
37
38
|
import { Markup } from "telegraf";
|
|
39
|
+
import { logger } from "@elizaos/core";
|
|
38
40
|
var TELEGRAM_RESERVED_REGEX = /([_*[\]()~`>#+\-=|{}.!\\])/g;
|
|
39
41
|
function escapePlainText(text) {
|
|
40
42
|
if (!text) return "";
|
|
@@ -127,14 +129,32 @@ function convertMarkdownToTelegram(markdown) {
|
|
|
127
129
|
}
|
|
128
130
|
function convertToTelegramButtons(buttons) {
|
|
129
131
|
if (!buttons) return [];
|
|
130
|
-
|
|
132
|
+
const telegramButtons = [];
|
|
133
|
+
for (const button of buttons) {
|
|
134
|
+
if (!button || !button.text || !button.url) {
|
|
135
|
+
logger.warn({ button }, "Invalid button configuration, skipping");
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
let telegramButton;
|
|
131
139
|
switch (button.kind) {
|
|
132
140
|
case "login":
|
|
133
|
-
|
|
141
|
+
telegramButton = Markup.button.login(button.text, button.url);
|
|
142
|
+
break;
|
|
134
143
|
case "url":
|
|
135
|
-
|
|
144
|
+
telegramButton = Markup.button.url(button.text, button.url);
|
|
145
|
+
break;
|
|
146
|
+
default:
|
|
147
|
+
logger.warn(`Unknown button kind '${button.kind}', treating as URL button`);
|
|
148
|
+
telegramButton = Markup.button.url(button.text, button.url);
|
|
149
|
+
break;
|
|
136
150
|
}
|
|
137
|
-
|
|
151
|
+
telegramButtons.push(telegramButton);
|
|
152
|
+
}
|
|
153
|
+
return telegramButtons;
|
|
154
|
+
}
|
|
155
|
+
function cleanText(text) {
|
|
156
|
+
if (!text) return "";
|
|
157
|
+
return text.split("\0").join("");
|
|
138
158
|
}
|
|
139
159
|
|
|
140
160
|
// src/messageManager.ts
|
|
@@ -165,7 +185,6 @@ var MessageManager = class {
|
|
|
165
185
|
this.bot = bot;
|
|
166
186
|
this.runtime = runtime;
|
|
167
187
|
}
|
|
168
|
-
// Process image messages and generate descriptions
|
|
169
188
|
/**
|
|
170
189
|
* Process an image from a Telegram message to extract the image URL and description.
|
|
171
190
|
*
|
|
@@ -175,12 +194,12 @@ var MessageManager = class {
|
|
|
175
194
|
async processImage(message) {
|
|
176
195
|
try {
|
|
177
196
|
let imageUrl = null;
|
|
178
|
-
|
|
197
|
+
logger2.info(`Telegram Message: ${JSON.stringify(message, null, 2)}`);
|
|
179
198
|
if ("photo" in message && message.photo?.length > 0) {
|
|
180
199
|
const photo = message.photo[message.photo.length - 1];
|
|
181
200
|
const fileLink = await this.bot.telegram.getFileLink(photo.file_id);
|
|
182
201
|
imageUrl = fileLink.toString();
|
|
183
|
-
} else if ("document" in message && message.document?.mime_type?.startsWith("image/")) {
|
|
202
|
+
} else if ("document" in message && message.document?.mime_type?.startsWith("image/") && !message.document?.mime_type?.startsWith("application/pdf")) {
|
|
184
203
|
const fileLink = await this.bot.telegram.getFileLink(message.document.file_id);
|
|
185
204
|
imageUrl = fileLink.toString();
|
|
186
205
|
}
|
|
@@ -197,7 +216,237 @@ ${description}]` };
|
|
|
197
216
|
}
|
|
198
217
|
return null;
|
|
199
218
|
}
|
|
200
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Process a document from a Telegram message to extract the document URL and description.
|
|
221
|
+
* Handles PDFs and other document types by converting them to text when possible.
|
|
222
|
+
*
|
|
223
|
+
* @param {Message} message - The Telegram message object containing the document.
|
|
224
|
+
* @returns {Promise<{ description: string } | null>} The description of the processed document or null if no document found.
|
|
225
|
+
*/
|
|
226
|
+
async processDocument(message) {
|
|
227
|
+
try {
|
|
228
|
+
if (!("document" in message) || !message.document) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const document = message.document;
|
|
232
|
+
const fileLink = await this.bot.telegram.getFileLink(document.file_id);
|
|
233
|
+
const documentUrl = fileLink.toString();
|
|
234
|
+
logger2.info(
|
|
235
|
+
`Processing document: ${document.file_name} (${document.mime_type}, ${document.file_size} bytes)`
|
|
236
|
+
);
|
|
237
|
+
const documentProcessor = this.getDocumentProcessor(document.mime_type);
|
|
238
|
+
if (documentProcessor) {
|
|
239
|
+
return await documentProcessor(document, documentUrl);
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
title: `Document: ${document.file_name || "Unknown Document"}`,
|
|
243
|
+
fullText: "",
|
|
244
|
+
formattedDescription: `[Document: ${document.file_name || "Unknown Document"}
|
|
245
|
+
Type: ${document.mime_type || "unknown"}
|
|
246
|
+
Size: ${document.file_size || 0} bytes]`,
|
|
247
|
+
fileName: document.file_name || "Unknown Document",
|
|
248
|
+
mimeType: document.mime_type,
|
|
249
|
+
fileSize: document.file_size
|
|
250
|
+
};
|
|
251
|
+
} catch (error) {
|
|
252
|
+
logger2.error({ error }, "Error processing document");
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get the appropriate document processor based on MIME type.
|
|
258
|
+
*/
|
|
259
|
+
getDocumentProcessor(mimeType) {
|
|
260
|
+
if (!mimeType) return null;
|
|
261
|
+
const processors = {
|
|
262
|
+
"application/pdf": this.processPdfDocument.bind(this),
|
|
263
|
+
"text/": this.processTextDocument.bind(this),
|
|
264
|
+
// covers text/plain, text/csv, text/markdown, etc.
|
|
265
|
+
"application/json": this.processTextDocument.bind(this)
|
|
266
|
+
};
|
|
267
|
+
for (const [pattern, processor] of Object.entries(processors)) {
|
|
268
|
+
if (mimeType.startsWith(pattern)) {
|
|
269
|
+
return processor;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Process PDF documents by converting them to text.
|
|
276
|
+
*/
|
|
277
|
+
async processPdfDocument(document, documentUrl) {
|
|
278
|
+
try {
|
|
279
|
+
const pdfService = this.runtime.getService(ServiceType.PDF);
|
|
280
|
+
if (!pdfService) {
|
|
281
|
+
logger2.warn("PDF service not available, using fallback");
|
|
282
|
+
return {
|
|
283
|
+
title: `PDF Document: ${document.file_name || "Unknown Document"}`,
|
|
284
|
+
fullText: "",
|
|
285
|
+
formattedDescription: `[PDF Document: ${document.file_name || "Unknown Document"}
|
|
286
|
+
Size: ${document.file_size || 0} bytes
|
|
287
|
+
Unable to extract text content]`,
|
|
288
|
+
fileName: document.file_name || "Unknown Document",
|
|
289
|
+
mimeType: document.mime_type,
|
|
290
|
+
fileSize: document.file_size
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
const response = await fetch(documentUrl);
|
|
294
|
+
if (!response.ok) {
|
|
295
|
+
throw new Error(`Failed to fetch PDF: ${response.status}`);
|
|
296
|
+
}
|
|
297
|
+
const pdfBuffer = await response.arrayBuffer();
|
|
298
|
+
const text = await pdfService.convertPdfToText(Buffer.from(pdfBuffer));
|
|
299
|
+
logger2.info(`PDF processed successfully: ${text.length} characters extracted`);
|
|
300
|
+
return {
|
|
301
|
+
title: document.file_name || "Unknown Document",
|
|
302
|
+
fullText: text,
|
|
303
|
+
formattedDescription: `[PDF Document: ${document.file_name || "Unknown Document"}
|
|
304
|
+
Size: ${document.file_size || 0} bytes
|
|
305
|
+
Text extracted successfully: ${text.length} characters]`,
|
|
306
|
+
fileName: document.file_name || "Unknown Document",
|
|
307
|
+
mimeType: document.mime_type,
|
|
308
|
+
fileSize: document.file_size
|
|
309
|
+
};
|
|
310
|
+
} catch (error) {
|
|
311
|
+
logger2.error({ error }, "Error processing PDF document");
|
|
312
|
+
return {
|
|
313
|
+
title: `PDF Document: ${document.file_name || "Unknown Document"}`,
|
|
314
|
+
fullText: "",
|
|
315
|
+
formattedDescription: `[PDF Document: ${document.file_name || "Unknown Document"}
|
|
316
|
+
Size: ${document.file_size || 0} bytes
|
|
317
|
+
Error: Unable to extract text content]`,
|
|
318
|
+
fileName: document.file_name || "Unknown Document",
|
|
319
|
+
mimeType: document.mime_type,
|
|
320
|
+
fileSize: document.file_size
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Process text documents by fetching their content.
|
|
326
|
+
*/
|
|
327
|
+
async processTextDocument(document, documentUrl) {
|
|
328
|
+
try {
|
|
329
|
+
const response = await fetch(documentUrl);
|
|
330
|
+
if (!response.ok) {
|
|
331
|
+
throw new Error(`Failed to fetch text document: ${response.status}`);
|
|
332
|
+
}
|
|
333
|
+
const text = await response.text();
|
|
334
|
+
logger2.info(`Text document processed successfully: ${text.length} characters extracted`);
|
|
335
|
+
return {
|
|
336
|
+
title: document.file_name || "Unknown Document",
|
|
337
|
+
fullText: text,
|
|
338
|
+
formattedDescription: `[Text Document: ${document.file_name || "Unknown Document"}
|
|
339
|
+
Size: ${document.file_size || 0} bytes
|
|
340
|
+
Text extracted successfully: ${text.length} characters]`,
|
|
341
|
+
fileName: document.file_name || "Unknown Document",
|
|
342
|
+
mimeType: document.mime_type,
|
|
343
|
+
fileSize: document.file_size
|
|
344
|
+
};
|
|
345
|
+
} catch (error) {
|
|
346
|
+
logger2.error({ error }, "Error processing text document");
|
|
347
|
+
return {
|
|
348
|
+
title: `Text Document: ${document.file_name || "Unknown Document"}`,
|
|
349
|
+
fullText: "",
|
|
350
|
+
formattedDescription: `[Text Document: ${document.file_name || "Unknown Document"}
|
|
351
|
+
Size: ${document.file_size || 0} bytes
|
|
352
|
+
Error: Unable to read content]`,
|
|
353
|
+
fileName: document.file_name || "Unknown Document",
|
|
354
|
+
mimeType: document.mime_type,
|
|
355
|
+
fileSize: document.file_size
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Processes the message content, documents, and images to generate
|
|
361
|
+
* processed content and media attachments.
|
|
362
|
+
*
|
|
363
|
+
* @param {Message} message The message to process
|
|
364
|
+
* @returns {Promise<{ processedContent: string; attachments: Media[] }>} Processed content and media attachments
|
|
365
|
+
*/
|
|
366
|
+
async processMessage(message) {
|
|
367
|
+
let processedContent = "";
|
|
368
|
+
let attachments = [];
|
|
369
|
+
if ("text" in message && message.text) {
|
|
370
|
+
processedContent = message.text;
|
|
371
|
+
} else if ("caption" in message && message.caption) {
|
|
372
|
+
processedContent = message.caption;
|
|
373
|
+
}
|
|
374
|
+
if ("document" in message && message.document) {
|
|
375
|
+
const document = message.document;
|
|
376
|
+
const documentInfo = await this.processDocument(message);
|
|
377
|
+
if (documentInfo) {
|
|
378
|
+
try {
|
|
379
|
+
const fileLink = await this.bot.telegram.getFileLink(document.file_id);
|
|
380
|
+
const title = documentInfo.title;
|
|
381
|
+
const fullText = documentInfo.fullText;
|
|
382
|
+
if (fullText) {
|
|
383
|
+
const documentContent = `
|
|
384
|
+
|
|
385
|
+
--- DOCUMENT CONTENT ---
|
|
386
|
+
Title: ${title}
|
|
387
|
+
|
|
388
|
+
Full Content:
|
|
389
|
+
${fullText}
|
|
390
|
+
--- END DOCUMENT ---
|
|
391
|
+
|
|
392
|
+
`;
|
|
393
|
+
processedContent += documentContent;
|
|
394
|
+
}
|
|
395
|
+
attachments.push({
|
|
396
|
+
id: document.file_id,
|
|
397
|
+
url: fileLink.toString(),
|
|
398
|
+
title,
|
|
399
|
+
source: document.mime_type?.startsWith("application/pdf") ? "PDF" : "Document",
|
|
400
|
+
description: documentInfo.formattedDescription,
|
|
401
|
+
text: fullText
|
|
402
|
+
});
|
|
403
|
+
logger2.info(`Document processed successfully: ${documentInfo.fileName}`);
|
|
404
|
+
} catch (error) {
|
|
405
|
+
logger2.error({ error }, `Error processing document ${documentInfo.fileName}`);
|
|
406
|
+
attachments.push({
|
|
407
|
+
id: document.file_id,
|
|
408
|
+
url: "",
|
|
409
|
+
title: `Document: ${documentInfo.fileName}`,
|
|
410
|
+
source: "Document",
|
|
411
|
+
description: `Document processing failed: ${documentInfo.fileName}`,
|
|
412
|
+
text: `Document: ${documentInfo.fileName}
|
|
413
|
+
Size: ${documentInfo.fileSize || 0} bytes
|
|
414
|
+
Type: ${documentInfo.mimeType || "unknown"}`
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
attachments.push({
|
|
419
|
+
id: document.file_id,
|
|
420
|
+
url: "",
|
|
421
|
+
title: `Document: ${document.file_name || "Unknown Document"}`,
|
|
422
|
+
source: "Document",
|
|
423
|
+
description: `Document: ${document.file_name || "Unknown Document"}`,
|
|
424
|
+
text: `Document: ${document.file_name || "Unknown Document"}
|
|
425
|
+
Size: ${document.file_size || 0} bytes
|
|
426
|
+
Type: ${document.mime_type || "unknown"}`
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if ("photo" in message && message.photo?.length > 0) {
|
|
431
|
+
const imageInfo = await this.processImage(message);
|
|
432
|
+
if (imageInfo) {
|
|
433
|
+
const photo = message.photo[message.photo.length - 1];
|
|
434
|
+
const fileLink = await this.bot.telegram.getFileLink(photo.file_id);
|
|
435
|
+
attachments.push({
|
|
436
|
+
id: photo.file_id,
|
|
437
|
+
url: fileLink.toString(),
|
|
438
|
+
title: "Image Attachment",
|
|
439
|
+
source: "Image",
|
|
440
|
+
description: imageInfo.description,
|
|
441
|
+
text: imageInfo.description
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
logger2.info(
|
|
446
|
+
`Message processed - Content: ${processedContent ? "yes" : "no"}, Attachments: ${attachments.length}`
|
|
447
|
+
);
|
|
448
|
+
return { processedContent, attachments };
|
|
449
|
+
}
|
|
201
450
|
/**
|
|
202
451
|
* Sends a message in chunks, handling attachments and splitting the message if necessary
|
|
203
452
|
*
|
|
@@ -236,14 +485,14 @@ ${description}]` };
|
|
|
236
485
|
const sentMessages = [];
|
|
237
486
|
const telegramButtons = convertToTelegramButtons(content.buttons ?? []);
|
|
238
487
|
if (!ctx.chat) {
|
|
239
|
-
|
|
488
|
+
logger2.error("sendMessageInChunks: ctx.chat is undefined");
|
|
240
489
|
return [];
|
|
241
490
|
}
|
|
242
491
|
await ctx.telegram.sendChatAction(ctx.chat.id, "typing");
|
|
243
492
|
for (let i = 0; i < chunks.length; i++) {
|
|
244
493
|
const chunk = convertMarkdownToTelegram(chunks[i]);
|
|
245
494
|
if (!ctx.chat) {
|
|
246
|
-
|
|
495
|
+
logger2.error("sendMessageInChunks loop: ctx.chat is undefined");
|
|
247
496
|
continue;
|
|
248
497
|
}
|
|
249
498
|
const sentMessage = await ctx.telegram.sendMessage(ctx.chat.id, chunk, {
|
|
@@ -299,19 +548,18 @@ ${description}]` };
|
|
|
299
548
|
fileStream.destroy();
|
|
300
549
|
}
|
|
301
550
|
}
|
|
302
|
-
|
|
551
|
+
logger2.info(
|
|
303
552
|
`${type.charAt(0).toUpperCase() + type.slice(1)} sent successfully: ${mediaPath}`
|
|
304
553
|
);
|
|
305
554
|
} catch (error) {
|
|
306
555
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
307
|
-
|
|
556
|
+
logger2.error(
|
|
308
557
|
{ originalError: error },
|
|
309
558
|
`Failed to send ${type}. Path: ${mediaPath}. Error: ${errorMessage}`
|
|
310
559
|
);
|
|
311
560
|
throw error;
|
|
312
561
|
}
|
|
313
562
|
}
|
|
314
|
-
// Split message into smaller parts
|
|
315
563
|
/**
|
|
316
564
|
* Splits a given text into an array of strings based on the maximum message length.
|
|
317
565
|
*
|
|
@@ -334,7 +582,6 @@ ${description}]` };
|
|
|
334
582
|
if (currentChunk) chunks.push(currentChunk);
|
|
335
583
|
return chunks;
|
|
336
584
|
}
|
|
337
|
-
// Main handler for incoming messages
|
|
338
585
|
/**
|
|
339
586
|
* Handle incoming messages from Telegram and process them accordingly.
|
|
340
587
|
* @param {Context} ctx - The context object containing information about the message.
|
|
@@ -347,21 +594,23 @@ ${description}]` };
|
|
|
347
594
|
const entityId = createUniqueUuid(this.runtime, ctx.from.id.toString());
|
|
348
595
|
const threadId = "is_topic_message" in message && message.is_topic_message ? message.message_thread_id?.toString() : void 0;
|
|
349
596
|
if (!ctx.chat) {
|
|
350
|
-
|
|
597
|
+
logger2.error("handleMessage: ctx.chat is undefined");
|
|
351
598
|
return;
|
|
352
599
|
}
|
|
353
600
|
const telegramRoomid = threadId ? `${ctx.chat.id}-${threadId}` : ctx.chat.id.toString();
|
|
354
601
|
const roomId = createUniqueUuid(this.runtime, telegramRoomid);
|
|
355
602
|
const messageId = createUniqueUuid(this.runtime, message?.message_id?.toString());
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
603
|
+
const { processedContent, attachments } = await this.processMessage(message);
|
|
604
|
+
const cleanedContent = cleanText(processedContent);
|
|
605
|
+
const cleanedAttachments = attachments.map((att) => ({
|
|
606
|
+
...att,
|
|
607
|
+
text: cleanText(att.text),
|
|
608
|
+
description: cleanText(att.description),
|
|
609
|
+
title: cleanText(att.title)
|
|
610
|
+
}));
|
|
611
|
+
if (!cleanedContent && cleanedAttachments.length === 0) {
|
|
612
|
+
return;
|
|
362
613
|
}
|
|
363
|
-
const fullText = imageInfo ? `${messageText} ${imageInfo.description}` : messageText;
|
|
364
|
-
if (!fullText) return;
|
|
365
614
|
const chat = message.chat;
|
|
366
615
|
const channelType = getChannelType(chat);
|
|
367
616
|
const sourceId = createUniqueUuid(this.runtime, "" + chat.id);
|
|
@@ -383,10 +632,9 @@ ${description}]` };
|
|
|
383
632
|
agentId: this.runtime.agentId,
|
|
384
633
|
roomId,
|
|
385
634
|
content: {
|
|
386
|
-
text:
|
|
387
|
-
|
|
635
|
+
text: cleanedContent || " ",
|
|
636
|
+
attachments: cleanedAttachments,
|
|
388
637
|
source: "telegram",
|
|
389
|
-
// url?
|
|
390
638
|
channelType,
|
|
391
639
|
inReplyTo: "reply_to_message" in message && message.reply_to_message ? createUniqueUuid(this.runtime, message.reply_to_message.message_id.toString()) : void 0
|
|
392
640
|
},
|
|
@@ -442,26 +690,19 @@ ${description}]` };
|
|
|
442
690
|
}
|
|
443
691
|
return memories;
|
|
444
692
|
} catch (error) {
|
|
445
|
-
|
|
693
|
+
logger2.error({ error }, "Error in message callback");
|
|
446
694
|
return [];
|
|
447
695
|
}
|
|
448
696
|
};
|
|
449
|
-
this.runtime.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
this.runtime.
|
|
456
|
-
runtime: this.runtime,
|
|
457
|
-
message: memory,
|
|
458
|
-
callback,
|
|
459
|
-
source: "telegram",
|
|
460
|
-
ctx,
|
|
461
|
-
originalMessage: message
|
|
462
|
-
});
|
|
697
|
+
if (!this.runtime.messageService) {
|
|
698
|
+
logger2.error("Message service is not available");
|
|
699
|
+
throw new Error(
|
|
700
|
+
"Message service is not initialized. Ensure the message service is properly configured."
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
await this.runtime.messageService.handleMessage(this.runtime, memory, callback);
|
|
463
704
|
} catch (error) {
|
|
464
|
-
|
|
705
|
+
logger2.error(
|
|
465
706
|
{
|
|
466
707
|
error,
|
|
467
708
|
chatId: ctx.chat?.id,
|
|
@@ -527,7 +768,7 @@ ${description}]` };
|
|
|
527
768
|
};
|
|
528
769
|
return [responseMemory];
|
|
529
770
|
} catch (error) {
|
|
530
|
-
|
|
771
|
+
logger2.error({ error }, "Error in reaction callback");
|
|
531
772
|
return [];
|
|
532
773
|
}
|
|
533
774
|
};
|
|
@@ -555,7 +796,7 @@ ${description}]` };
|
|
|
555
796
|
});
|
|
556
797
|
} catch (error) {
|
|
557
798
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
558
|
-
|
|
799
|
+
logger2.error(
|
|
559
800
|
{
|
|
560
801
|
error: errorMessage,
|
|
561
802
|
originalError: error
|
|
@@ -621,7 +862,7 @@ ${description}]` };
|
|
|
621
862
|
return sentMessages;
|
|
622
863
|
} catch (error) {
|
|
623
864
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
624
|
-
|
|
865
|
+
logger2.error(
|
|
625
866
|
{
|
|
626
867
|
error: errorMessage,
|
|
627
868
|
originalError: error
|
|
@@ -648,10 +889,10 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
648
889
|
*/
|
|
649
890
|
constructor(runtime) {
|
|
650
891
|
super(runtime);
|
|
651
|
-
|
|
892
|
+
logger3.log("\u{1F4F1} Constructing new TelegramService...");
|
|
652
893
|
const botToken = runtime.getSetting("TELEGRAM_BOT_TOKEN");
|
|
653
894
|
if (!botToken || botToken.trim() === "") {
|
|
654
|
-
|
|
895
|
+
logger3.warn("Telegram Bot Token not provided - Telegram functionality will be unavailable");
|
|
655
896
|
this.bot = null;
|
|
656
897
|
this.messageManager = null;
|
|
657
898
|
return;
|
|
@@ -664,9 +905,9 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
664
905
|
try {
|
|
665
906
|
this.bot = new Telegraf(botToken, this.options);
|
|
666
907
|
this.messageManager = new MessageManager(this.bot, this.runtime);
|
|
667
|
-
|
|
908
|
+
logger3.log("\u2705 TelegramService constructor completed");
|
|
668
909
|
} catch (error) {
|
|
669
|
-
|
|
910
|
+
logger3.error(
|
|
670
911
|
`Error initializing Telegram bot: ${error instanceof Error ? error.message : String(error)}`
|
|
671
912
|
);
|
|
672
913
|
this.bot = null;
|
|
@@ -682,7 +923,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
682
923
|
static async start(runtime) {
|
|
683
924
|
const service = new _TelegramService(runtime);
|
|
684
925
|
if (!service.bot) {
|
|
685
|
-
|
|
926
|
+
logger3.warn("Telegram service started without bot functionality - no bot token provided");
|
|
686
927
|
return service;
|
|
687
928
|
}
|
|
688
929
|
const maxRetries = 5;
|
|
@@ -690,10 +931,10 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
690
931
|
let lastError = null;
|
|
691
932
|
while (retryCount < maxRetries) {
|
|
692
933
|
try {
|
|
693
|
-
|
|
934
|
+
logger3.success(
|
|
694
935
|
`\u2705 Telegram client successfully started for character ${runtime.character.name}`
|
|
695
936
|
);
|
|
696
|
-
|
|
937
|
+
logger3.log("\u{1F680} Starting Telegram bot...");
|
|
697
938
|
await service.initializeBot();
|
|
698
939
|
service.setupMiddlewares();
|
|
699
940
|
service.setupMessageHandlers();
|
|
@@ -701,18 +942,18 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
701
942
|
return service;
|
|
702
943
|
} catch (error) {
|
|
703
944
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
704
|
-
|
|
945
|
+
logger3.error(
|
|
705
946
|
`Telegram initialization attempt ${retryCount + 1} failed: ${lastError.message}`
|
|
706
947
|
);
|
|
707
948
|
retryCount++;
|
|
708
949
|
if (retryCount < maxRetries) {
|
|
709
950
|
const delay = 2 ** retryCount * 1e3;
|
|
710
|
-
|
|
951
|
+
logger3.info(`Retrying Telegram initialization in ${delay / 1e3} seconds...`);
|
|
711
952
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
712
953
|
}
|
|
713
954
|
}
|
|
714
955
|
}
|
|
715
|
-
|
|
956
|
+
logger3.error(
|
|
716
957
|
`Telegram initialization failed after ${maxRetries} attempts. Last error: ${lastError?.message}. Service will continue without Telegram functionality.`
|
|
717
958
|
);
|
|
718
959
|
return service;
|
|
@@ -751,7 +992,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
751
992
|
allowedUpdates: ["message", "message_reaction"]
|
|
752
993
|
});
|
|
753
994
|
const botInfo = await this.bot.telegram.getMe();
|
|
754
|
-
|
|
995
|
+
logger3.log(`Bot info: ${JSON.stringify(botInfo)}`);
|
|
755
996
|
process.once("SIGINT", () => this.bot?.stop("SIGINT"));
|
|
756
997
|
process.once("SIGTERM", () => this.bot?.stop("SIGTERM"));
|
|
757
998
|
}
|
|
@@ -785,7 +1026,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
785
1026
|
*/
|
|
786
1027
|
async authorizationMiddleware(ctx, next) {
|
|
787
1028
|
if (!await this.isGroupAuthorized(ctx)) {
|
|
788
|
-
|
|
1029
|
+
logger3.debug("Chat not authorized, skipping message processing");
|
|
789
1030
|
return;
|
|
790
1031
|
}
|
|
791
1032
|
await next();
|
|
@@ -825,7 +1066,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
825
1066
|
try {
|
|
826
1067
|
await this.handleForumTopic(ctx);
|
|
827
1068
|
} catch (error) {
|
|
828
|
-
|
|
1069
|
+
logger3.error({ error }, `Error handling forum topic: ${error}`);
|
|
829
1070
|
}
|
|
830
1071
|
}
|
|
831
1072
|
if (ctx.from && ctx.chat.type !== "private") {
|
|
@@ -843,14 +1084,14 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
843
1084
|
try {
|
|
844
1085
|
await this.messageManager.handleMessage(ctx);
|
|
845
1086
|
} catch (error) {
|
|
846
|
-
|
|
1087
|
+
logger3.error({ error }, "Error handling message");
|
|
847
1088
|
}
|
|
848
1089
|
});
|
|
849
1090
|
this.bot?.on("message_reaction", async (ctx) => {
|
|
850
1091
|
try {
|
|
851
1092
|
await this.messageManager.handleReaction(ctx);
|
|
852
1093
|
} catch (error) {
|
|
853
|
-
|
|
1094
|
+
logger3.error({ error }, "Error handling reaction");
|
|
854
1095
|
}
|
|
855
1096
|
});
|
|
856
1097
|
}
|
|
@@ -870,7 +1111,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
870
1111
|
const allowedChatsList = JSON.parse(allowedChats);
|
|
871
1112
|
return allowedChatsList.includes(chatId);
|
|
872
1113
|
} catch (error) {
|
|
873
|
-
|
|
1114
|
+
logger3.error({ error }, "Error parsing TELEGRAM_ALLOWED_CHATS");
|
|
874
1115
|
return false;
|
|
875
1116
|
}
|
|
876
1117
|
}
|
|
@@ -1059,7 +1300,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1059
1300
|
);
|
|
1060
1301
|
owner = foundOwner || null;
|
|
1061
1302
|
} catch (error) {
|
|
1062
|
-
|
|
1303
|
+
logger3.warn(
|
|
1063
1304
|
`Could not get chat administrators: ${error instanceof Error ? error.message : String(error)}`
|
|
1064
1305
|
);
|
|
1065
1306
|
}
|
|
@@ -1172,13 +1413,13 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1172
1413
|
worldId
|
|
1173
1414
|
});
|
|
1174
1415
|
} else {
|
|
1175
|
-
|
|
1416
|
+
logger3.warn(
|
|
1176
1417
|
`Skipping entity sync due to missing ID: ${JSON.stringify(entity.names)}`
|
|
1177
1418
|
);
|
|
1178
1419
|
}
|
|
1179
1420
|
} catch (err) {
|
|
1180
1421
|
const telegramMetadata = entity.metadata?.telegram;
|
|
1181
|
-
|
|
1422
|
+
logger3.warn(`Failed to sync user ${telegramMetadata?.username}: ${err}`);
|
|
1182
1423
|
}
|
|
1183
1424
|
})
|
|
1184
1425
|
);
|
|
@@ -1274,11 +1515,11 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1274
1515
|
}
|
|
1275
1516
|
}
|
|
1276
1517
|
} catch (error) {
|
|
1277
|
-
|
|
1518
|
+
logger3.warn(`Could not fetch administrators for chat ${chat.id}: ${error}`);
|
|
1278
1519
|
}
|
|
1279
1520
|
}
|
|
1280
1521
|
} catch (error) {
|
|
1281
|
-
|
|
1522
|
+
logger3.error(
|
|
1282
1523
|
`Error building standardized entities: ${error instanceof Error ? error.message : String(error)}`
|
|
1283
1524
|
);
|
|
1284
1525
|
}
|
|
@@ -1330,7 +1571,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1330
1571
|
};
|
|
1331
1572
|
return room;
|
|
1332
1573
|
} catch (error) {
|
|
1333
|
-
|
|
1574
|
+
logger3.error(
|
|
1334
1575
|
`Error building forum topic room: ${error instanceof Error ? error.message : String(error)}`
|
|
1335
1576
|
);
|
|
1336
1577
|
return null;
|
|
@@ -1342,14 +1583,14 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1342
1583
|
"telegram",
|
|
1343
1584
|
serviceInstance.handleSendMessage.bind(serviceInstance)
|
|
1344
1585
|
);
|
|
1345
|
-
|
|
1586
|
+
logger3.info("[Telegram] Registered send handler.");
|
|
1346
1587
|
} else {
|
|
1347
|
-
|
|
1588
|
+
logger3.warn("[Telegram] Cannot register send handler - bot not initialized.");
|
|
1348
1589
|
}
|
|
1349
1590
|
}
|
|
1350
1591
|
async handleSendMessage(runtime, target, content) {
|
|
1351
1592
|
if (!this.bot || !this.messageManager) {
|
|
1352
|
-
|
|
1593
|
+
logger3.error("[Telegram SendHandler] Bot not initialized - cannot send messages.");
|
|
1353
1594
|
throw new Error("Telegram bot is not initialized. Please provide TELEGRAM_BOT_TOKEN.");
|
|
1354
1595
|
}
|
|
1355
1596
|
let chatId;
|
|
@@ -1361,7 +1602,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1361
1602
|
if (!chatId)
|
|
1362
1603
|
throw new Error(`Could not resolve Telegram chat ID from roomId ${target.roomId}`);
|
|
1363
1604
|
} else if (target.entityId) {
|
|
1364
|
-
|
|
1605
|
+
logger3.error("[Telegram SendHandler] Sending DMs via entityId not implemented yet.");
|
|
1365
1606
|
throw new Error("Sending DMs via entityId is not yet supported for Telegram.");
|
|
1366
1607
|
} else {
|
|
1367
1608
|
throw new Error("Telegram SendHandler requires channelId, roomId, or entityId.");
|
|
@@ -1373,9 +1614,9 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1373
1614
|
}
|
|
1374
1615
|
try {
|
|
1375
1616
|
await this.messageManager.sendMessage(chatId, content);
|
|
1376
|
-
|
|
1617
|
+
logger3.info(`[Telegram SendHandler] Message sent to chat ID: ${chatId}`);
|
|
1377
1618
|
} catch (error) {
|
|
1378
|
-
|
|
1619
|
+
logger3.error(
|
|
1379
1620
|
{
|
|
1380
1621
|
target,
|
|
1381
1622
|
content
|
|
@@ -1388,7 +1629,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1388
1629
|
};
|
|
1389
1630
|
|
|
1390
1631
|
// src/tests.ts
|
|
1391
|
-
import { logger as
|
|
1632
|
+
import { logger as logger4 } from "@elizaos/core";
|
|
1392
1633
|
var TEST_IMAGE_URL = "https://github.com/elizaOS/awesome-eliza/blob/main/assets/eliza-logo.jpg?raw=true";
|
|
1393
1634
|
var TelegramTestSuite = class {
|
|
1394
1635
|
name = "telegram";
|
|
@@ -1457,7 +1698,7 @@ var TelegramTestSuite = class {
|
|
|
1457
1698
|
throw new Error("Bot is not initialized.");
|
|
1458
1699
|
}
|
|
1459
1700
|
const chat = await this.bot.telegram.getChat(chatId);
|
|
1460
|
-
|
|
1701
|
+
logger4.log(`Fetched real chat: ${JSON.stringify(chat)}`);
|
|
1461
1702
|
return chat;
|
|
1462
1703
|
} catch (error) {
|
|
1463
1704
|
throw new Error(`Error fetching real Telegram chat: ${error}`);
|
|
@@ -1472,14 +1713,14 @@ var TelegramTestSuite = class {
|
|
|
1472
1713
|
}
|
|
1473
1714
|
this.bot = this.telegramClient.messageManager.bot;
|
|
1474
1715
|
this.messageManager = this.telegramClient.messageManager;
|
|
1475
|
-
|
|
1716
|
+
logger4.debug("Telegram bot initialized successfully.");
|
|
1476
1717
|
}
|
|
1477
1718
|
async testSendingTextMessage(runtime) {
|
|
1478
1719
|
try {
|
|
1479
1720
|
if (!this.bot) throw new Error("Bot not initialized.");
|
|
1480
1721
|
const chatId = this.validateChatId(runtime);
|
|
1481
1722
|
await this.bot.telegram.sendMessage(chatId, "Testing Telegram message!");
|
|
1482
|
-
|
|
1723
|
+
logger4.debug("Message sent successfully.");
|
|
1483
1724
|
} catch (error) {
|
|
1484
1725
|
throw new Error(`Error sending Telegram message: ${error}`);
|
|
1485
1726
|
}
|
|
@@ -1512,7 +1753,7 @@ var TelegramTestSuite = class {
|
|
|
1512
1753
|
mockContext,
|
|
1513
1754
|
messageContent
|
|
1514
1755
|
);
|
|
1515
|
-
|
|
1756
|
+
logger4.success("Message with image attachment sent successfully.");
|
|
1516
1757
|
} catch (error) {
|
|
1517
1758
|
throw new Error(`Error sending Telegram message with attachment: ${error}`);
|
|
1518
1759
|
}
|
|
@@ -1573,7 +1814,7 @@ var TelegramTestSuite = class {
|
|
|
1573
1814
|
throw new Error("Error processing Telegram image or description not found");
|
|
1574
1815
|
}
|
|
1575
1816
|
const { description } = result;
|
|
1576
|
-
|
|
1817
|
+
logger4.log(`Processing Telegram image successfully: ${description}`);
|
|
1577
1818
|
} catch (error) {
|
|
1578
1819
|
throw new Error(`Error processing Telegram image: ${error}`);
|
|
1579
1820
|
}
|
|
@@ -1589,7 +1830,7 @@ var TelegramTestSuite = class {
|
|
|
1589
1830
|
}
|
|
1590
1831
|
return message.photo[message.photo.length - 1].file_id;
|
|
1591
1832
|
} catch (error) {
|
|
1592
|
-
|
|
1833
|
+
logger4.error({ error }, `Error sending image: ${error}`);
|
|
1593
1834
|
throw error;
|
|
1594
1835
|
}
|
|
1595
1836
|
}
|