@elizaos/plugin-telegram 2.0.0-alpha.1 → 2.0.0-alpha.3
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 +1078 -64
- package/dist/index.js.map +11 -6
- package/package.json +13 -4
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
18
18
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
19
19
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
20
20
|
|
|
21
|
-
// ../../../node_modules/
|
|
21
|
+
// ../../../node_modules/ms/index.js
|
|
22
22
|
var require_ms = __commonJS((exports, module) => {
|
|
23
23
|
var s = 1000;
|
|
24
24
|
var m = s * 60;
|
|
@@ -128,7 +128,7 @@ var require_ms = __commonJS((exports, module) => {
|
|
|
128
128
|
}
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
// ../../../node_modules/
|
|
131
|
+
// ../../../node_modules/debug/src/common.js
|
|
132
132
|
var require_common = __commonJS((exports, module) => {
|
|
133
133
|
function setup(env) {
|
|
134
134
|
createDebug.debug = createDebug;
|
|
@@ -303,7 +303,7 @@ var require_common = __commonJS((exports, module) => {
|
|
|
303
303
|
module.exports = setup;
|
|
304
304
|
});
|
|
305
305
|
|
|
306
|
-
// ../../../node_modules/
|
|
306
|
+
// ../../../node_modules/debug/src/browser.js
|
|
307
307
|
var require_browser = __commonJS((exports, module) => {
|
|
308
308
|
exports.formatArgs = formatArgs;
|
|
309
309
|
exports.save = save;
|
|
@@ -479,21 +479,19 @@ var require_supports_color = __commonJS((exports, module) => {
|
|
|
479
479
|
var tty = __require("tty");
|
|
480
480
|
var hasFlag = require_has_flag();
|
|
481
481
|
var { env } = process;
|
|
482
|
-
var
|
|
482
|
+
var forceColor;
|
|
483
483
|
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
484
|
-
|
|
484
|
+
forceColor = 0;
|
|
485
485
|
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
486
|
-
|
|
486
|
+
forceColor = 1;
|
|
487
487
|
}
|
|
488
|
-
|
|
489
|
-
if (
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
488
|
+
if ("FORCE_COLOR" in env) {
|
|
489
|
+
if (env.FORCE_COLOR === "true") {
|
|
490
|
+
forceColor = 1;
|
|
491
|
+
} else if (env.FORCE_COLOR === "false") {
|
|
492
|
+
forceColor = 0;
|
|
493
|
+
} else {
|
|
494
|
+
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
|
|
497
495
|
}
|
|
498
496
|
}
|
|
499
497
|
function translateLevel(level) {
|
|
@@ -507,22 +505,15 @@ var require_supports_color = __commonJS((exports, module) => {
|
|
|
507
505
|
has16m: level >= 3
|
|
508
506
|
};
|
|
509
507
|
}
|
|
510
|
-
function supportsColor(haveStream,
|
|
511
|
-
const noFlagForceColor = envForceColor();
|
|
512
|
-
if (noFlagForceColor !== undefined) {
|
|
513
|
-
flagForceColor = noFlagForceColor;
|
|
514
|
-
}
|
|
515
|
-
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
508
|
+
function supportsColor(haveStream, streamIsTTY) {
|
|
516
509
|
if (forceColor === 0) {
|
|
517
510
|
return 0;
|
|
518
511
|
}
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
return 2;
|
|
525
|
-
}
|
|
512
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
513
|
+
return 3;
|
|
514
|
+
}
|
|
515
|
+
if (hasFlag("color=256")) {
|
|
516
|
+
return 2;
|
|
526
517
|
}
|
|
527
518
|
if (haveStream && !streamIsTTY && forceColor === undefined) {
|
|
528
519
|
return 0;
|
|
@@ -539,7 +530,7 @@ var require_supports_color = __commonJS((exports, module) => {
|
|
|
539
530
|
return 1;
|
|
540
531
|
}
|
|
541
532
|
if ("CI" in env) {
|
|
542
|
-
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"
|
|
533
|
+
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => (sign in env)) || env.CI_NAME === "codeship") {
|
|
543
534
|
return 1;
|
|
544
535
|
}
|
|
545
536
|
return min;
|
|
@@ -551,7 +542,7 @@ var require_supports_color = __commonJS((exports, module) => {
|
|
|
551
542
|
return 3;
|
|
552
543
|
}
|
|
553
544
|
if ("TERM_PROGRAM" in env) {
|
|
554
|
-
const version =
|
|
545
|
+
const version = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
555
546
|
switch (env.TERM_PROGRAM) {
|
|
556
547
|
case "iTerm.app":
|
|
557
548
|
return version >= 3 ? 3 : 2;
|
|
@@ -570,21 +561,18 @@ var require_supports_color = __commonJS((exports, module) => {
|
|
|
570
561
|
}
|
|
571
562
|
return min;
|
|
572
563
|
}
|
|
573
|
-
function getSupportLevel(stream
|
|
574
|
-
const level = supportsColor(stream,
|
|
575
|
-
streamIsTTY: stream && stream.isTTY,
|
|
576
|
-
...options
|
|
577
|
-
});
|
|
564
|
+
function getSupportLevel(stream) {
|
|
565
|
+
const level = supportsColor(stream, stream && stream.isTTY);
|
|
578
566
|
return translateLevel(level);
|
|
579
567
|
}
|
|
580
568
|
module.exports = {
|
|
581
569
|
supportsColor: getSupportLevel,
|
|
582
|
-
stdout:
|
|
583
|
-
stderr:
|
|
570
|
+
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
|
|
571
|
+
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
|
|
584
572
|
};
|
|
585
573
|
});
|
|
586
574
|
|
|
587
|
-
// ../../../node_modules/
|
|
575
|
+
// ../../../node_modules/debug/src/node.js
|
|
588
576
|
var require_node = __commonJS((exports, module) => {
|
|
589
577
|
var tty = __require("tty");
|
|
590
578
|
var util = __require("util");
|
|
@@ -755,7 +743,7 @@ var require_node = __commonJS((exports, module) => {
|
|
|
755
743
|
};
|
|
756
744
|
});
|
|
757
745
|
|
|
758
|
-
// ../../../node_modules/
|
|
746
|
+
// ../../../node_modules/debug/src/index.js
|
|
759
747
|
var require_src = __commonJS((exports, module) => {
|
|
760
748
|
if (typeof process === "undefined" || process.type === "renderer" || false || process.__nwjs) {
|
|
761
749
|
module.exports = require_browser();
|
|
@@ -2765,7 +2753,7 @@ var require_abort_controller = __commonJS((exports, module) => {
|
|
|
2765
2753
|
});
|
|
2766
2754
|
}
|
|
2767
2755
|
|
|
2768
|
-
class
|
|
2756
|
+
class AbortController2 {
|
|
2769
2757
|
constructor() {
|
|
2770
2758
|
signals.set(this, createAbortSignal());
|
|
2771
2759
|
}
|
|
@@ -2784,21 +2772,21 @@ var require_abort_controller = __commonJS((exports, module) => {
|
|
|
2784
2772
|
}
|
|
2785
2773
|
return signal;
|
|
2786
2774
|
}
|
|
2787
|
-
Object.defineProperties(
|
|
2775
|
+
Object.defineProperties(AbortController2.prototype, {
|
|
2788
2776
|
signal: { enumerable: true },
|
|
2789
2777
|
abort: { enumerable: true }
|
|
2790
2778
|
});
|
|
2791
2779
|
if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
|
|
2792
|
-
Object.defineProperty(
|
|
2780
|
+
Object.defineProperty(AbortController2.prototype, Symbol.toStringTag, {
|
|
2793
2781
|
configurable: true,
|
|
2794
2782
|
value: "AbortController"
|
|
2795
2783
|
});
|
|
2796
2784
|
}
|
|
2797
|
-
exports.AbortController =
|
|
2785
|
+
exports.AbortController = AbortController2;
|
|
2798
2786
|
exports.AbortSignal = AbortSignal;
|
|
2799
|
-
exports.default =
|
|
2800
|
-
module.exports =
|
|
2801
|
-
module.exports.AbortController = module.exports["default"] =
|
|
2787
|
+
exports.default = AbortController2;
|
|
2788
|
+
module.exports = AbortController2;
|
|
2789
|
+
module.exports.AbortController = module.exports["default"] = AbortController2;
|
|
2802
2790
|
module.exports.AbortSignal = AbortSignal;
|
|
2803
2791
|
});
|
|
2804
2792
|
|
|
@@ -9150,12 +9138,12 @@ var require_lib3 = __commonJS((exports, module) => {
|
|
|
9150
9138
|
AbortError.prototype.name = "AbortError";
|
|
9151
9139
|
var URL$1 = Url.URL || whatwgUrl.URL;
|
|
9152
9140
|
var PassThrough$1 = Stream.PassThrough;
|
|
9153
|
-
var isDomainOrSubdomain = function
|
|
9141
|
+
var isDomainOrSubdomain = function isDomainOrSubdomain2(destination, original) {
|
|
9154
9142
|
const orig = new URL$1(original).hostname;
|
|
9155
9143
|
const dest = new URL$1(destination).hostname;
|
|
9156
9144
|
return orig === dest || orig[orig.length - dest.length - 1] === "." && orig.endsWith(dest);
|
|
9157
9145
|
};
|
|
9158
|
-
var isSameProtocol = function
|
|
9146
|
+
var isSameProtocol = function isSameProtocol2(destination, original) {
|
|
9159
9147
|
const orig = new URL$1(original).protocol;
|
|
9160
9148
|
const dest = new URL$1(destination).protocol;
|
|
9161
9149
|
return orig === dest;
|
|
@@ -9171,7 +9159,7 @@ var require_lib3 = __commonJS((exports, module) => {
|
|
|
9171
9159
|
const send = (options.protocol === "https:" ? https : http).request;
|
|
9172
9160
|
const signal = request.signal;
|
|
9173
9161
|
let response = null;
|
|
9174
|
-
const abort = function
|
|
9162
|
+
const abort = function abort2() {
|
|
9175
9163
|
let error = new AbortError("The user aborted a request.");
|
|
9176
9164
|
reject(error);
|
|
9177
9165
|
if (request.body && request.body instanceof Stream.Readable) {
|
|
@@ -9185,7 +9173,7 @@ var require_lib3 = __commonJS((exports, module) => {
|
|
|
9185
9173
|
abort();
|
|
9186
9174
|
return;
|
|
9187
9175
|
}
|
|
9188
|
-
const abortAndFinalize = function
|
|
9176
|
+
const abortAndFinalize = function abortAndFinalize2() {
|
|
9189
9177
|
abort();
|
|
9190
9178
|
finalize();
|
|
9191
9179
|
};
|
|
@@ -10866,7 +10854,7 @@ var require_buffer_alloc = __commonJS((exports, module) => {
|
|
|
10866
10854
|
var require_safe_compare = __commonJS((exports, module) => {
|
|
10867
10855
|
var crypto = __require("crypto");
|
|
10868
10856
|
var bufferAlloc = require_buffer_alloc();
|
|
10869
|
-
var safeCompare = function
|
|
10857
|
+
var safeCompare = function safeCompare2(a, b) {
|
|
10870
10858
|
var strA = String(a);
|
|
10871
10859
|
var strB = String(b);
|
|
10872
10860
|
var lenA = strA.length;
|
|
@@ -10880,7 +10868,7 @@ var require_safe_compare = __commonJS((exports, module) => {
|
|
|
10880
10868
|
}
|
|
10881
10869
|
return result === 0;
|
|
10882
10870
|
};
|
|
10883
|
-
var nativeTimingSafeEqual = function
|
|
10871
|
+
var nativeTimingSafeEqual = function nativeTimingSafeEqual2(a, b) {
|
|
10884
10872
|
var strA = String(a);
|
|
10885
10873
|
var strB = String(b);
|
|
10886
10874
|
var aLen = Buffer.byteLength(strA);
|
|
@@ -12034,6 +12022,321 @@ var sendMessageAction = {
|
|
|
12034
12022
|
]
|
|
12035
12023
|
]
|
|
12036
12024
|
};
|
|
12025
|
+
// src/actions/sendReaction.ts
|
|
12026
|
+
import { composePromptFromState, ModelType, parseJSONObjectFromText } from "@elizaos/core";
|
|
12027
|
+
|
|
12028
|
+
// src/types.ts
|
|
12029
|
+
var TelegramEventTypes;
|
|
12030
|
+
((TelegramEventTypes2) => {
|
|
12031
|
+
TelegramEventTypes2["WORLD_JOINED"] = "TELEGRAM_WORLD_JOINED";
|
|
12032
|
+
TelegramEventTypes2["WORLD_CONNECTED"] = "TELEGRAM_WORLD_CONNECTED";
|
|
12033
|
+
TelegramEventTypes2["WORLD_LEFT"] = "TELEGRAM_WORLD_LEFT";
|
|
12034
|
+
TelegramEventTypes2["ENTITY_JOINED"] = "TELEGRAM_ENTITY_JOINED";
|
|
12035
|
+
TelegramEventTypes2["ENTITY_LEFT"] = "TELEGRAM_ENTITY_LEFT";
|
|
12036
|
+
TelegramEventTypes2["ENTITY_UPDATED"] = "TELEGRAM_ENTITY_UPDATED";
|
|
12037
|
+
TelegramEventTypes2["MESSAGE_RECEIVED"] = "TELEGRAM_MESSAGE_RECEIVED";
|
|
12038
|
+
TelegramEventTypes2["MESSAGE_SENT"] = "TELEGRAM_MESSAGE_SENT";
|
|
12039
|
+
TelegramEventTypes2["REACTION_RECEIVED"] = "TELEGRAM_REACTION_RECEIVED";
|
|
12040
|
+
TelegramEventTypes2["REACTION_SENT"] = "TELEGRAM_REACTION_SENT";
|
|
12041
|
+
TelegramEventTypes2["INTERACTION_RECEIVED"] = "TELEGRAM_INTERACTION_RECEIVED";
|
|
12042
|
+
TelegramEventTypes2["SLASH_START"] = "TELEGRAM_SLASH_START";
|
|
12043
|
+
TelegramEventTypes2["BOT_STARTED"] = "TELEGRAM_BOT_STARTED";
|
|
12044
|
+
TelegramEventTypes2["BOT_STOPPED"] = "TELEGRAM_BOT_STOPPED";
|
|
12045
|
+
TelegramEventTypes2["WEBHOOK_REGISTERED"] = "TELEGRAM_WEBHOOK_REGISTERED";
|
|
12046
|
+
})(TelegramEventTypes ||= {});
|
|
12047
|
+
var TELEGRAM_REACTIONS = {
|
|
12048
|
+
THUMBS_UP: "\uD83D\uDC4D",
|
|
12049
|
+
THUMBS_DOWN: "\uD83D\uDC4E",
|
|
12050
|
+
HEART: "❤",
|
|
12051
|
+
FIRE: "\uD83D\uDD25",
|
|
12052
|
+
CELEBRATION: "\uD83C\uDF89",
|
|
12053
|
+
CRYING: "\uD83D\uDE22",
|
|
12054
|
+
THINKING: "\uD83E\uDD14",
|
|
12055
|
+
EXPLODING_HEAD: "\uD83E\uDD2F",
|
|
12056
|
+
SCREAMING: "\uD83D\uDE31",
|
|
12057
|
+
ANGRY: "\uD83E\uDD2C",
|
|
12058
|
+
SKULL: "\uD83D\uDC80",
|
|
12059
|
+
POOP: "\uD83D\uDCA9",
|
|
12060
|
+
CLOWN: "\uD83E\uDD21",
|
|
12061
|
+
QUESTION: "\uD83E\uDD28",
|
|
12062
|
+
EYES: "\uD83D\uDC40",
|
|
12063
|
+
WHALE: "\uD83D\uDC33",
|
|
12064
|
+
HEART_ON_FIRE: "❤️\uD83D\uDD25",
|
|
12065
|
+
NEW_MOON: "\uD83C\uDF1A",
|
|
12066
|
+
HOT_DOG: "\uD83C\uDF2D",
|
|
12067
|
+
HUNDRED: "\uD83D\uDCAF",
|
|
12068
|
+
TEARS_OF_JOY: "\uD83D\uDE02",
|
|
12069
|
+
LIGHTNING: "⚡",
|
|
12070
|
+
BANANA: "\uD83C\uDF4C",
|
|
12071
|
+
TROPHY: "\uD83C\uDFC6",
|
|
12072
|
+
BROKEN_HEART: "\uD83D\uDC94",
|
|
12073
|
+
FACE_WITH_RAISED_EYEBROW: "\uD83E\uDD28",
|
|
12074
|
+
NEUTRAL: "\uD83D\uDE10",
|
|
12075
|
+
STRAWBERRY: "\uD83C\uDF53",
|
|
12076
|
+
CHAMPAGNE: "\uD83C\uDF7E",
|
|
12077
|
+
KISS: "\uD83D\uDC8B",
|
|
12078
|
+
MIDDLE_FINGER: "\uD83D\uDD95",
|
|
12079
|
+
DEVIL: "\uD83D\uDE08",
|
|
12080
|
+
SLEEPING: "\uD83D\uDE34",
|
|
12081
|
+
LOUDLY_CRYING: "\uD83D\uDE2D",
|
|
12082
|
+
NERD: "\uD83E\uDD13",
|
|
12083
|
+
GHOST: "\uD83D\uDC7B",
|
|
12084
|
+
TECHNOLOGIST: "\uD83D\uDC68\uD83D\uDCBB",
|
|
12085
|
+
UNICORN: "\uD83E\uDD84"
|
|
12086
|
+
};
|
|
12087
|
+
|
|
12088
|
+
// src/actions/sendReaction.ts
|
|
12089
|
+
var SEND_REACTION_ACTION = "SEND_TELEGRAM_REACTION";
|
|
12090
|
+
var REACTION_EXTRACTION_TEMPLATE = `
|
|
12091
|
+
You are extracting reaction parameters from a conversation.
|
|
12092
|
+
|
|
12093
|
+
The user wants to react to a Telegram message. Extract the following:
|
|
12094
|
+
1. reaction: The emoji to use as a reaction (must be a valid Telegram reaction emoji)
|
|
12095
|
+
2. messageId: The message ID to react to (if specified, otherwise use the current message)
|
|
12096
|
+
3. isBig: Whether to use a big/animated reaction (default: false)
|
|
12097
|
+
|
|
12098
|
+
Valid Telegram reaction emojis include:
|
|
12099
|
+
\uD83D\uDC4D \uD83D\uDC4E ❤ \uD83D\uDD25 \uD83C\uDF89 \uD83D\uDE22 \uD83E\uDD14 \uD83E\uDD2F \uD83D\uDE31 \uD83E\uDD2C \uD83D\uDC80 \uD83D\uDCA9 \uD83E\uDD21 \uD83E\uDD28 \uD83D\uDC40 \uD83D\uDC33 ❤️\uD83D\uDD25 \uD83C\uDF1A \uD83C\uDF2D \uD83D\uDCAF \uD83D\uDE02 ⚡ \uD83C\uDF4C \uD83C\uDFC6 \uD83D\uDC94 \uD83D\uDE10 \uD83C\uDF53 \uD83C\uDF7E \uD83D\uDC8B \uD83D\uDD95 \uD83D\uDE08 \uD83D\uDE34 \uD83D\uDE2D \uD83E\uDD13 \uD83D\uDC7B \uD83D\uDC68\uD83D\uDCBB \uD83E\uDD84
|
|
12100
|
+
|
|
12101
|
+
{{recentMessages}}
|
|
12102
|
+
|
|
12103
|
+
Based on the conversation, extract the reaction parameters.
|
|
12104
|
+
If the user mentions "thumbs up", "like", or similar, use \uD83D\uDC4D.
|
|
12105
|
+
If the user mentions "heart", "love", use ❤.
|
|
12106
|
+
If the user mentions "fire", "lit", use \uD83D\uDD25.
|
|
12107
|
+
If the user doesn't specify a message, react to their current message.
|
|
12108
|
+
|
|
12109
|
+
Respond with a JSON object:
|
|
12110
|
+
{
|
|
12111
|
+
"reaction": "emoji here",
|
|
12112
|
+
"messageId": number or null,
|
|
12113
|
+
"isBig": boolean
|
|
12114
|
+
}
|
|
12115
|
+
`;
|
|
12116
|
+
var sendReactionAction = {
|
|
12117
|
+
name: SEND_REACTION_ACTION,
|
|
12118
|
+
similes: [
|
|
12119
|
+
"TELEGRAM_REACT",
|
|
12120
|
+
"TELEGRAM_REACTION",
|
|
12121
|
+
"REACT_TO_MESSAGE",
|
|
12122
|
+
"ADD_REACTION",
|
|
12123
|
+
"SEND_EMOJI",
|
|
12124
|
+
"TELEGRAM_EMOJI"
|
|
12125
|
+
],
|
|
12126
|
+
description: "Send a reaction emoji to a Telegram message",
|
|
12127
|
+
validate: async (_runtime, message) => {
|
|
12128
|
+
const source = message.content?.source;
|
|
12129
|
+
return source === "telegram";
|
|
12130
|
+
},
|
|
12131
|
+
handler: async (runtime, message, state, _options, callback) => {
|
|
12132
|
+
const telegramService = runtime.getService(TELEGRAM_SERVICE_NAME);
|
|
12133
|
+
if (!telegramService) {
|
|
12134
|
+
if (callback) {
|
|
12135
|
+
await callback({
|
|
12136
|
+
text: "Telegram service not available"
|
|
12137
|
+
});
|
|
12138
|
+
}
|
|
12139
|
+
return { success: false, error: "Telegram service not initialized" };
|
|
12140
|
+
}
|
|
12141
|
+
const chatId = message.content?.chatId;
|
|
12142
|
+
if (!chatId) {
|
|
12143
|
+
if (callback) {
|
|
12144
|
+
await callback({
|
|
12145
|
+
text: "No chat ID available"
|
|
12146
|
+
});
|
|
12147
|
+
}
|
|
12148
|
+
return { success: false, error: "Missing chat ID" };
|
|
12149
|
+
}
|
|
12150
|
+
const currentState = state ?? await runtime.composeState(message);
|
|
12151
|
+
const prompt = composePromptFromState({
|
|
12152
|
+
state: currentState,
|
|
12153
|
+
template: REACTION_EXTRACTION_TEMPLATE
|
|
12154
|
+
});
|
|
12155
|
+
let params;
|
|
12156
|
+
try {
|
|
12157
|
+
const response = await runtime.useModel(ModelType.TEXT_SMALL, {
|
|
12158
|
+
prompt
|
|
12159
|
+
});
|
|
12160
|
+
const parsed = parseJSONObjectFromText(response);
|
|
12161
|
+
if (!parsed || !parsed.reaction) {
|
|
12162
|
+
params = {
|
|
12163
|
+
reaction: TELEGRAM_REACTIONS.THUMBS_UP,
|
|
12164
|
+
isBig: false
|
|
12165
|
+
};
|
|
12166
|
+
} else {
|
|
12167
|
+
params = parsed;
|
|
12168
|
+
}
|
|
12169
|
+
} catch {
|
|
12170
|
+
params = {
|
|
12171
|
+
reaction: TELEGRAM_REACTIONS.THUMBS_UP,
|
|
12172
|
+
isBig: false
|
|
12173
|
+
};
|
|
12174
|
+
}
|
|
12175
|
+
const targetMessageId = params.messageId ?? message.content?.messageId;
|
|
12176
|
+
if (!targetMessageId) {
|
|
12177
|
+
if (callback) {
|
|
12178
|
+
await callback({
|
|
12179
|
+
text: "No message ID available to react to"
|
|
12180
|
+
});
|
|
12181
|
+
}
|
|
12182
|
+
return { success: false, error: "Missing message ID" };
|
|
12183
|
+
}
|
|
12184
|
+
const result = await telegramService.sendReaction({
|
|
12185
|
+
chatId,
|
|
12186
|
+
messageId: targetMessageId,
|
|
12187
|
+
reaction: params.reaction,
|
|
12188
|
+
isBig: params.isBig
|
|
12189
|
+
});
|
|
12190
|
+
if (result.success) {
|
|
12191
|
+
if (callback) {
|
|
12192
|
+
await callback({
|
|
12193
|
+
text: `Reacted with ${params.reaction}`,
|
|
12194
|
+
action: SEND_REACTION_ACTION
|
|
12195
|
+
});
|
|
12196
|
+
}
|
|
12197
|
+
return {
|
|
12198
|
+
success: true,
|
|
12199
|
+
data: {
|
|
12200
|
+
action: SEND_REACTION_ACTION,
|
|
12201
|
+
chatId,
|
|
12202
|
+
messageId: targetMessageId,
|
|
12203
|
+
reaction: params.reaction
|
|
12204
|
+
}
|
|
12205
|
+
};
|
|
12206
|
+
} else {
|
|
12207
|
+
if (callback) {
|
|
12208
|
+
await callback({
|
|
12209
|
+
text: `Failed to send reaction: ${result.error}`
|
|
12210
|
+
});
|
|
12211
|
+
}
|
|
12212
|
+
return { success: false, error: result.error };
|
|
12213
|
+
}
|
|
12214
|
+
},
|
|
12215
|
+
examples: [
|
|
12216
|
+
[
|
|
12217
|
+
{
|
|
12218
|
+
name: "{{name1}}",
|
|
12219
|
+
content: {
|
|
12220
|
+
text: "React to my message with a thumbs up"
|
|
12221
|
+
}
|
|
12222
|
+
},
|
|
12223
|
+
{
|
|
12224
|
+
name: "{{agentName}}",
|
|
12225
|
+
content: {
|
|
12226
|
+
text: "I'll add a thumbs up reaction to your message.",
|
|
12227
|
+
actions: [SEND_REACTION_ACTION]
|
|
12228
|
+
}
|
|
12229
|
+
}
|
|
12230
|
+
],
|
|
12231
|
+
[
|
|
12232
|
+
{
|
|
12233
|
+
name: "{{name1}}",
|
|
12234
|
+
content: {
|
|
12235
|
+
text: "Give that a heart reaction"
|
|
12236
|
+
}
|
|
12237
|
+
},
|
|
12238
|
+
{
|
|
12239
|
+
name: "{{agentName}}",
|
|
12240
|
+
content: {
|
|
12241
|
+
text: "Adding a heart reaction now.",
|
|
12242
|
+
actions: [SEND_REACTION_ACTION]
|
|
12243
|
+
}
|
|
12244
|
+
}
|
|
12245
|
+
],
|
|
12246
|
+
[
|
|
12247
|
+
{
|
|
12248
|
+
name: "{{name1}}",
|
|
12249
|
+
content: {
|
|
12250
|
+
text: "\uD83D\uDD25 that message"
|
|
12251
|
+
}
|
|
12252
|
+
},
|
|
12253
|
+
{
|
|
12254
|
+
name: "{{agentName}}",
|
|
12255
|
+
content: {
|
|
12256
|
+
text: "I'll react with the fire emoji.",
|
|
12257
|
+
actions: [SEND_REACTION_ACTION]
|
|
12258
|
+
}
|
|
12259
|
+
}
|
|
12260
|
+
]
|
|
12261
|
+
]
|
|
12262
|
+
};
|
|
12263
|
+
// src/environment.ts
|
|
12264
|
+
import { z } from "zod";
|
|
12265
|
+
var telegramEnvSchema = z.object({
|
|
12266
|
+
TELEGRAM_BOT_TOKEN: z.string().min(1, "Telegram bot token is required"),
|
|
12267
|
+
TELEGRAM_API_ROOT: z.string().optional(),
|
|
12268
|
+
TELEGRAM_UPDATE_MODE: z.enum(["polling", "webhook"]).optional().default("polling"),
|
|
12269
|
+
TELEGRAM_WEBHOOK_URL: z.string().url().optional(),
|
|
12270
|
+
TELEGRAM_WEBHOOK_PATH: z.string().optional(),
|
|
12271
|
+
TELEGRAM_WEBHOOK_PORT: z.coerce.number().optional(),
|
|
12272
|
+
TELEGRAM_WEBHOOK_SECRET: z.string().optional(),
|
|
12273
|
+
TELEGRAM_ALLOWED_CHATS: z.string().optional(),
|
|
12274
|
+
TELEGRAM_PROXY_URL: z.string().url().optional(),
|
|
12275
|
+
TELEGRAM_DROP_PENDING_UPDATES: z.coerce.boolean().optional().default(true),
|
|
12276
|
+
TELEGRAM_SHOULD_IGNORE_BOT_MESSAGES: z.coerce.boolean().optional().default(true),
|
|
12277
|
+
TELEGRAM_SHOULD_RESPOND_ONLY_TO_MENTIONS: z.coerce.boolean().optional().default(false)
|
|
12278
|
+
});
|
|
12279
|
+
function parseAllowedChats(value) {
|
|
12280
|
+
if (!value)
|
|
12281
|
+
return [];
|
|
12282
|
+
const trimmed = value.trim();
|
|
12283
|
+
if (!trimmed)
|
|
12284
|
+
return [];
|
|
12285
|
+
if (trimmed.startsWith("[")) {
|
|
12286
|
+
const parsed = JSON.parse(trimmed);
|
|
12287
|
+
if (Array.isArray(parsed)) {
|
|
12288
|
+
return parsed.map((id) => {
|
|
12289
|
+
const num = typeof id === "string" ? parseInt(id, 10) : Number(id);
|
|
12290
|
+
return Number.isFinite(num) ? num : 0;
|
|
12291
|
+
}).filter((id) => id !== 0);
|
|
12292
|
+
}
|
|
12293
|
+
}
|
|
12294
|
+
return trimmed.split(",").map((s) => parseInt(s.trim(), 10)).filter((id) => Number.isFinite(id));
|
|
12295
|
+
}
|
|
12296
|
+
async function validateTelegramConfig(runtime) {
|
|
12297
|
+
try {
|
|
12298
|
+
const config = {
|
|
12299
|
+
TELEGRAM_BOT_TOKEN: runtime.getSetting("TELEGRAM_BOT_TOKEN") || process.env.TELEGRAM_BOT_TOKEN,
|
|
12300
|
+
TELEGRAM_API_ROOT: runtime.getSetting("TELEGRAM_API_ROOT") || process.env.TELEGRAM_API_ROOT,
|
|
12301
|
+
TELEGRAM_UPDATE_MODE: runtime.getSetting("TELEGRAM_UPDATE_MODE") || process.env.TELEGRAM_UPDATE_MODE,
|
|
12302
|
+
TELEGRAM_WEBHOOK_URL: runtime.getSetting("TELEGRAM_WEBHOOK_URL") || process.env.TELEGRAM_WEBHOOK_URL,
|
|
12303
|
+
TELEGRAM_WEBHOOK_PATH: runtime.getSetting("TELEGRAM_WEBHOOK_PATH") || process.env.TELEGRAM_WEBHOOK_PATH,
|
|
12304
|
+
TELEGRAM_WEBHOOK_PORT: runtime.getSetting("TELEGRAM_WEBHOOK_PORT") || process.env.TELEGRAM_WEBHOOK_PORT,
|
|
12305
|
+
TELEGRAM_WEBHOOK_SECRET: runtime.getSetting("TELEGRAM_WEBHOOK_SECRET") || process.env.TELEGRAM_WEBHOOK_SECRET,
|
|
12306
|
+
TELEGRAM_ALLOWED_CHATS: runtime.getSetting("TELEGRAM_ALLOWED_CHATS") || process.env.TELEGRAM_ALLOWED_CHATS,
|
|
12307
|
+
TELEGRAM_PROXY_URL: runtime.getSetting("TELEGRAM_PROXY_URL") || process.env.TELEGRAM_PROXY_URL,
|
|
12308
|
+
TELEGRAM_DROP_PENDING_UPDATES: runtime.getSetting("TELEGRAM_DROP_PENDING_UPDATES") || process.env.TELEGRAM_DROP_PENDING_UPDATES,
|
|
12309
|
+
TELEGRAM_SHOULD_IGNORE_BOT_MESSAGES: runtime.getSetting("TELEGRAM_SHOULD_IGNORE_BOT_MESSAGES") || process.env.TELEGRAM_SHOULD_IGNORE_BOT_MESSAGES,
|
|
12310
|
+
TELEGRAM_SHOULD_RESPOND_ONLY_TO_MENTIONS: runtime.getSetting("TELEGRAM_SHOULD_RESPOND_ONLY_TO_MENTIONS") || process.env.TELEGRAM_SHOULD_RESPOND_ONLY_TO_MENTIONS
|
|
12311
|
+
};
|
|
12312
|
+
return telegramEnvSchema.parse(config);
|
|
12313
|
+
} catch (error) {
|
|
12314
|
+
if (error instanceof z.ZodError) {
|
|
12315
|
+
const errorMessages = error.issues.map((err) => `${err.path.join(".")}: ${err.message}`).join(`
|
|
12316
|
+
`);
|
|
12317
|
+
console.warn(`Telegram configuration validation failed:
|
|
12318
|
+
${errorMessages}`);
|
|
12319
|
+
}
|
|
12320
|
+
return null;
|
|
12321
|
+
}
|
|
12322
|
+
}
|
|
12323
|
+
function buildTelegramSettings(config) {
|
|
12324
|
+
return {
|
|
12325
|
+
botToken: config.TELEGRAM_BOT_TOKEN,
|
|
12326
|
+
apiRoot: config.TELEGRAM_API_ROOT || "https://api.telegram.org",
|
|
12327
|
+
updateMode: config.TELEGRAM_UPDATE_MODE || "polling",
|
|
12328
|
+
webhookUrl: config.TELEGRAM_WEBHOOK_URL,
|
|
12329
|
+
webhookPath: config.TELEGRAM_WEBHOOK_PATH || "/telegram/webhook",
|
|
12330
|
+
webhookPort: config.TELEGRAM_WEBHOOK_PORT,
|
|
12331
|
+
webhookSecret: config.TELEGRAM_WEBHOOK_SECRET,
|
|
12332
|
+
allowedChatIds: parseAllowedChats(config.TELEGRAM_ALLOWED_CHATS),
|
|
12333
|
+
proxyUrl: config.TELEGRAM_PROXY_URL,
|
|
12334
|
+
dropPendingUpdates: config.TELEGRAM_DROP_PENDING_UPDATES ?? true,
|
|
12335
|
+
shouldIgnoreBotMessages: config.TELEGRAM_SHOULD_IGNORE_BOT_MESSAGES ?? true,
|
|
12336
|
+
shouldRespondOnlyToMentions: config.TELEGRAM_SHOULD_RESPOND_ONLY_TO_MENTIONS ?? false
|
|
12337
|
+
};
|
|
12338
|
+
}
|
|
12339
|
+
|
|
12037
12340
|
// src/messageManager.ts
|
|
12038
12341
|
var import_telegraf2 = __toESM(require_lib4(), 1);
|
|
12039
12342
|
import fs from "node:fs";
|
|
@@ -12043,7 +12346,7 @@ import {
|
|
|
12043
12346
|
EventType,
|
|
12044
12347
|
logger as logger2,
|
|
12045
12348
|
MemoryType,
|
|
12046
|
-
ModelType,
|
|
12349
|
+
ModelType as ModelType2,
|
|
12047
12350
|
ServiceType
|
|
12048
12351
|
} from "@elizaos/core";
|
|
12049
12352
|
|
|
@@ -12212,7 +12515,7 @@ class MessageManager {
|
|
|
12212
12515
|
imageUrl = fileLink.toString();
|
|
12213
12516
|
}
|
|
12214
12517
|
if (imageUrl) {
|
|
12215
|
-
const { title, description } = await this.runtime.useModel(
|
|
12518
|
+
const { title, description } = await this.runtime.useModel(ModelType2.IMAGE_DESCRIPTION, imageUrl);
|
|
12216
12519
|
return { description: `[Image: ${title}
|
|
12217
12520
|
${description}]` };
|
|
12218
12521
|
}
|
|
@@ -12810,12 +13113,134 @@ var chatStateProvider = {
|
|
|
12810
13113
|
var import_telegraf3 = __toESM(require_lib4(), 1);
|
|
12811
13114
|
import {
|
|
12812
13115
|
ChannelType as ChannelType2,
|
|
13116
|
+
checkPairingAllowed,
|
|
12813
13117
|
createUniqueUuid as createUniqueUuid2,
|
|
12814
13118
|
EventType as EventType2,
|
|
13119
|
+
isInAllowlist,
|
|
12815
13120
|
logger as logger3,
|
|
12816
13121
|
Role,
|
|
12817
13122
|
Service
|
|
12818
13123
|
} from "@elizaos/core";
|
|
13124
|
+
|
|
13125
|
+
// src/accounts.ts
|
|
13126
|
+
var DEFAULT_ACCOUNT_ID = "default";
|
|
13127
|
+
function normalizeAccountId(accountId) {
|
|
13128
|
+
if (!accountId || typeof accountId !== "string") {
|
|
13129
|
+
return DEFAULT_ACCOUNT_ID;
|
|
13130
|
+
}
|
|
13131
|
+
const trimmed = accountId.trim().toLowerCase();
|
|
13132
|
+
return trimmed || DEFAULT_ACCOUNT_ID;
|
|
13133
|
+
}
|
|
13134
|
+
function normalizeTelegramToken(raw) {
|
|
13135
|
+
const trimmed = raw?.trim();
|
|
13136
|
+
return trimmed || undefined;
|
|
13137
|
+
}
|
|
13138
|
+
function getMultiAccountConfig(runtime) {
|
|
13139
|
+
const characterTelegram = runtime.character?.settings?.telegram;
|
|
13140
|
+
return {
|
|
13141
|
+
enabled: characterTelegram?.enabled,
|
|
13142
|
+
token: characterTelegram?.token,
|
|
13143
|
+
accounts: characterTelegram?.accounts
|
|
13144
|
+
};
|
|
13145
|
+
}
|
|
13146
|
+
function listTelegramAccountIds(runtime) {
|
|
13147
|
+
const config = getMultiAccountConfig(runtime);
|
|
13148
|
+
const accounts = config.accounts;
|
|
13149
|
+
if (!accounts || typeof accounts !== "object") {
|
|
13150
|
+
return [DEFAULT_ACCOUNT_ID];
|
|
13151
|
+
}
|
|
13152
|
+
const ids = Object.keys(accounts).filter(Boolean);
|
|
13153
|
+
if (ids.length === 0) {
|
|
13154
|
+
return [DEFAULT_ACCOUNT_ID];
|
|
13155
|
+
}
|
|
13156
|
+
return ids.slice().sort((a, b) => a.localeCompare(b));
|
|
13157
|
+
}
|
|
13158
|
+
function resolveDefaultTelegramAccountId(runtime) {
|
|
13159
|
+
const ids = listTelegramAccountIds(runtime);
|
|
13160
|
+
if (ids.includes(DEFAULT_ACCOUNT_ID)) {
|
|
13161
|
+
return DEFAULT_ACCOUNT_ID;
|
|
13162
|
+
}
|
|
13163
|
+
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
|
13164
|
+
}
|
|
13165
|
+
function getAccountConfig(runtime, accountId) {
|
|
13166
|
+
const config = getMultiAccountConfig(runtime);
|
|
13167
|
+
const accounts = config.accounts;
|
|
13168
|
+
if (!accounts || typeof accounts !== "object") {
|
|
13169
|
+
return;
|
|
13170
|
+
}
|
|
13171
|
+
return accounts[accountId];
|
|
13172
|
+
}
|
|
13173
|
+
function mergeTelegramAccountConfig(runtime, accountId) {
|
|
13174
|
+
const multiConfig = getMultiAccountConfig(runtime);
|
|
13175
|
+
const { accounts: _ignored, ...baseConfig } = multiConfig;
|
|
13176
|
+
const accountConfig = getAccountConfig(runtime, accountId) ?? {};
|
|
13177
|
+
const envUpdateMode = runtime.getSetting("TELEGRAM_UPDATE_MODE");
|
|
13178
|
+
const envWebhookUrl = runtime.getSetting("TELEGRAM_WEBHOOK_URL");
|
|
13179
|
+
const envWebhookPort = runtime.getSetting("TELEGRAM_WEBHOOK_PORT");
|
|
13180
|
+
const envWebhookPath = runtime.getSetting("TELEGRAM_WEBHOOK_PATH");
|
|
13181
|
+
const envWebhookSecret = runtime.getSetting("TELEGRAM_WEBHOOK_SECRET");
|
|
13182
|
+
const envApiRoot = runtime.getSetting("TELEGRAM_API_ROOT");
|
|
13183
|
+
const envAllowedChats = runtime.getSetting("TELEGRAM_ALLOWED_CHATS");
|
|
13184
|
+
const envConfig = {
|
|
13185
|
+
updateMode: envUpdateMode === "webhook" ? "webhook" : "polling",
|
|
13186
|
+
webhookUrl: envWebhookUrl || undefined,
|
|
13187
|
+
webhookPort: envWebhookPort ? parseInt(envWebhookPort, 10) : undefined,
|
|
13188
|
+
webhookPath: envWebhookPath || undefined,
|
|
13189
|
+
webhookSecret: envWebhookSecret || undefined,
|
|
13190
|
+
apiRoot: envApiRoot || undefined,
|
|
13191
|
+
allowedChatIds: envAllowedChats ? envAllowedChats.split(",").map((s) => s.trim()).filter(Boolean) : undefined
|
|
13192
|
+
};
|
|
13193
|
+
return {
|
|
13194
|
+
...envConfig,
|
|
13195
|
+
...baseConfig,
|
|
13196
|
+
...accountConfig
|
|
13197
|
+
};
|
|
13198
|
+
}
|
|
13199
|
+
function resolveTelegramToken(runtime, opts = {}) {
|
|
13200
|
+
const accountId = normalizeAccountId(opts.accountId);
|
|
13201
|
+
const multiConfig = getMultiAccountConfig(runtime);
|
|
13202
|
+
const accountConfig = accountId !== DEFAULT_ACCOUNT_ID ? multiConfig.accounts?.[accountId] : multiConfig.accounts?.[DEFAULT_ACCOUNT_ID];
|
|
13203
|
+
const accountToken = normalizeTelegramToken(accountConfig?.token);
|
|
13204
|
+
if (accountToken) {
|
|
13205
|
+
return { token: accountToken, source: "config" };
|
|
13206
|
+
}
|
|
13207
|
+
const allowBase = accountId === DEFAULT_ACCOUNT_ID;
|
|
13208
|
+
const baseToken = allowBase ? normalizeTelegramToken(multiConfig.token) : undefined;
|
|
13209
|
+
if (baseToken) {
|
|
13210
|
+
return { token: baseToken, source: "character" };
|
|
13211
|
+
}
|
|
13212
|
+
const envToken = allowBase ? normalizeTelegramToken(runtime.getSetting("TELEGRAM_BOT_TOKEN")) : undefined;
|
|
13213
|
+
if (envToken) {
|
|
13214
|
+
return { token: envToken, source: "env" };
|
|
13215
|
+
}
|
|
13216
|
+
return { token: "", source: "none" };
|
|
13217
|
+
}
|
|
13218
|
+
function resolveTelegramAccount(runtime, accountId) {
|
|
13219
|
+
const normalizedAccountId = normalizeAccountId(accountId);
|
|
13220
|
+
const multiConfig = getMultiAccountConfig(runtime);
|
|
13221
|
+
const baseEnabled = multiConfig.enabled !== false;
|
|
13222
|
+
const merged = mergeTelegramAccountConfig(runtime, normalizedAccountId);
|
|
13223
|
+
const accountEnabled = merged.enabled !== false;
|
|
13224
|
+
const enabled = baseEnabled && accountEnabled;
|
|
13225
|
+
const tokenResolution = resolveTelegramToken(runtime, { accountId: normalizedAccountId });
|
|
13226
|
+
return {
|
|
13227
|
+
accountId: normalizedAccountId,
|
|
13228
|
+
enabled,
|
|
13229
|
+
name: merged.name?.trim() || undefined,
|
|
13230
|
+
token: tokenResolution.token,
|
|
13231
|
+
tokenSource: tokenResolution.source,
|
|
13232
|
+
config: merged
|
|
13233
|
+
};
|
|
13234
|
+
}
|
|
13235
|
+
function listEnabledTelegramAccounts(runtime) {
|
|
13236
|
+
return listTelegramAccountIds(runtime).map((accountId) => resolveTelegramAccount(runtime, accountId)).filter((account) => account.enabled && account.token);
|
|
13237
|
+
}
|
|
13238
|
+
function isMultiAccountEnabled(runtime) {
|
|
13239
|
+
const accounts = listEnabledTelegramAccounts(runtime);
|
|
13240
|
+
return accounts.length > 1;
|
|
13241
|
+
}
|
|
13242
|
+
|
|
13243
|
+
// src/service.ts
|
|
12819
13244
|
class TelegramService extends Service {
|
|
12820
13245
|
static serviceType = TELEGRAM_SERVICE_NAME;
|
|
12821
13246
|
capabilityDescription = "The agent is able to send and receive messages on telegram";
|
|
@@ -12824,6 +13249,9 @@ class TelegramService extends Service {
|
|
|
12824
13249
|
options;
|
|
12825
13250
|
knownChats = new Map;
|
|
12826
13251
|
syncedEntityIds = new Set;
|
|
13252
|
+
settings = null;
|
|
13253
|
+
botInfo = null;
|
|
13254
|
+
webhookServer = null;
|
|
12827
13255
|
constructor(runtime) {
|
|
12828
13256
|
super(runtime);
|
|
12829
13257
|
const botToken = runtime.getSetting("TELEGRAM_BOT_TOKEN");
|
|
@@ -12841,22 +13269,159 @@ class TelegramService extends Service {
|
|
|
12841
13269
|
this.bot = new import_telegraf3.Telegraf(botToken, this.options);
|
|
12842
13270
|
this.messageManager = new MessageManager(this.bot, this.runtime);
|
|
12843
13271
|
}
|
|
13272
|
+
getBotInfo() {
|
|
13273
|
+
return this.botInfo;
|
|
13274
|
+
}
|
|
13275
|
+
getSettings() {
|
|
13276
|
+
return this.settings;
|
|
13277
|
+
}
|
|
13278
|
+
async probeTelegram(timeoutMs = 5000) {
|
|
13279
|
+
if (!this.bot) {
|
|
13280
|
+
return {
|
|
13281
|
+
ok: false,
|
|
13282
|
+
error: "Bot not initialized",
|
|
13283
|
+
latencyMs: 0
|
|
13284
|
+
};
|
|
13285
|
+
}
|
|
13286
|
+
const startTime = Date.now();
|
|
13287
|
+
const controller = new AbortController;
|
|
13288
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
13289
|
+
try {
|
|
13290
|
+
const me = await this.bot.telegram.getMe();
|
|
13291
|
+
const latencyMs = Date.now() - startTime;
|
|
13292
|
+
return {
|
|
13293
|
+
ok: true,
|
|
13294
|
+
bot: {
|
|
13295
|
+
id: me.id,
|
|
13296
|
+
username: me.username,
|
|
13297
|
+
firstName: me.first_name,
|
|
13298
|
+
canJoinGroups: me.can_join_groups ?? false,
|
|
13299
|
+
canReadAllGroupMessages: me.can_read_all_group_messages ?? false,
|
|
13300
|
+
supportsInlineQueries: me.supports_inline_queries ?? false
|
|
13301
|
+
},
|
|
13302
|
+
latencyMs
|
|
13303
|
+
};
|
|
13304
|
+
} catch (error) {
|
|
13305
|
+
const latencyMs = Date.now() - startTime;
|
|
13306
|
+
return {
|
|
13307
|
+
ok: false,
|
|
13308
|
+
error: error instanceof Error ? error.message : String(error),
|
|
13309
|
+
latencyMs
|
|
13310
|
+
};
|
|
13311
|
+
} finally {
|
|
13312
|
+
clearTimeout(timeoutId);
|
|
13313
|
+
}
|
|
13314
|
+
}
|
|
13315
|
+
async sendReaction(params) {
|
|
13316
|
+
if (!this.bot) {
|
|
13317
|
+
return {
|
|
13318
|
+
success: false,
|
|
13319
|
+
chatId: params.chatId,
|
|
13320
|
+
messageId: params.messageId,
|
|
13321
|
+
reaction: params.reaction,
|
|
13322
|
+
error: "Bot not initialized"
|
|
13323
|
+
};
|
|
13324
|
+
}
|
|
13325
|
+
try {
|
|
13326
|
+
const chatId = typeof params.chatId === "string" ? parseInt(params.chatId, 10) : params.chatId;
|
|
13327
|
+
const reactionType = {
|
|
13328
|
+
type: "emoji",
|
|
13329
|
+
emoji: params.reaction
|
|
13330
|
+
};
|
|
13331
|
+
await this.bot.telegram.setMessageReaction(chatId, params.messageId, [reactionType], params.isBig ?? false);
|
|
13332
|
+
this.runtime.emitEvent("TELEGRAM_REACTION_SENT" /* REACTION_SENT */, {
|
|
13333
|
+
runtime: this.runtime,
|
|
13334
|
+
chatId: params.chatId,
|
|
13335
|
+
messageId: params.messageId,
|
|
13336
|
+
reaction: params.reaction,
|
|
13337
|
+
success: true
|
|
13338
|
+
});
|
|
13339
|
+
return {
|
|
13340
|
+
success: true,
|
|
13341
|
+
chatId: params.chatId,
|
|
13342
|
+
messageId: params.messageId,
|
|
13343
|
+
reaction: params.reaction
|
|
13344
|
+
};
|
|
13345
|
+
} catch (error) {
|
|
13346
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
13347
|
+
logger3.error({ error }, `Failed to send reaction: ${errorMessage}`);
|
|
13348
|
+
return {
|
|
13349
|
+
success: false,
|
|
13350
|
+
chatId: params.chatId,
|
|
13351
|
+
messageId: params.messageId,
|
|
13352
|
+
reaction: params.reaction,
|
|
13353
|
+
error: errorMessage
|
|
13354
|
+
};
|
|
13355
|
+
}
|
|
13356
|
+
}
|
|
13357
|
+
async removeReaction(chatId, messageId) {
|
|
13358
|
+
if (!this.bot) {
|
|
13359
|
+
return {
|
|
13360
|
+
success: false,
|
|
13361
|
+
chatId,
|
|
13362
|
+
messageId,
|
|
13363
|
+
reaction: "",
|
|
13364
|
+
error: "Bot not initialized"
|
|
13365
|
+
};
|
|
13366
|
+
}
|
|
13367
|
+
try {
|
|
13368
|
+
const numericChatId = typeof chatId === "string" ? parseInt(chatId, 10) : chatId;
|
|
13369
|
+
await this.bot.telegram.setMessageReaction(numericChatId, messageId, []);
|
|
13370
|
+
return {
|
|
13371
|
+
success: true,
|
|
13372
|
+
chatId,
|
|
13373
|
+
messageId,
|
|
13374
|
+
reaction: ""
|
|
13375
|
+
};
|
|
13376
|
+
} catch (error) {
|
|
13377
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
13378
|
+
logger3.error({ error }, `Failed to remove reaction: ${errorMessage}`);
|
|
13379
|
+
return {
|
|
13380
|
+
success: false,
|
|
13381
|
+
chatId,
|
|
13382
|
+
messageId,
|
|
13383
|
+
reaction: "",
|
|
13384
|
+
error: errorMessage
|
|
13385
|
+
};
|
|
13386
|
+
}
|
|
13387
|
+
}
|
|
12844
13388
|
static async start(runtime) {
|
|
12845
13389
|
const service = new TelegramService(runtime);
|
|
12846
13390
|
if (!service.bot) {
|
|
12847
13391
|
logger3.warn("Telegram service started without bot functionality - no bot token provided");
|
|
12848
13392
|
return service;
|
|
12849
13393
|
}
|
|
13394
|
+
const config = await validateTelegramConfig(runtime);
|
|
13395
|
+
if (config) {
|
|
13396
|
+
service.settings = buildTelegramSettings(config);
|
|
13397
|
+
}
|
|
12850
13398
|
const maxRetries = 5;
|
|
12851
13399
|
let retryCount = 0;
|
|
12852
13400
|
let lastError = null;
|
|
12853
13401
|
while (retryCount < maxRetries) {
|
|
12854
13402
|
try {
|
|
12855
13403
|
logger3.success(`Telegram client started for character ${runtime.character.name}`);
|
|
12856
|
-
await service.
|
|
13404
|
+
const botInfo = await service.bot?.telegram.getMe();
|
|
13405
|
+
if (botInfo) {
|
|
13406
|
+
service.botInfo = botInfo;
|
|
13407
|
+
logger3.info(`Bot connected: @${botInfo.username} (ID: ${botInfo.id})`);
|
|
13408
|
+
}
|
|
12857
13409
|
service.setupMiddlewares();
|
|
12858
13410
|
service.setupMessageHandlers();
|
|
12859
|
-
|
|
13411
|
+
const updateMode = service.settings?.updateMode || "polling";
|
|
13412
|
+
if (updateMode === "webhook" && service.settings?.webhookUrl) {
|
|
13413
|
+
await service.initializeWebhook();
|
|
13414
|
+
} else {
|
|
13415
|
+
await service.initializePolling();
|
|
13416
|
+
}
|
|
13417
|
+
service.runtime.emitEvent("TELEGRAM_BOT_STARTED" /* BOT_STARTED */, {
|
|
13418
|
+
runtime: service.runtime,
|
|
13419
|
+
botId: service.botInfo?.id,
|
|
13420
|
+
botUsername: service.botInfo?.username,
|
|
13421
|
+
botName: service.botInfo?.first_name,
|
|
13422
|
+
updateMode,
|
|
13423
|
+
timestamp: Date.now()
|
|
13424
|
+
});
|
|
12860
13425
|
return service;
|
|
12861
13426
|
} catch (error) {
|
|
12862
13427
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
@@ -12879,9 +13444,23 @@ class TelegramService extends Service {
|
|
|
12879
13444
|
}
|
|
12880
13445
|
}
|
|
12881
13446
|
async stop() {
|
|
13447
|
+
this.runtime.emitEvent("TELEGRAM_BOT_STOPPED" /* BOT_STOPPED */, {
|
|
13448
|
+
runtime: this.runtime,
|
|
13449
|
+
botId: this.botInfo?.id,
|
|
13450
|
+
botUsername: this.botInfo?.username,
|
|
13451
|
+
botName: this.botInfo?.first_name,
|
|
13452
|
+
updateMode: this.settings?.updateMode || "polling",
|
|
13453
|
+
timestamp: Date.now()
|
|
13454
|
+
});
|
|
13455
|
+
if (this.webhookServer) {
|
|
13456
|
+
await new Promise((resolve) => {
|
|
13457
|
+
this.webhookServer?.close(() => resolve());
|
|
13458
|
+
});
|
|
13459
|
+
this.webhookServer = null;
|
|
13460
|
+
}
|
|
12882
13461
|
this.bot?.stop();
|
|
12883
13462
|
}
|
|
12884
|
-
async
|
|
13463
|
+
async initializePolling() {
|
|
12885
13464
|
this.bot?.start((ctx) => {
|
|
12886
13465
|
this.runtime.emitEvent("TELEGRAM_SLASH_START" /* SLASH_START */, {
|
|
12887
13466
|
runtime: this.runtime,
|
|
@@ -12889,17 +13468,102 @@ class TelegramService extends Service {
|
|
|
12889
13468
|
ctx
|
|
12890
13469
|
});
|
|
12891
13470
|
});
|
|
13471
|
+
const dropPendingUpdates = this.settings?.dropPendingUpdates ?? true;
|
|
12892
13472
|
this.bot?.launch({
|
|
12893
|
-
dropPendingUpdates
|
|
12894
|
-
allowedUpdates: ["message", "message_reaction"]
|
|
13473
|
+
dropPendingUpdates,
|
|
13474
|
+
allowedUpdates: ["message", "message_reaction", "chat_member", "my_chat_member"]
|
|
12895
13475
|
});
|
|
12896
|
-
|
|
12897
|
-
logger3.log(`Bot info: ${JSON.stringify(botInfo)}`);
|
|
13476
|
+
logger3.info(`Telegram bot started in polling mode (dropPendingUpdates: ${dropPendingUpdates})`);
|
|
12898
13477
|
process.once("SIGINT", () => this.bot?.stop("SIGINT"));
|
|
12899
13478
|
process.once("SIGTERM", () => this.bot?.stop("SIGTERM"));
|
|
12900
13479
|
}
|
|
13480
|
+
async initializeWebhook() {
|
|
13481
|
+
if (!this.bot || !this.settings?.webhookUrl) {
|
|
13482
|
+
throw new Error("Bot or webhook URL not configured");
|
|
13483
|
+
}
|
|
13484
|
+
const webhookUrl = this.settings.webhookUrl;
|
|
13485
|
+
const webhookPath = this.settings.webhookPath || "/telegram/webhook";
|
|
13486
|
+
const webhookPort = this.settings.webhookPort || 3000;
|
|
13487
|
+
const webhookSecret = this.settings.webhookSecret;
|
|
13488
|
+
this.bot.start((ctx) => {
|
|
13489
|
+
this.runtime.emitEvent("TELEGRAM_SLASH_START" /* SLASH_START */, {
|
|
13490
|
+
runtime: this.runtime,
|
|
13491
|
+
source: "telegram",
|
|
13492
|
+
ctx
|
|
13493
|
+
});
|
|
13494
|
+
});
|
|
13495
|
+
const fullWebhookUrl = `${webhookUrl}${webhookPath}`;
|
|
13496
|
+
await this.bot.telegram.setWebhook(fullWebhookUrl, {
|
|
13497
|
+
secret_token: webhookSecret,
|
|
13498
|
+
allowed_updates: ["message", "message_reaction", "chat_member", "my_chat_member"],
|
|
13499
|
+
drop_pending_updates: this.settings.dropPendingUpdates
|
|
13500
|
+
});
|
|
13501
|
+
const webhookCallback = this.bot.webhookCallback(webhookPath, {
|
|
13502
|
+
secretToken: webhookSecret
|
|
13503
|
+
});
|
|
13504
|
+
const http = await import("node:http");
|
|
13505
|
+
this.webhookServer = http.createServer(async (req, res) => {
|
|
13506
|
+
if (req.url === webhookPath && req.method === "POST") {
|
|
13507
|
+
await webhookCallback(req, res);
|
|
13508
|
+
} else if (req.url === "/health" || req.url === "/") {
|
|
13509
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
13510
|
+
res.end(JSON.stringify({ status: "ok", bot: this.botInfo?.username }));
|
|
13511
|
+
} else {
|
|
13512
|
+
res.writeHead(404);
|
|
13513
|
+
res.end("Not Found");
|
|
13514
|
+
}
|
|
13515
|
+
});
|
|
13516
|
+
this.webhookServer.listen(webhookPort, () => {
|
|
13517
|
+
logger3.info(`Telegram webhook server listening on port ${webhookPort}`);
|
|
13518
|
+
logger3.info(`Webhook URL: ${fullWebhookUrl}`);
|
|
13519
|
+
});
|
|
13520
|
+
this.runtime.emitEvent("TELEGRAM_WEBHOOK_REGISTERED" /* WEBHOOK_REGISTERED */, {
|
|
13521
|
+
runtime: this.runtime,
|
|
13522
|
+
url: fullWebhookUrl,
|
|
13523
|
+
path: webhookPath,
|
|
13524
|
+
port: webhookPort,
|
|
13525
|
+
hasSecret: !!webhookSecret,
|
|
13526
|
+
timestamp: Date.now()
|
|
13527
|
+
});
|
|
13528
|
+
process.once("SIGINT", () => this.stop());
|
|
13529
|
+
process.once("SIGTERM", () => this.stop());
|
|
13530
|
+
}
|
|
13531
|
+
async deleteWebhook() {
|
|
13532
|
+
if (!this.bot) {
|
|
13533
|
+
return false;
|
|
13534
|
+
}
|
|
13535
|
+
try {
|
|
13536
|
+
await this.bot.telegram.deleteWebhook({ drop_pending_updates: true });
|
|
13537
|
+
logger3.info("Webhook deleted successfully");
|
|
13538
|
+
return true;
|
|
13539
|
+
} catch (error) {
|
|
13540
|
+
logger3.error({ error }, "Failed to delete webhook");
|
|
13541
|
+
return false;
|
|
13542
|
+
}
|
|
13543
|
+
}
|
|
13544
|
+
async getWebhookInfo() {
|
|
13545
|
+
if (!this.bot) {
|
|
13546
|
+
return null;
|
|
13547
|
+
}
|
|
13548
|
+
try {
|
|
13549
|
+
const info = await this.bot.telegram.getWebhookInfo();
|
|
13550
|
+
return {
|
|
13551
|
+
url: info.url,
|
|
13552
|
+
hasCustomCertificate: info.has_custom_certificate,
|
|
13553
|
+
pendingUpdateCount: info.pending_update_count,
|
|
13554
|
+
lastErrorDate: info.last_error_date,
|
|
13555
|
+
lastErrorMessage: info.last_error_message,
|
|
13556
|
+
maxConnections: info.max_connections,
|
|
13557
|
+
allowedUpdates: info.allowed_updates
|
|
13558
|
+
};
|
|
13559
|
+
} catch (error) {
|
|
13560
|
+
logger3.error({ error }, "Failed to get webhook info");
|
|
13561
|
+
return null;
|
|
13562
|
+
}
|
|
13563
|
+
}
|
|
12901
13564
|
setupMiddlewares() {
|
|
12902
13565
|
this.bot?.use(this.authorizationMiddleware.bind(this));
|
|
13566
|
+
this.bot?.use(this.dmAccessMiddleware.bind(this));
|
|
12903
13567
|
this.bot?.use(this.chatAndEntityMiddleware.bind(this));
|
|
12904
13568
|
}
|
|
12905
13569
|
async authorizationMiddleware(ctx, next) {
|
|
@@ -12909,6 +13573,75 @@ class TelegramService extends Service {
|
|
|
12909
13573
|
}
|
|
12910
13574
|
await next();
|
|
12911
13575
|
}
|
|
13576
|
+
async dmAccessMiddleware(ctx, next) {
|
|
13577
|
+
if (ctx.chat?.type !== "private") {
|
|
13578
|
+
return next();
|
|
13579
|
+
}
|
|
13580
|
+
const accessResult = await this.checkDmAccess(ctx);
|
|
13581
|
+
if (!accessResult.allowed) {
|
|
13582
|
+
if (accessResult.replyMessage && ctx.from) {
|
|
13583
|
+
try {
|
|
13584
|
+
await this.bot?.telegram.sendMessage(ctx.from.id, accessResult.replyMessage);
|
|
13585
|
+
} catch (err) {
|
|
13586
|
+
logger3.warn({ error: err instanceof Error ? err.message : String(err), userId: ctx.from.id }, "Failed to send pairing reply");
|
|
13587
|
+
}
|
|
13588
|
+
}
|
|
13589
|
+
return;
|
|
13590
|
+
}
|
|
13591
|
+
await next();
|
|
13592
|
+
}
|
|
13593
|
+
async checkDmAccess(ctx) {
|
|
13594
|
+
if (!ctx.from) {
|
|
13595
|
+
return { allowed: false };
|
|
13596
|
+
}
|
|
13597
|
+
const account = resolveTelegramAccount(this.runtime);
|
|
13598
|
+
const dmConfig = account.config.dm;
|
|
13599
|
+
const policy = dmConfig?.policy ?? "open";
|
|
13600
|
+
const userId = ctx.from.id.toString();
|
|
13601
|
+
if (policy === "disabled" || dmConfig?.enabled === false) {
|
|
13602
|
+
logger3.debug({ userId }, "DM blocked: policy is disabled");
|
|
13603
|
+
return { allowed: false };
|
|
13604
|
+
}
|
|
13605
|
+
if (policy === "open") {
|
|
13606
|
+
return { allowed: true };
|
|
13607
|
+
}
|
|
13608
|
+
if (policy === "allowlist") {
|
|
13609
|
+
const allowFrom = dmConfig?.allowFrom ?? [];
|
|
13610
|
+
if (allowFrom.some((a) => String(a) === userId || String(a) === ctx.from?.username)) {
|
|
13611
|
+
return { allowed: true };
|
|
13612
|
+
}
|
|
13613
|
+
const inDynamicAllowlist = await isInAllowlist(this.runtime, "telegram", userId);
|
|
13614
|
+
if (inDynamicAllowlist) {
|
|
13615
|
+
return { allowed: true };
|
|
13616
|
+
}
|
|
13617
|
+
logger3.debug({ userId }, "DM blocked: user not in allowlist");
|
|
13618
|
+
return { allowed: false };
|
|
13619
|
+
}
|
|
13620
|
+
if (policy === "pairing") {
|
|
13621
|
+
const allowFrom = dmConfig?.allowFrom ?? [];
|
|
13622
|
+
if (allowFrom.some((a) => String(a) === userId || String(a) === ctx.from?.username)) {
|
|
13623
|
+
return { allowed: true };
|
|
13624
|
+
}
|
|
13625
|
+
const result = await checkPairingAllowed(this.runtime, {
|
|
13626
|
+
channel: "telegram",
|
|
13627
|
+
senderId: userId,
|
|
13628
|
+
metadata: {
|
|
13629
|
+
username: ctx.from.username ?? "",
|
|
13630
|
+
firstName: ctx.from.first_name ?? "",
|
|
13631
|
+
lastName: ctx.from.last_name ?? ""
|
|
13632
|
+
}
|
|
13633
|
+
});
|
|
13634
|
+
if (result.allowed) {
|
|
13635
|
+
return { allowed: true };
|
|
13636
|
+
}
|
|
13637
|
+
logger3.debug({ userId, pairingCode: result.pairingCode, newRequest: result.newRequest }, "DM blocked: pairing required");
|
|
13638
|
+
return {
|
|
13639
|
+
allowed: false,
|
|
13640
|
+
replyMessage: result.newRequest ? result.replyMessage : undefined
|
|
13641
|
+
};
|
|
13642
|
+
}
|
|
13643
|
+
return { allowed: true };
|
|
13644
|
+
}
|
|
12912
13645
|
async chatAndEntityMiddleware(ctx, next) {
|
|
12913
13646
|
if (!ctx.chat)
|
|
12914
13647
|
return next();
|
|
@@ -13515,25 +14248,306 @@ class TelegramTestSuite {
|
|
|
13515
14248
|
}
|
|
13516
14249
|
}
|
|
13517
14250
|
}
|
|
14251
|
+
// src/formatting.ts
|
|
14252
|
+
function escapeHtml(text) {
|
|
14253
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
14254
|
+
}
|
|
14255
|
+
function escapeHtmlAttr(text) {
|
|
14256
|
+
return escapeHtml(text).replace(/"/g, """);
|
|
14257
|
+
}
|
|
14258
|
+
function escapeMarkdownV2(text) {
|
|
14259
|
+
return text.replace(/([_*[\]()~`>#+\-=|{}.!\\])/g, "\\$1");
|
|
14260
|
+
}
|
|
14261
|
+
function convertBold(text) {
|
|
14262
|
+
return text.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
|
|
14263
|
+
}
|
|
14264
|
+
function convertItalic(text) {
|
|
14265
|
+
return text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<i>$1</i>");
|
|
14266
|
+
}
|
|
14267
|
+
function convertUnderline(text) {
|
|
14268
|
+
return text.replace(/__(.+?)__/g, "<u>$1</u>");
|
|
14269
|
+
}
|
|
14270
|
+
function convertStrikethrough(text) {
|
|
14271
|
+
return text.replace(/~~(.+?)~~/g, "<s>$1</s>");
|
|
14272
|
+
}
|
|
14273
|
+
function convertInlineCode(text) {
|
|
14274
|
+
return text.replace(/`([^`\n]+)`/g, (_, code) => `<code>${escapeHtml(code)}</code>`);
|
|
14275
|
+
}
|
|
14276
|
+
function convertCodeBlocks(text) {
|
|
14277
|
+
return text.replace(/```(\w*)\n?([\s\S]*?)```/g, (_, lang, code) => {
|
|
14278
|
+
const escapedCode = escapeHtml(code.trim());
|
|
14279
|
+
if (lang) {
|
|
14280
|
+
return `<pre><code class="language-${escapeHtmlAttr(lang)}">${escapedCode}</code></pre>`;
|
|
14281
|
+
}
|
|
14282
|
+
return `<pre><code>${escapedCode}</code></pre>`;
|
|
14283
|
+
});
|
|
14284
|
+
}
|
|
14285
|
+
function convertLinks(text) {
|
|
14286
|
+
return text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, linkText, url) => {
|
|
14287
|
+
const safeUrl = escapeHtmlAttr(url.trim());
|
|
14288
|
+
return `<a href="${safeUrl}">${escapeHtml(linkText)}</a>`;
|
|
14289
|
+
});
|
|
14290
|
+
}
|
|
14291
|
+
function linkifyUrls(text) {
|
|
14292
|
+
const urlRegex = /(?<!["'])(https?:\/\/[^\s<>"']+)/g;
|
|
14293
|
+
return text.replace(urlRegex, (url) => {
|
|
14294
|
+
const safeUrl = escapeHtmlAttr(url);
|
|
14295
|
+
return `<a href="${safeUrl}">${escapeHtml(url)}</a>`;
|
|
14296
|
+
});
|
|
14297
|
+
}
|
|
14298
|
+
function markdownToTelegramHtml(markdown, options = {}) {
|
|
14299
|
+
if (!markdown) {
|
|
14300
|
+
return "";
|
|
14301
|
+
}
|
|
14302
|
+
let result = markdown;
|
|
14303
|
+
result = convertCodeBlocks(result);
|
|
14304
|
+
result = convertInlineCode(result);
|
|
14305
|
+
result = convertLinks(result);
|
|
14306
|
+
const htmlTagPattern = /(<(?:b|i|u|s|code|pre|a)[^>]*>[\s\S]*?<\/(?:b|i|u|s|code|pre|a)>)/g;
|
|
14307
|
+
const parts = result.split(htmlTagPattern);
|
|
14308
|
+
result = parts.map((part, index) => {
|
|
14309
|
+
if (index % 2 === 0) {
|
|
14310
|
+
let text = escapeHtml(part);
|
|
14311
|
+
text = convertBold(text);
|
|
14312
|
+
text = convertItalic(text);
|
|
14313
|
+
text = convertUnderline(text);
|
|
14314
|
+
text = convertStrikethrough(text);
|
|
14315
|
+
if (options.linkify !== false) {
|
|
14316
|
+
text = linkifyUrls(text);
|
|
14317
|
+
}
|
|
14318
|
+
return text;
|
|
14319
|
+
}
|
|
14320
|
+
return part;
|
|
14321
|
+
}).join("");
|
|
14322
|
+
return result;
|
|
14323
|
+
}
|
|
14324
|
+
function markdownToTelegramChunks(markdown, limit, options = {}) {
|
|
14325
|
+
const html = markdownToTelegramHtml(markdown, options);
|
|
14326
|
+
const chunks = chunkTelegramText(html, limit);
|
|
14327
|
+
return chunks.map((chunk) => ({
|
|
14328
|
+
html: chunk,
|
|
14329
|
+
text: stripHtmlTags(chunk)
|
|
14330
|
+
}));
|
|
14331
|
+
}
|
|
14332
|
+
function markdownToTelegramHtmlChunks(markdown, limit) {
|
|
14333
|
+
return markdownToTelegramChunks(markdown, limit).map((chunk) => chunk.html);
|
|
14334
|
+
}
|
|
14335
|
+
function stripHtmlTags(html) {
|
|
14336
|
+
return html.replace(/<[^>]+>/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"');
|
|
14337
|
+
}
|
|
14338
|
+
var DEFAULT_MAX_CHARS = 4096;
|
|
14339
|
+
function chunkTelegramText(text, maxChars = DEFAULT_MAX_CHARS) {
|
|
14340
|
+
if (!text) {
|
|
14341
|
+
return [];
|
|
14342
|
+
}
|
|
14343
|
+
if (text.length <= maxChars) {
|
|
14344
|
+
return [text];
|
|
14345
|
+
}
|
|
14346
|
+
const chunks = [];
|
|
14347
|
+
let remaining = text;
|
|
14348
|
+
while (remaining.length > 0) {
|
|
14349
|
+
if (remaining.length <= maxChars) {
|
|
14350
|
+
chunks.push(remaining);
|
|
14351
|
+
break;
|
|
14352
|
+
}
|
|
14353
|
+
let breakPoint = maxChars;
|
|
14354
|
+
const newlineIndex = remaining.lastIndexOf(`
|
|
14355
|
+
`, maxChars);
|
|
14356
|
+
if (newlineIndex > maxChars * 0.5) {
|
|
14357
|
+
breakPoint = newlineIndex + 1;
|
|
14358
|
+
} else {
|
|
14359
|
+
const spaceIndex = remaining.lastIndexOf(" ", maxChars);
|
|
14360
|
+
if (spaceIndex > maxChars * 0.5) {
|
|
14361
|
+
breakPoint = spaceIndex + 1;
|
|
14362
|
+
}
|
|
14363
|
+
}
|
|
14364
|
+
const chunk = remaining.slice(0, breakPoint);
|
|
14365
|
+
const openTags = chunk.match(/<(\w+)[^>]*>/g) || [];
|
|
14366
|
+
const closeTags = chunk.match(/<\/(\w+)>/g) || [];
|
|
14367
|
+
const tagStack = [];
|
|
14368
|
+
for (const tag of openTags) {
|
|
14369
|
+
const tagName = tag.match(/<(\w+)/)?.[1];
|
|
14370
|
+
if (tagName && !tag.endsWith("/>")) {
|
|
14371
|
+
tagStack.push(tagName);
|
|
14372
|
+
}
|
|
14373
|
+
}
|
|
14374
|
+
for (const tag of closeTags) {
|
|
14375
|
+
const tagName = tag.match(/<\/(\w+)>/)?.[1];
|
|
14376
|
+
if (tagName) {
|
|
14377
|
+
const index = tagStack.lastIndexOf(tagName);
|
|
14378
|
+
if (index !== -1) {
|
|
14379
|
+
tagStack.splice(index, 1);
|
|
14380
|
+
}
|
|
14381
|
+
}
|
|
14382
|
+
}
|
|
14383
|
+
let chunkWithClosedTags = chunk;
|
|
14384
|
+
const closingTags = tagStack.slice().reverse().map((tag) => `</${tag}>`).join("");
|
|
14385
|
+
chunkWithClosedTags += closingTags;
|
|
14386
|
+
chunks.push(chunkWithClosedTags);
|
|
14387
|
+
const openingTags = tagStack.map((tag) => `<${tag}>`).join("");
|
|
14388
|
+
remaining = openingTags + remaining.slice(breakPoint);
|
|
14389
|
+
}
|
|
14390
|
+
return chunks;
|
|
14391
|
+
}
|
|
14392
|
+
function formatTelegramUser(user) {
|
|
14393
|
+
if (user.username) {
|
|
14394
|
+
return `@${user.username}`;
|
|
14395
|
+
}
|
|
14396
|
+
if (user.last_name) {
|
|
14397
|
+
return `${user.first_name} ${user.last_name}`;
|
|
14398
|
+
}
|
|
14399
|
+
return user.first_name;
|
|
14400
|
+
}
|
|
14401
|
+
function formatTelegramUserMention(user) {
|
|
14402
|
+
const displayName = formatTelegramUser(user);
|
|
14403
|
+
return `<a href="tg://user?id=${user.id}">${escapeHtml(displayName)}</a>`;
|
|
14404
|
+
}
|
|
14405
|
+
function formatTelegramChat(chat) {
|
|
14406
|
+
if (chat.type === "private") {
|
|
14407
|
+
const privateChat = chat;
|
|
14408
|
+
if (privateChat.username) {
|
|
14409
|
+
return `@${privateChat.username}`;
|
|
14410
|
+
}
|
|
14411
|
+
if (privateChat.last_name) {
|
|
14412
|
+
return `${privateChat.first_name} ${privateChat.last_name}`;
|
|
14413
|
+
}
|
|
14414
|
+
return privateChat.first_name || `User ${chat.id}`;
|
|
14415
|
+
}
|
|
14416
|
+
const groupChat = chat;
|
|
14417
|
+
if ("username" in groupChat && groupChat.username) {
|
|
14418
|
+
return `@${groupChat.username}`;
|
|
14419
|
+
}
|
|
14420
|
+
return groupChat.title || `Chat ${chat.id}`;
|
|
14421
|
+
}
|
|
14422
|
+
function getChatTypeString(chat) {
|
|
14423
|
+
switch (chat.type) {
|
|
14424
|
+
case "private":
|
|
14425
|
+
return "DM";
|
|
14426
|
+
case "group":
|
|
14427
|
+
return "Group";
|
|
14428
|
+
case "supergroup":
|
|
14429
|
+
return "Supergroup";
|
|
14430
|
+
case "channel":
|
|
14431
|
+
return "Channel";
|
|
14432
|
+
default:
|
|
14433
|
+
return "Unknown";
|
|
14434
|
+
}
|
|
14435
|
+
}
|
|
14436
|
+
function resolveTelegramSystemLocation(chat) {
|
|
14437
|
+
const chatType = getChatTypeString(chat);
|
|
14438
|
+
const chatName = formatTelegramChat(chat);
|
|
14439
|
+
return `${chatType}: ${chatName}`;
|
|
14440
|
+
}
|
|
14441
|
+
function isPrivateChat(chat) {
|
|
14442
|
+
return chat.type === "private";
|
|
14443
|
+
}
|
|
14444
|
+
function isGroupChat(chat) {
|
|
14445
|
+
return chat.type === "group" || chat.type === "supergroup";
|
|
14446
|
+
}
|
|
14447
|
+
function isChannelChat(chat) {
|
|
14448
|
+
return chat.type === "channel";
|
|
14449
|
+
}
|
|
14450
|
+
function truncateText(text, maxLength, ellipsis = "…") {
|
|
14451
|
+
if (text.length <= maxLength) {
|
|
14452
|
+
return text;
|
|
14453
|
+
}
|
|
14454
|
+
return text.slice(0, maxLength - ellipsis.length) + ellipsis;
|
|
14455
|
+
}
|
|
14456
|
+
function buildTelegramDeepLink(botUsername, startParam) {
|
|
14457
|
+
const base = `https://t.me/${botUsername}`;
|
|
14458
|
+
if (startParam) {
|
|
14459
|
+
return `${base}?start=${encodeURIComponent(startParam)}`;
|
|
14460
|
+
}
|
|
14461
|
+
return base;
|
|
14462
|
+
}
|
|
14463
|
+
function buildTelegramMessageLink(chatUsername, messageId) {
|
|
14464
|
+
return `https://t.me/${chatUsername}/${messageId}`;
|
|
14465
|
+
}
|
|
14466
|
+
function parseTelegramMessageLink(url) {
|
|
14467
|
+
const match = url.match(/^https?:\/\/t\.me\/([^/]+)\/(\d+)$/);
|
|
14468
|
+
if (!match) {
|
|
14469
|
+
return null;
|
|
14470
|
+
}
|
|
14471
|
+
return {
|
|
14472
|
+
chatUsername: match[1],
|
|
14473
|
+
messageId: parseInt(match[2], 10)
|
|
14474
|
+
};
|
|
14475
|
+
}
|
|
14476
|
+
function formatMediaCaption(text, maxLength = 1024) {
|
|
14477
|
+
if (!text) {
|
|
14478
|
+
return "";
|
|
14479
|
+
}
|
|
14480
|
+
if (text.length <= maxLength) {
|
|
14481
|
+
return text;
|
|
14482
|
+
}
|
|
14483
|
+
let breakPoint = maxLength - 1;
|
|
14484
|
+
const newlineIndex = text.lastIndexOf(`
|
|
14485
|
+
`, maxLength);
|
|
14486
|
+
if (newlineIndex > maxLength * 0.5) {
|
|
14487
|
+
breakPoint = newlineIndex;
|
|
14488
|
+
} else {
|
|
14489
|
+
const spaceIndex = text.lastIndexOf(" ", maxLength);
|
|
14490
|
+
if (spaceIndex > maxLength * 0.5) {
|
|
14491
|
+
breakPoint = spaceIndex;
|
|
14492
|
+
}
|
|
14493
|
+
}
|
|
14494
|
+
return `${text.slice(0, breakPoint)}…`;
|
|
14495
|
+
}
|
|
13518
14496
|
|
|
13519
14497
|
// src/index.ts
|
|
13520
14498
|
var telegramPlugin = {
|
|
13521
14499
|
name: TELEGRAM_SERVICE_NAME,
|
|
13522
|
-
description: "Telegram client plugin",
|
|
14500
|
+
description: "Telegram client plugin with polling and webhook support",
|
|
13523
14501
|
services: [TelegramService],
|
|
13524
|
-
actions: [sendMessageAction],
|
|
14502
|
+
actions: [sendMessageAction, sendReactionAction],
|
|
13525
14503
|
providers: [chatStateProvider],
|
|
13526
14504
|
tests: [new TelegramTestSuite]
|
|
13527
14505
|
};
|
|
13528
14506
|
var src_default = telegramPlugin;
|
|
13529
14507
|
export {
|
|
14508
|
+
validateTelegramConfig,
|
|
14509
|
+
truncateText,
|
|
14510
|
+
stripHtmlTags,
|
|
14511
|
+
sendReactionAction,
|
|
13530
14512
|
sendMessageAction,
|
|
14513
|
+
resolveTelegramToken,
|
|
14514
|
+
resolveTelegramSystemLocation,
|
|
14515
|
+
resolveTelegramAccount,
|
|
14516
|
+
resolveDefaultTelegramAccountId,
|
|
14517
|
+
parseTelegramMessageLink,
|
|
14518
|
+
normalizeTelegramToken,
|
|
14519
|
+
normalizeAccountId,
|
|
14520
|
+
markdownToTelegramHtmlChunks,
|
|
14521
|
+
markdownToTelegramHtml,
|
|
14522
|
+
markdownToTelegramChunks,
|
|
14523
|
+
listTelegramAccountIds,
|
|
14524
|
+
listEnabledTelegramAccounts,
|
|
14525
|
+
isPrivateChat,
|
|
14526
|
+
isMultiAccountEnabled,
|
|
14527
|
+
isGroupChat,
|
|
14528
|
+
isChannelChat,
|
|
14529
|
+
getChatTypeString,
|
|
14530
|
+
formatTelegramUserMention,
|
|
14531
|
+
formatTelegramUser,
|
|
14532
|
+
formatTelegramChat,
|
|
14533
|
+
formatMediaCaption,
|
|
14534
|
+
escapeMarkdownV2,
|
|
14535
|
+
escapeHtmlAttr,
|
|
14536
|
+
escapeHtml,
|
|
13531
14537
|
src_default as default,
|
|
14538
|
+
chunkTelegramText,
|
|
13532
14539
|
chatStateProvider,
|
|
14540
|
+
buildTelegramSettings,
|
|
14541
|
+
buildTelegramMessageLink,
|
|
14542
|
+
buildTelegramDeepLink,
|
|
13533
14543
|
TelegramService,
|
|
14544
|
+
TelegramEventTypes,
|
|
14545
|
+
TELEGRAM_REACTIONS,
|
|
14546
|
+
SEND_REACTION_ACTION,
|
|
13534
14547
|
SEND_MESSAGE_ACTION,
|
|
13535
14548
|
MessageManager,
|
|
14549
|
+
DEFAULT_ACCOUNT_ID,
|
|
13536
14550
|
CHAT_STATE_PROVIDER
|
|
13537
14551
|
};
|
|
13538
14552
|
|
|
13539
|
-
//# debugId=
|
|
14553
|
+
//# debugId=5EB5738096CCF54A64756E2164756E21
|