@elizaos/plugin-telegram 1.0.9 → 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 +358 -97
- package/dist/index.js.map +1 -1
- package/dist/messageManager.d.ts +46 -2
- package/dist/utils.d.ts +8 -2
- package/package.json +3 -3
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,18 +129,36 @@ 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
|
|
141
|
-
import fs from "
|
|
161
|
+
import fs from "fs";
|
|
142
162
|
var MAX_MESSAGE_LENGTH = 4096;
|
|
143
163
|
var getChannelType = (chat) => {
|
|
144
164
|
switch (chat.type) {
|
|
@@ -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,18 +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
|
-
|
|
308
|
-
originalError: error
|
|
309
|
-
|
|
556
|
+
logger2.error(
|
|
557
|
+
{ originalError: error },
|
|
558
|
+
`Failed to send ${type}. Path: ${mediaPath}. Error: ${errorMessage}`
|
|
559
|
+
);
|
|
310
560
|
throw error;
|
|
311
561
|
}
|
|
312
562
|
}
|
|
313
|
-
// Split message into smaller parts
|
|
314
563
|
/**
|
|
315
564
|
* Splits a given text into an array of strings based on the maximum message length.
|
|
316
565
|
*
|
|
@@ -333,7 +582,6 @@ ${description}]` };
|
|
|
333
582
|
if (currentChunk) chunks.push(currentChunk);
|
|
334
583
|
return chunks;
|
|
335
584
|
}
|
|
336
|
-
// Main handler for incoming messages
|
|
337
585
|
/**
|
|
338
586
|
* Handle incoming messages from Telegram and process them accordingly.
|
|
339
587
|
* @param {Context} ctx - The context object containing information about the message.
|
|
@@ -346,21 +594,23 @@ ${description}]` };
|
|
|
346
594
|
const entityId = createUniqueUuid(this.runtime, ctx.from.id.toString());
|
|
347
595
|
const threadId = "is_topic_message" in message && message.is_topic_message ? message.message_thread_id?.toString() : void 0;
|
|
348
596
|
if (!ctx.chat) {
|
|
349
|
-
|
|
597
|
+
logger2.error("handleMessage: ctx.chat is undefined");
|
|
350
598
|
return;
|
|
351
599
|
}
|
|
352
600
|
const telegramRoomid = threadId ? `${ctx.chat.id}-${threadId}` : ctx.chat.id.toString();
|
|
353
601
|
const roomId = createUniqueUuid(this.runtime, telegramRoomid);
|
|
354
602
|
const messageId = createUniqueUuid(this.runtime, message?.message_id?.toString());
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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;
|
|
361
613
|
}
|
|
362
|
-
const fullText = imageInfo ? `${messageText} ${imageInfo.description}` : messageText;
|
|
363
|
-
if (!fullText) return;
|
|
364
614
|
const chat = message.chat;
|
|
365
615
|
const channelType = getChannelType(chat);
|
|
366
616
|
const sourceId = createUniqueUuid(this.runtime, "" + chat.id);
|
|
@@ -382,10 +632,9 @@ ${description}]` };
|
|
|
382
632
|
agentId: this.runtime.agentId,
|
|
383
633
|
roomId,
|
|
384
634
|
content: {
|
|
385
|
-
text:
|
|
386
|
-
|
|
635
|
+
text: cleanedContent || " ",
|
|
636
|
+
attachments: cleanedAttachments,
|
|
387
637
|
source: "telegram",
|
|
388
|
-
// url?
|
|
389
638
|
channelType,
|
|
390
639
|
inReplyTo: "reply_to_message" in message && message.reply_to_message ? createUniqueUuid(this.runtime, message.reply_to_message.message_id.toString()) : void 0
|
|
391
640
|
},
|
|
@@ -441,31 +690,27 @@ ${description}]` };
|
|
|
441
690
|
}
|
|
442
691
|
return memories;
|
|
443
692
|
} catch (error) {
|
|
444
|
-
|
|
693
|
+
logger2.error({ error }, "Error in message callback");
|
|
445
694
|
return [];
|
|
446
695
|
}
|
|
447
696
|
};
|
|
448
|
-
this.runtime.
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
}
|
|
454
|
-
this.runtime.
|
|
455
|
-
runtime: this.runtime,
|
|
456
|
-
message: memory,
|
|
457
|
-
callback,
|
|
458
|
-
source: "telegram",
|
|
459
|
-
ctx,
|
|
460
|
-
originalMessage: message
|
|
461
|
-
});
|
|
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);
|
|
462
704
|
} catch (error) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
705
|
+
logger2.error(
|
|
706
|
+
{
|
|
707
|
+
error,
|
|
708
|
+
chatId: ctx.chat?.id,
|
|
709
|
+
messageId: ctx.message?.message_id,
|
|
710
|
+
from: ctx.from?.username || ctx.from?.id
|
|
711
|
+
},
|
|
712
|
+
"Error handling Telegram message"
|
|
713
|
+
);
|
|
469
714
|
throw error;
|
|
470
715
|
}
|
|
471
716
|
}
|
|
@@ -523,7 +768,7 @@ ${description}]` };
|
|
|
523
768
|
};
|
|
524
769
|
return [responseMemory];
|
|
525
770
|
} catch (error) {
|
|
526
|
-
|
|
771
|
+
logger2.error({ error }, "Error in reaction callback");
|
|
527
772
|
return [];
|
|
528
773
|
}
|
|
529
774
|
};
|
|
@@ -551,7 +796,13 @@ ${description}]` };
|
|
|
551
796
|
});
|
|
552
797
|
} catch (error) {
|
|
553
798
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
554
|
-
|
|
799
|
+
logger2.error(
|
|
800
|
+
{
|
|
801
|
+
error: errorMessage,
|
|
802
|
+
originalError: error
|
|
803
|
+
},
|
|
804
|
+
"Error handling reaction"
|
|
805
|
+
);
|
|
555
806
|
}
|
|
556
807
|
}
|
|
557
808
|
/**
|
|
@@ -611,10 +862,13 @@ ${description}]` };
|
|
|
611
862
|
return sentMessages;
|
|
612
863
|
} catch (error) {
|
|
613
864
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
865
|
+
logger2.error(
|
|
866
|
+
{
|
|
867
|
+
error: errorMessage,
|
|
868
|
+
originalError: error
|
|
869
|
+
},
|
|
870
|
+
"Error sending message to Telegram"
|
|
871
|
+
);
|
|
618
872
|
return [];
|
|
619
873
|
}
|
|
620
874
|
}
|
|
@@ -635,10 +889,10 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
635
889
|
*/
|
|
636
890
|
constructor(runtime) {
|
|
637
891
|
super(runtime);
|
|
638
|
-
|
|
892
|
+
logger3.log("\u{1F4F1} Constructing new TelegramService...");
|
|
639
893
|
const botToken = runtime.getSetting("TELEGRAM_BOT_TOKEN");
|
|
640
894
|
if (!botToken || botToken.trim() === "") {
|
|
641
|
-
|
|
895
|
+
logger3.warn("Telegram Bot Token not provided - Telegram functionality will be unavailable");
|
|
642
896
|
this.bot = null;
|
|
643
897
|
this.messageManager = null;
|
|
644
898
|
return;
|
|
@@ -651,9 +905,11 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
651
905
|
try {
|
|
652
906
|
this.bot = new Telegraf(botToken, this.options);
|
|
653
907
|
this.messageManager = new MessageManager(this.bot, this.runtime);
|
|
654
|
-
|
|
908
|
+
logger3.log("\u2705 TelegramService constructor completed");
|
|
655
909
|
} catch (error) {
|
|
656
|
-
|
|
910
|
+
logger3.error(
|
|
911
|
+
`Error initializing Telegram bot: ${error instanceof Error ? error.message : String(error)}`
|
|
912
|
+
);
|
|
657
913
|
this.bot = null;
|
|
658
914
|
this.messageManager = null;
|
|
659
915
|
}
|
|
@@ -667,7 +923,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
667
923
|
static async start(runtime) {
|
|
668
924
|
const service = new _TelegramService(runtime);
|
|
669
925
|
if (!service.bot) {
|
|
670
|
-
|
|
926
|
+
logger3.warn("Telegram service started without bot functionality - no bot token provided");
|
|
671
927
|
return service;
|
|
672
928
|
}
|
|
673
929
|
const maxRetries = 5;
|
|
@@ -675,10 +931,10 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
675
931
|
let lastError = null;
|
|
676
932
|
while (retryCount < maxRetries) {
|
|
677
933
|
try {
|
|
678
|
-
|
|
934
|
+
logger3.success(
|
|
679
935
|
`\u2705 Telegram client successfully started for character ${runtime.character.name}`
|
|
680
936
|
);
|
|
681
|
-
|
|
937
|
+
logger3.log("\u{1F680} Starting Telegram bot...");
|
|
682
938
|
await service.initializeBot();
|
|
683
939
|
service.setupMiddlewares();
|
|
684
940
|
service.setupMessageHandlers();
|
|
@@ -686,18 +942,18 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
686
942
|
return service;
|
|
687
943
|
} catch (error) {
|
|
688
944
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
689
|
-
|
|
945
|
+
logger3.error(
|
|
690
946
|
`Telegram initialization attempt ${retryCount + 1} failed: ${lastError.message}`
|
|
691
947
|
);
|
|
692
948
|
retryCount++;
|
|
693
949
|
if (retryCount < maxRetries) {
|
|
694
950
|
const delay = 2 ** retryCount * 1e3;
|
|
695
|
-
|
|
951
|
+
logger3.info(`Retrying Telegram initialization in ${delay / 1e3} seconds...`);
|
|
696
952
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
697
953
|
}
|
|
698
954
|
}
|
|
699
955
|
}
|
|
700
|
-
|
|
956
|
+
logger3.error(
|
|
701
957
|
`Telegram initialization failed after ${maxRetries} attempts. Last error: ${lastError?.message}. Service will continue without Telegram functionality.`
|
|
702
958
|
);
|
|
703
959
|
return service;
|
|
@@ -736,7 +992,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
736
992
|
allowedUpdates: ["message", "message_reaction"]
|
|
737
993
|
});
|
|
738
994
|
const botInfo = await this.bot.telegram.getMe();
|
|
739
|
-
|
|
995
|
+
logger3.log(`Bot info: ${JSON.stringify(botInfo)}`);
|
|
740
996
|
process.once("SIGINT", () => this.bot?.stop("SIGINT"));
|
|
741
997
|
process.once("SIGTERM", () => this.bot?.stop("SIGTERM"));
|
|
742
998
|
}
|
|
@@ -770,7 +1026,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
770
1026
|
*/
|
|
771
1027
|
async authorizationMiddleware(ctx, next) {
|
|
772
1028
|
if (!await this.isGroupAuthorized(ctx)) {
|
|
773
|
-
|
|
1029
|
+
logger3.debug("Chat not authorized, skipping message processing");
|
|
774
1030
|
return;
|
|
775
1031
|
}
|
|
776
1032
|
await next();
|
|
@@ -810,7 +1066,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
810
1066
|
try {
|
|
811
1067
|
await this.handleForumTopic(ctx);
|
|
812
1068
|
} catch (error) {
|
|
813
|
-
|
|
1069
|
+
logger3.error({ error }, `Error handling forum topic: ${error}`);
|
|
814
1070
|
}
|
|
815
1071
|
}
|
|
816
1072
|
if (ctx.from && ctx.chat.type !== "private") {
|
|
@@ -828,14 +1084,14 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
828
1084
|
try {
|
|
829
1085
|
await this.messageManager.handleMessage(ctx);
|
|
830
1086
|
} catch (error) {
|
|
831
|
-
|
|
1087
|
+
logger3.error({ error }, "Error handling message");
|
|
832
1088
|
}
|
|
833
1089
|
});
|
|
834
1090
|
this.bot?.on("message_reaction", async (ctx) => {
|
|
835
1091
|
try {
|
|
836
1092
|
await this.messageManager.handleReaction(ctx);
|
|
837
1093
|
} catch (error) {
|
|
838
|
-
|
|
1094
|
+
logger3.error({ error }, "Error handling reaction");
|
|
839
1095
|
}
|
|
840
1096
|
});
|
|
841
1097
|
}
|
|
@@ -855,7 +1111,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
855
1111
|
const allowedChatsList = JSON.parse(allowedChats);
|
|
856
1112
|
return allowedChatsList.includes(chatId);
|
|
857
1113
|
} catch (error) {
|
|
858
|
-
|
|
1114
|
+
logger3.error({ error }, "Error parsing TELEGRAM_ALLOWED_CHATS");
|
|
859
1115
|
return false;
|
|
860
1116
|
}
|
|
861
1117
|
}
|
|
@@ -1044,7 +1300,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1044
1300
|
);
|
|
1045
1301
|
owner = foundOwner || null;
|
|
1046
1302
|
} catch (error) {
|
|
1047
|
-
|
|
1303
|
+
logger3.warn(
|
|
1048
1304
|
`Could not get chat administrators: ${error instanceof Error ? error.message : String(error)}`
|
|
1049
1305
|
);
|
|
1050
1306
|
}
|
|
@@ -1157,13 +1413,13 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1157
1413
|
worldId
|
|
1158
1414
|
});
|
|
1159
1415
|
} else {
|
|
1160
|
-
|
|
1416
|
+
logger3.warn(
|
|
1161
1417
|
`Skipping entity sync due to missing ID: ${JSON.stringify(entity.names)}`
|
|
1162
1418
|
);
|
|
1163
1419
|
}
|
|
1164
1420
|
} catch (err) {
|
|
1165
1421
|
const telegramMetadata = entity.metadata?.telegram;
|
|
1166
|
-
|
|
1422
|
+
logger3.warn(`Failed to sync user ${telegramMetadata?.username}: ${err}`);
|
|
1167
1423
|
}
|
|
1168
1424
|
})
|
|
1169
1425
|
);
|
|
@@ -1259,11 +1515,11 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1259
1515
|
}
|
|
1260
1516
|
}
|
|
1261
1517
|
} catch (error) {
|
|
1262
|
-
|
|
1518
|
+
logger3.warn(`Could not fetch administrators for chat ${chat.id}: ${error}`);
|
|
1263
1519
|
}
|
|
1264
1520
|
}
|
|
1265
1521
|
} catch (error) {
|
|
1266
|
-
|
|
1522
|
+
logger3.error(
|
|
1267
1523
|
`Error building standardized entities: ${error instanceof Error ? error.message : String(error)}`
|
|
1268
1524
|
);
|
|
1269
1525
|
}
|
|
@@ -1315,7 +1571,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1315
1571
|
};
|
|
1316
1572
|
return room;
|
|
1317
1573
|
} catch (error) {
|
|
1318
|
-
|
|
1574
|
+
logger3.error(
|
|
1319
1575
|
`Error building forum topic room: ${error instanceof Error ? error.message : String(error)}`
|
|
1320
1576
|
);
|
|
1321
1577
|
return null;
|
|
@@ -1327,14 +1583,14 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1327
1583
|
"telegram",
|
|
1328
1584
|
serviceInstance.handleSendMessage.bind(serviceInstance)
|
|
1329
1585
|
);
|
|
1330
|
-
|
|
1586
|
+
logger3.info("[Telegram] Registered send handler.");
|
|
1331
1587
|
} else {
|
|
1332
|
-
|
|
1588
|
+
logger3.warn("[Telegram] Cannot register send handler - bot not initialized.");
|
|
1333
1589
|
}
|
|
1334
1590
|
}
|
|
1335
1591
|
async handleSendMessage(runtime, target, content) {
|
|
1336
1592
|
if (!this.bot || !this.messageManager) {
|
|
1337
|
-
|
|
1593
|
+
logger3.error("[Telegram SendHandler] Bot not initialized - cannot send messages.");
|
|
1338
1594
|
throw new Error("Telegram bot is not initialized. Please provide TELEGRAM_BOT_TOKEN.");
|
|
1339
1595
|
}
|
|
1340
1596
|
let chatId;
|
|
@@ -1346,7 +1602,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1346
1602
|
if (!chatId)
|
|
1347
1603
|
throw new Error(`Could not resolve Telegram chat ID from roomId ${target.roomId}`);
|
|
1348
1604
|
} else if (target.entityId) {
|
|
1349
|
-
|
|
1605
|
+
logger3.error("[Telegram SendHandler] Sending DMs via entityId not implemented yet.");
|
|
1350
1606
|
throw new Error("Sending DMs via entityId is not yet supported for Telegram.");
|
|
1351
1607
|
} else {
|
|
1352
1608
|
throw new Error("Telegram SendHandler requires channelId, roomId, or entityId.");
|
|
@@ -1358,14 +1614,14 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1358
1614
|
}
|
|
1359
1615
|
try {
|
|
1360
1616
|
await this.messageManager.sendMessage(chatId, content);
|
|
1361
|
-
|
|
1617
|
+
logger3.info(`[Telegram SendHandler] Message sent to chat ID: ${chatId}`);
|
|
1362
1618
|
} catch (error) {
|
|
1363
|
-
|
|
1364
|
-
`[Telegram SendHandler] Error sending message: ${error instanceof Error ? error.message : String(error)}`,
|
|
1619
|
+
logger3.error(
|
|
1365
1620
|
{
|
|
1366
1621
|
target,
|
|
1367
1622
|
content
|
|
1368
|
-
}
|
|
1623
|
+
},
|
|
1624
|
+
`[Telegram SendHandler] Error sending message: ${error instanceof Error ? error.message : String(error)}`
|
|
1369
1625
|
);
|
|
1370
1626
|
throw error;
|
|
1371
1627
|
}
|
|
@@ -1373,7 +1629,7 @@ var TelegramService = class _TelegramService extends Service {
|
|
|
1373
1629
|
};
|
|
1374
1630
|
|
|
1375
1631
|
// src/tests.ts
|
|
1376
|
-
import { logger as
|
|
1632
|
+
import { logger as logger4 } from "@elizaos/core";
|
|
1377
1633
|
var TEST_IMAGE_URL = "https://github.com/elizaOS/awesome-eliza/blob/main/assets/eliza-logo.jpg?raw=true";
|
|
1378
1634
|
var TelegramTestSuite = class {
|
|
1379
1635
|
name = "telegram";
|
|
@@ -1442,7 +1698,7 @@ var TelegramTestSuite = class {
|
|
|
1442
1698
|
throw new Error("Bot is not initialized.");
|
|
1443
1699
|
}
|
|
1444
1700
|
const chat = await this.bot.telegram.getChat(chatId);
|
|
1445
|
-
|
|
1701
|
+
logger4.log(`Fetched real chat: ${JSON.stringify(chat)}`);
|
|
1446
1702
|
return chat;
|
|
1447
1703
|
} catch (error) {
|
|
1448
1704
|
throw new Error(`Error fetching real Telegram chat: ${error}`);
|
|
@@ -1451,18 +1707,20 @@ var TelegramTestSuite = class {
|
|
|
1451
1707
|
async testCreatingTelegramBot(runtime) {
|
|
1452
1708
|
this.telegramClient = runtime.getService("telegram");
|
|
1453
1709
|
if (!this.telegramClient || !this.telegramClient.messageManager) {
|
|
1454
|
-
throw new Error(
|
|
1710
|
+
throw new Error(
|
|
1711
|
+
"Telegram service or message manager not initialized - check TELEGRAM_BOT_TOKEN"
|
|
1712
|
+
);
|
|
1455
1713
|
}
|
|
1456
1714
|
this.bot = this.telegramClient.messageManager.bot;
|
|
1457
1715
|
this.messageManager = this.telegramClient.messageManager;
|
|
1458
|
-
|
|
1716
|
+
logger4.debug("Telegram bot initialized successfully.");
|
|
1459
1717
|
}
|
|
1460
1718
|
async testSendingTextMessage(runtime) {
|
|
1461
1719
|
try {
|
|
1462
1720
|
if (!this.bot) throw new Error("Bot not initialized.");
|
|
1463
1721
|
const chatId = this.validateChatId(runtime);
|
|
1464
1722
|
await this.bot.telegram.sendMessage(chatId, "Testing Telegram message!");
|
|
1465
|
-
|
|
1723
|
+
logger4.debug("Message sent successfully.");
|
|
1466
1724
|
} catch (error) {
|
|
1467
1725
|
throw new Error(`Error sending Telegram message: ${error}`);
|
|
1468
1726
|
}
|
|
@@ -1491,8 +1749,11 @@ var TelegramTestSuite = class {
|
|
|
1491
1749
|
}
|
|
1492
1750
|
]
|
|
1493
1751
|
};
|
|
1494
|
-
await this.messageManager.sendMessageInChunks(
|
|
1495
|
-
|
|
1752
|
+
await this.messageManager.sendMessageInChunks(
|
|
1753
|
+
mockContext,
|
|
1754
|
+
messageContent
|
|
1755
|
+
);
|
|
1756
|
+
logger4.success("Message with image attachment sent successfully.");
|
|
1496
1757
|
} catch (error) {
|
|
1497
1758
|
throw new Error(`Error sending Telegram message with attachment: ${error}`);
|
|
1498
1759
|
}
|
|
@@ -1553,7 +1814,7 @@ var TelegramTestSuite = class {
|
|
|
1553
1814
|
throw new Error("Error processing Telegram image or description not found");
|
|
1554
1815
|
}
|
|
1555
1816
|
const { description } = result;
|
|
1556
|
-
|
|
1817
|
+
logger4.log(`Processing Telegram image successfully: ${description}`);
|
|
1557
1818
|
} catch (error) {
|
|
1558
1819
|
throw new Error(`Error processing Telegram image: ${error}`);
|
|
1559
1820
|
}
|
|
@@ -1569,7 +1830,7 @@ var TelegramTestSuite = class {
|
|
|
1569
1830
|
}
|
|
1570
1831
|
return message.photo[message.photo.length - 1].file_id;
|
|
1571
1832
|
} catch (error) {
|
|
1572
|
-
|
|
1833
|
+
logger4.error({ error }, `Error sending image: ${error}`);
|
|
1573
1834
|
throw error;
|
|
1574
1835
|
}
|
|
1575
1836
|
}
|