@elizaos/plugin-telegram 1.0.4 → 1.0.10

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/index.js CHANGED
@@ -23,27 +23,6 @@ import {
23
23
  } from "@elizaos/core";
24
24
  import { Telegraf } from "telegraf";
25
25
 
26
- // src/environment.ts
27
- import { z } from "zod";
28
- var telegramEnvSchema = z.object({
29
- TELEGRAM_BOT_TOKEN: z.string().min(1, "Telegram bot token is required")
30
- });
31
- async function validateTelegramConfig(runtime) {
32
- try {
33
- const config = {
34
- TELEGRAM_BOT_TOKEN: runtime.getSetting("TELEGRAM_BOT_TOKEN") || process.env.TELEGRAM_BOT_TOKEN
35
- };
36
- return telegramEnvSchema.parse(config);
37
- } catch (error) {
38
- if (error instanceof z.ZodError) {
39
- const errorMessages = error.errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("\n");
40
- throw new Error(`Telegram configuration validation failed:
41
- ${errorMessages}`);
42
- }
43
- throw error;
44
- }
45
- }
46
-
47
26
  // src/messageManager.ts
48
27
  import {
49
28
  ChannelType,
@@ -87,46 +66,46 @@ function convertMarkdownToTelegram(markdown) {
87
66
  return placeholder;
88
67
  }
89
68
  let converted = markdown;
90
- converted = converted.replace(/```(\w+)?\n([\s\S]*?)```/g, (match, lang, code) => {
69
+ converted = converted.replace(/```(\w+)?\n([\s\S]*?)```/g, (_match, lang, code) => {
91
70
  const escapedCode = escapeCode(code);
92
71
  const formatted = "```" + (lang || "") + "\n" + escapedCode + "```";
93
72
  return storeReplacement(formatted);
94
73
  });
95
- converted = converted.replace(/`([^`]+)`/g, (match, code) => {
74
+ converted = converted.replace(/`([^`]+)`/g, (_match, code) => {
96
75
  const escapedCode = escapeCode(code);
97
76
  const formatted = "`" + escapedCode + "`";
98
77
  return storeReplacement(formatted);
99
78
  });
100
79
  converted = converted.replace(
101
80
  /$begin:math:display$([^$end:math:display$]+)]$begin:math:text$([^)]+)$end:math:text$/g,
102
- (match, text, url) => {
81
+ (_match, text, url) => {
103
82
  const formattedText = escapePlainText(text);
104
83
  const escapedURL = escapeUrl(url);
105
84
  const formatted = `[${formattedText}](${escapedURL})`;
106
85
  return storeReplacement(formatted);
107
86
  }
108
87
  );
109
- converted = converted.replace(/\*\*([^*]+)\*\*/g, (match, content) => {
88
+ converted = converted.replace(/\*\*([^*]+)\*\*/g, (_match, content) => {
110
89
  const formattedContent = escapePlainText(content);
111
90
  const formatted = `*${formattedContent}*`;
112
91
  return storeReplacement(formatted);
113
92
  });
114
- converted = converted.replace(/~~([^~]+)~~/g, (match, content) => {
93
+ converted = converted.replace(/~~([^~]+)~~/g, (_match, content) => {
115
94
  const formattedContent = escapePlainText(content);
116
95
  const formatted = `~${formattedContent}~`;
117
96
  return storeReplacement(formatted);
118
97
  });
119
- converted = converted.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, (match, content) => {
98
+ converted = converted.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, (_match, content) => {
120
99
  const formattedContent = escapePlainText(content);
121
100
  const formatted = `_${formattedContent}_`;
122
101
  return storeReplacement(formatted);
123
102
  });
124
- converted = converted.replace(/_([^_\n]+)_/g, (match, content) => {
103
+ converted = converted.replace(/_([^_\n]+)_/g, (_match, content) => {
125
104
  const formattedContent = escapePlainText(content);
126
105
  const formatted = `_${formattedContent}_`;
127
106
  return storeReplacement(formatted);
128
107
  });
129
- converted = converted.replace(/^(#{1,6})\s*(.*)$/gm, (match, hashes, headerContent) => {
108
+ converted = converted.replace(/^(#{1,6})\s*(.*)$/gm, (_match, _hashes, headerContent) => {
130
109
  const formatted = `*${escapePlainText(headerContent.trim())}*`;
131
110
  return storeReplacement(formatted);
132
111
  });
@@ -159,7 +138,7 @@ function convertToTelegramButtons(buttons) {
159
138
  }
160
139
 
161
140
  // src/messageManager.ts
162
- import fs from "node:fs";
141
+ import fs from "fs";
163
142
  var MAX_MESSAGE_LENGTH = 4096;
164
143
  var getChannelType = (chat) => {
165
144
  switch (chat.type) {
@@ -325,9 +304,10 @@ ${description}]` };
325
304
  );
326
305
  } catch (error) {
327
306
  const errorMessage = error instanceof Error ? error.message : String(error);
328
- logger.error(`Failed to send ${type}. Path: ${mediaPath}. Error: ${errorMessage}`, {
329
- originalError: error
330
- });
307
+ logger.error(
308
+ { originalError: error },
309
+ `Failed to send ${type}. Path: ${mediaPath}. Error: ${errorMessage}`
310
+ );
331
311
  throw error;
332
312
  }
333
313
  }
@@ -384,6 +364,7 @@ ${description}]` };
384
364
  if (!fullText) return;
385
365
  const chat = message.chat;
386
366
  const channelType = getChannelType(chat);
367
+ const sourceId = createUniqueUuid(this.runtime, "" + chat.id);
387
368
  await this.runtime.ensureConnection({
388
369
  entityId,
389
370
  roomId,
@@ -405,6 +386,7 @@ ${description}]` };
405
386
  text: fullText,
406
387
  // attachments?
407
388
  source: "telegram",
389
+ // url?
408
390
  channelType,
409
391
  inReplyTo: "reply_to_message" in message && message.reply_to_message ? createUniqueUuid(this.runtime, message.reply_to_message.message_id.toString()) : void 0
410
392
  },
@@ -415,9 +397,12 @@ ${description}]` };
415
397
  // include very technical/exact reference to this user for security reasons
416
398
  // don't remove or change this, spartan needs this
417
399
  fromId: chat.id,
400
+ sourceId,
418
401
  // why message? all Memories contain content (which is basically a message)
419
- // what are the other types?
402
+ // what are the other types? see MemoryType
420
403
  type: "message"
404
+ // MemoryType.MESSAGE
405
+ // scope: `shared`, `private`, or `room`
421
406
  },
422
407
  createdAt: message.date * 1e3
423
408
  };
@@ -425,7 +410,7 @@ ${description}]` };
425
410
  try {
426
411
  if (!content.text) return [];
427
412
  let sentMessages = false;
428
- if (content?.target === "DM") {
413
+ if (content?.channelType === "DM") {
429
414
  sentMessages = [];
430
415
  if (ctx.from) {
431
416
  const res = await this.bot.telegram.sendMessage(ctx.from.id, content.text);
@@ -438,7 +423,6 @@ ${description}]` };
438
423
  const memories = [];
439
424
  for (let i = 0; i < sentMessages.length; i++) {
440
425
  const sentMessage = sentMessages[i];
441
- const _isLastMessage = i === sentMessages.length - 1;
442
426
  const responseMemory = {
443
427
  id: createUniqueUuid(this.runtime, sentMessage.message_id.toString()),
444
428
  entityId: this.runtime.agentId,
@@ -458,7 +442,7 @@ ${description}]` };
458
442
  }
459
443
  return memories;
460
444
  } catch (error) {
461
- logger.error("Error in message callback:", error);
445
+ logger.error({ error }, "Error in message callback");
462
446
  return [];
463
447
  }
464
448
  };
@@ -477,12 +461,15 @@ ${description}]` };
477
461
  originalMessage: message
478
462
  });
479
463
  } catch (error) {
480
- logger.error("Error handling Telegram message:", {
481
- error,
482
- chatId: ctx.chat?.id,
483
- messageId: ctx.message?.message_id,
484
- from: ctx.from?.username || ctx.from?.id
485
- });
464
+ logger.error(
465
+ {
466
+ error,
467
+ chatId: ctx.chat?.id,
468
+ messageId: ctx.message?.message_id,
469
+ from: ctx.from?.username || ctx.from?.id
470
+ },
471
+ "Error handling Telegram message"
472
+ );
486
473
  throw error;
487
474
  }
488
475
  }
@@ -540,7 +527,7 @@ ${description}]` };
540
527
  };
541
528
  return [responseMemory];
542
529
  } catch (error) {
543
- logger.error("Error in reaction callback:", error);
530
+ logger.error({ error }, "Error in reaction callback");
544
531
  return [];
545
532
  }
546
533
  };
@@ -568,7 +555,13 @@ ${description}]` };
568
555
  });
569
556
  } catch (error) {
570
557
  const errorMessage = error instanceof Error ? error.message : String(error);
571
- logger.error("Error handling reaction:", { error: errorMessage, originalError: error });
558
+ logger.error(
559
+ {
560
+ error: errorMessage,
561
+ originalError: error
562
+ },
563
+ "Error handling reaction"
564
+ );
572
565
  }
573
566
  }
574
567
  /**
@@ -628,10 +621,13 @@ ${description}]` };
628
621
  return sentMessages;
629
622
  } catch (error) {
630
623
  const errorMessage = error instanceof Error ? error.message : String(error);
631
- logger.error("Error sending message to Telegram:", {
632
- error: errorMessage,
633
- originalError: error
634
- });
624
+ logger.error(
625
+ {
626
+ error: errorMessage,
627
+ originalError: error
628
+ },
629
+ "Error sending message to Telegram"
630
+ );
635
631
  return [];
636
632
  }
637
633
  }
@@ -653,15 +649,29 @@ var TelegramService = class _TelegramService extends Service {
653
649
  constructor(runtime) {
654
650
  super(runtime);
655
651
  logger2.log("\u{1F4F1} Constructing new TelegramService...");
652
+ const botToken = runtime.getSetting("TELEGRAM_BOT_TOKEN");
653
+ if (!botToken || botToken.trim() === "") {
654
+ logger2.warn("Telegram Bot Token not provided - Telegram functionality will be unavailable");
655
+ this.bot = null;
656
+ this.messageManager = null;
657
+ return;
658
+ }
656
659
  this.options = {
657
660
  telegram: {
658
661
  apiRoot: runtime.getSetting("TELEGRAM_API_ROOT") || process.env.TELEGRAM_API_ROOT || "https://api.telegram.org"
659
662
  }
660
663
  };
661
- const botToken = runtime.getSetting("TELEGRAM_BOT_TOKEN");
662
- this.bot = new Telegraf(botToken, this.options);
663
- this.messageManager = new MessageManager(this.bot, this.runtime);
664
- logger2.log("\u2705 TelegramService constructor completed");
664
+ try {
665
+ this.bot = new Telegraf(botToken, this.options);
666
+ this.messageManager = new MessageManager(this.bot, this.runtime);
667
+ logger2.log("\u2705 TelegramService constructor completed");
668
+ } catch (error) {
669
+ logger2.error(
670
+ `Error initializing Telegram bot: ${error instanceof Error ? error.message : String(error)}`
671
+ );
672
+ this.bot = null;
673
+ this.messageManager = null;
674
+ }
665
675
  }
666
676
  /**
667
677
  * Starts the Telegram service for the given runtime.
@@ -670,13 +680,16 @@ var TelegramService = class _TelegramService extends Service {
670
680
  * @returns {Promise<TelegramService>} A promise that resolves with the initialized TelegramService.
671
681
  */
672
682
  static async start(runtime) {
673
- await validateTelegramConfig(runtime);
683
+ const service = new _TelegramService(runtime);
684
+ if (!service.bot) {
685
+ logger2.warn("Telegram service started without bot functionality - no bot token provided");
686
+ return service;
687
+ }
674
688
  const maxRetries = 5;
675
689
  let retryCount = 0;
676
690
  let lastError = null;
677
691
  while (retryCount < maxRetries) {
678
692
  try {
679
- const service = new _TelegramService(runtime);
680
693
  logger2.success(
681
694
  `\u2705 Telegram client successfully started for character ${runtime.character.name}`
682
695
  );
@@ -699,9 +712,10 @@ var TelegramService = class _TelegramService extends Service {
699
712
  }
700
713
  }
701
714
  }
702
- throw new Error(
703
- `Telegram initialization failed after ${maxRetries} attempts. Last error: ${lastError?.message}`
715
+ logger2.error(
716
+ `Telegram initialization failed after ${maxRetries} attempts. Last error: ${lastError?.message}. Service will continue without Telegram functionality.`
704
717
  );
718
+ return service;
705
719
  }
706
720
  /**
707
721
  * Stops the agent runtime.
@@ -719,21 +733,27 @@ var TelegramService = class _TelegramService extends Service {
719
733
  * @returns A Promise that resolves once the bot has stopped.
720
734
  */
721
735
  async stop() {
722
- this.bot.stop();
736
+ this.bot?.stop();
723
737
  }
724
738
  /**
725
739
  * Initializes the Telegram bot by launching it, getting bot info, and setting up message manager.
726
740
  * @returns {Promise<void>} A Promise that resolves when the initialization is complete.
727
741
  */
728
742
  async initializeBot() {
729
- this.bot.launch({
743
+ this.bot?.start((ctx) => {
744
+ this.runtime.emitEvent(["TELEGRAM_SLASH_START" /* SLASH_START */], {
745
+ // we don't need this
746
+ ctx
747
+ });
748
+ });
749
+ this.bot?.launch({
730
750
  dropPendingUpdates: true,
731
751
  allowedUpdates: ["message", "message_reaction"]
732
752
  });
733
753
  const botInfo = await this.bot.telegram.getMe();
734
754
  logger2.log(`Bot info: ${JSON.stringify(botInfo)}`);
735
- process.once("SIGINT", () => this.bot.stop("SIGINT"));
736
- process.once("SIGTERM", () => this.bot.stop("SIGTERM"));
755
+ process.once("SIGINT", () => this.bot?.stop("SIGINT"));
756
+ process.once("SIGTERM", () => this.bot?.stop("SIGTERM"));
737
757
  }
738
758
  /**
739
759
  * Sets up the middleware chain for preprocessing messages before they reach handlers.
@@ -751,8 +771,8 @@ var TelegramService = class _TelegramService extends Service {
751
771
  * @private
752
772
  */
753
773
  setupMiddlewares() {
754
- this.bot.use(this.authorizationMiddleware.bind(this));
755
- this.bot.use(this.chatAndEntityMiddleware.bind(this));
774
+ this.bot?.use(this.authorizationMiddleware.bind(this));
775
+ this.bot?.use(this.chatAndEntityMiddleware.bind(this));
756
776
  }
757
777
  /**
758
778
  * Authorization middleware - checks if chat is allowed to interact with the bot
@@ -805,7 +825,7 @@ var TelegramService = class _TelegramService extends Service {
805
825
  try {
806
826
  await this.handleForumTopic(ctx);
807
827
  } catch (error) {
808
- logger2.error(`Error handling forum topic: ${error}`);
828
+ logger2.error({ error }, `Error handling forum topic: ${error}`);
809
829
  }
810
830
  }
811
831
  if (ctx.from && ctx.chat.type !== "private") {
@@ -819,18 +839,18 @@ var TelegramService = class _TelegramService extends Service {
819
839
  * @private
820
840
  */
821
841
  setupMessageHandlers() {
822
- this.bot.on("message", async (ctx) => {
842
+ this.bot?.on("message", async (ctx) => {
823
843
  try {
824
844
  await this.messageManager.handleMessage(ctx);
825
845
  } catch (error) {
826
- logger2.error("Error handling message:", error);
846
+ logger2.error({ error }, "Error handling message");
827
847
  }
828
848
  });
829
- this.bot.on("message_reaction", async (ctx) => {
849
+ this.bot?.on("message_reaction", async (ctx) => {
830
850
  try {
831
851
  await this.messageManager.handleReaction(ctx);
832
852
  } catch (error) {
833
- logger2.error("Error handling reaction:", error);
853
+ logger2.error({ error }, "Error handling reaction");
834
854
  }
835
855
  });
836
856
  }
@@ -850,7 +870,7 @@ var TelegramService = class _TelegramService extends Service {
850
870
  const allowedChatsList = JSON.parse(allowedChats);
851
871
  return allowedChatsList.includes(chatId);
852
872
  } catch (error) {
853
- logger2.error("Error parsing TELEGRAM_ALLOWED_CHATS:", error);
873
+ logger2.error({ error }, "Error parsing TELEGRAM_ALLOWED_CHATS");
854
874
  return false;
855
875
  }
856
876
  }
@@ -1105,7 +1125,7 @@ var TelegramService = class _TelegramService extends Service {
1105
1125
  entities,
1106
1126
  source: "telegram",
1107
1127
  chat,
1108
- botUsername: this.bot.botInfo.username
1128
+ botUsername: this.bot?.botInfo?.username
1109
1129
  };
1110
1130
  if (chat.type !== "private") {
1111
1131
  await this.runtime.emitEvent("TELEGRAM_WORLD_JOINED" /* WORLD_JOINED */, telegramWorldPayload);
@@ -1230,7 +1250,7 @@ var TelegramService = class _TelegramService extends Service {
1230
1250
  this.syncedEntityIds.add(userId);
1231
1251
  } else if (chat.type === "group" || chat.type === "supergroup") {
1232
1252
  try {
1233
- const admins = await this.bot.telegram.getChatAdministrators(chat.id);
1253
+ const admins = await this.bot?.telegram.getChatAdministrators(chat.id);
1234
1254
  if (admins && admins.length > 0) {
1235
1255
  for (const admin of admins) {
1236
1256
  const userId = createUniqueUuid2(this.runtime, admin.user.id.toString());
@@ -1317,15 +1337,21 @@ var TelegramService = class _TelegramService extends Service {
1317
1337
  }
1318
1338
  }
1319
1339
  static registerSendHandlers(runtime, serviceInstance) {
1320
- if (serviceInstance) {
1340
+ if (serviceInstance && serviceInstance.bot) {
1321
1341
  runtime.registerSendHandler(
1322
1342
  "telegram",
1323
1343
  serviceInstance.handleSendMessage.bind(serviceInstance)
1324
1344
  );
1325
1345
  logger2.info("[Telegram] Registered send handler.");
1346
+ } else {
1347
+ logger2.warn("[Telegram] Cannot register send handler - bot not initialized.");
1326
1348
  }
1327
1349
  }
1328
1350
  async handleSendMessage(runtime, target, content) {
1351
+ if (!this.bot || !this.messageManager) {
1352
+ logger2.error("[Telegram SendHandler] Bot not initialized - cannot send messages.");
1353
+ throw new Error("Telegram bot is not initialized. Please provide TELEGRAM_BOT_TOKEN.");
1354
+ }
1329
1355
  let chatId;
1330
1356
  if (target.channelId) {
1331
1357
  chatId = target.channelId;
@@ -1350,11 +1376,11 @@ var TelegramService = class _TelegramService extends Service {
1350
1376
  logger2.info(`[Telegram SendHandler] Message sent to chat ID: ${chatId}`);
1351
1377
  } catch (error) {
1352
1378
  logger2.error(
1353
- `[Telegram SendHandler] Error sending message: ${error instanceof Error ? error.message : String(error)}`,
1354
1379
  {
1355
1380
  target,
1356
1381
  content
1357
- }
1382
+ },
1383
+ `[Telegram SendHandler] Error sending message: ${error instanceof Error ? error.message : String(error)}`
1358
1384
  );
1359
1385
  throw error;
1360
1386
  }
@@ -1439,6 +1465,11 @@ var TelegramTestSuite = class {
1439
1465
  }
1440
1466
  async testCreatingTelegramBot(runtime) {
1441
1467
  this.telegramClient = runtime.getService("telegram");
1468
+ if (!this.telegramClient || !this.telegramClient.messageManager) {
1469
+ throw new Error(
1470
+ "Telegram service or message manager not initialized - check TELEGRAM_BOT_TOKEN"
1471
+ );
1472
+ }
1442
1473
  this.bot = this.telegramClient.messageManager.bot;
1443
1474
  this.messageManager = this.telegramClient.messageManager;
1444
1475
  logger3.debug("Telegram bot initialized successfully.");
@@ -1477,7 +1508,10 @@ var TelegramTestSuite = class {
1477
1508
  }
1478
1509
  ]
1479
1510
  };
1480
- await this.messageManager.sendMessageInChunks(mockContext, messageContent);
1511
+ await this.messageManager.sendMessageInChunks(
1512
+ mockContext,
1513
+ messageContent
1514
+ );
1481
1515
  logger3.success("Message with image attachment sent successfully.");
1482
1516
  } catch (error) {
1483
1517
  throw new Error(`Error sending Telegram message with attachment: ${error}`);
@@ -1555,7 +1589,7 @@ var TelegramTestSuite = class {
1555
1589
  }
1556
1590
  return message.photo[message.photo.length - 1].file_id;
1557
1591
  } catch (error) {
1558
- logger3.error(`Error sending image: ${error}`);
1592
+ logger3.error({ error }, `Error sending image: ${error}`);
1559
1593
  throw error;
1560
1594
  }
1561
1595
  }