@fre4x/telegram 1.1.5 → 1.1.6
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 +303 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28236,9 +28236,9 @@ var StdioServerTransport = class {
|
|
|
28236
28236
|
var import_dotenv = __toESM(require_main(), 1);
|
|
28237
28237
|
import { Telegraf } from "telegraf";
|
|
28238
28238
|
import { createHash } from "node:crypto";
|
|
28239
|
-
import * as fs from "fs";
|
|
28239
|
+
import * as fs from "node:fs";
|
|
28240
28240
|
import os from "node:os";
|
|
28241
|
-
import * as path from "path";
|
|
28241
|
+
import * as path from "node:path";
|
|
28242
28242
|
|
|
28243
28243
|
// ../node_modules/zod/index.js
|
|
28244
28244
|
var zod_exports = {};
|
|
@@ -28587,8 +28587,107 @@ function applyPagination(items, params) {
|
|
|
28587
28587
|
};
|
|
28588
28588
|
}
|
|
28589
28589
|
|
|
28590
|
+
// src/channel.ts
|
|
28591
|
+
var MAX_CHANNEL_CONTENT_BYTES = 8192;
|
|
28592
|
+
var ChannelPermissionRequestNotificationSchema = external_exports3.object({
|
|
28593
|
+
method: external_exports3.literal("notifications/claude/channel/permission_request"),
|
|
28594
|
+
params: external_exports3.object({
|
|
28595
|
+
request_id: external_exports3.string().min(1),
|
|
28596
|
+
tool_name: external_exports3.string(),
|
|
28597
|
+
description: external_exports3.string(),
|
|
28598
|
+
input_preview: external_exports3.string().optional()
|
|
28599
|
+
})
|
|
28600
|
+
});
|
|
28601
|
+
function coerceMetaValue(value) {
|
|
28602
|
+
if (value === null || value === void 0) return "";
|
|
28603
|
+
if (typeof value === "string") return value;
|
|
28604
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
28605
|
+
return String(value);
|
|
28606
|
+
}
|
|
28607
|
+
return JSON.stringify(value);
|
|
28608
|
+
}
|
|
28609
|
+
function buildChannelMeta(meta3) {
|
|
28610
|
+
const result = {};
|
|
28611
|
+
for (const [key, value] of Object.entries(meta3)) {
|
|
28612
|
+
result[key] = coerceMetaValue(value);
|
|
28613
|
+
}
|
|
28614
|
+
return result;
|
|
28615
|
+
}
|
|
28616
|
+
function truncateChannelContent(content) {
|
|
28617
|
+
const bytes = Buffer.byteLength(content, "utf8");
|
|
28618
|
+
if (bytes > MAX_CHANNEL_CONTENT_BYTES) {
|
|
28619
|
+
console.error(
|
|
28620
|
+
`[telegram:channel] dropping message (${bytes} bytes > ${MAX_CHANNEL_CONTENT_BYTES})`
|
|
28621
|
+
);
|
|
28622
|
+
return null;
|
|
28623
|
+
}
|
|
28624
|
+
return content;
|
|
28625
|
+
}
|
|
28626
|
+
async function sendChannelNotification(server2, content, meta3) {
|
|
28627
|
+
const safeContent = truncateChannelContent(content);
|
|
28628
|
+
if (!safeContent) return false;
|
|
28629
|
+
try {
|
|
28630
|
+
await server2.notification({
|
|
28631
|
+
method: "claude/channel",
|
|
28632
|
+
params: {
|
|
28633
|
+
content: safeContent,
|
|
28634
|
+
meta: meta3 ?? {}
|
|
28635
|
+
}
|
|
28636
|
+
});
|
|
28637
|
+
return true;
|
|
28638
|
+
} catch (error48) {
|
|
28639
|
+
console.error("[telegram:channel] failed to send notification:", error48);
|
|
28640
|
+
return false;
|
|
28641
|
+
}
|
|
28642
|
+
}
|
|
28643
|
+
async function sendPermissionVerdict(server2, requestId, behavior) {
|
|
28644
|
+
try {
|
|
28645
|
+
await server2.notification({
|
|
28646
|
+
method: "claude/channel/permission",
|
|
28647
|
+
params: {
|
|
28648
|
+
request_id: requestId,
|
|
28649
|
+
behavior
|
|
28650
|
+
}
|
|
28651
|
+
});
|
|
28652
|
+
return true;
|
|
28653
|
+
} catch (error48) {
|
|
28654
|
+
console.error(
|
|
28655
|
+
`[telegram:channel] failed to send permission verdict (${behavior}):`,
|
|
28656
|
+
error48
|
|
28657
|
+
);
|
|
28658
|
+
return false;
|
|
28659
|
+
}
|
|
28660
|
+
}
|
|
28661
|
+
function formatPermissionRequestMessage(params) {
|
|
28662
|
+
const preview = params.input_preview?.trim();
|
|
28663
|
+
const lines = [
|
|
28664
|
+
"Tool approval requested",
|
|
28665
|
+
"",
|
|
28666
|
+
`Tool: ${params.tool_name}`,
|
|
28667
|
+
params.description
|
|
28668
|
+
];
|
|
28669
|
+
if (preview) {
|
|
28670
|
+
lines.push("", "Preview:", preview);
|
|
28671
|
+
}
|
|
28672
|
+
return lines.join("\n");
|
|
28673
|
+
}
|
|
28674
|
+
function parsePermissionCallbackData(data) {
|
|
28675
|
+
const match = /^perm:(allow|deny):([a-f0-9]{32})$/.exec(data);
|
|
28676
|
+
if (!match) return null;
|
|
28677
|
+
return {
|
|
28678
|
+
behavior: match[1],
|
|
28679
|
+
requestId: match[2]
|
|
28680
|
+
};
|
|
28681
|
+
}
|
|
28682
|
+
function buildPermissionCallbackData(behavior, requestId) {
|
|
28683
|
+
return `perm:${behavior}:${requestId}`;
|
|
28684
|
+
}
|
|
28685
|
+
|
|
28590
28686
|
// src/index.ts
|
|
28591
28687
|
import_dotenv.default.config();
|
|
28688
|
+
function isCallbackQueryUpdate(update) {
|
|
28689
|
+
return typeof update === "object" && update !== null && "callback_query" in update && update.callback_query !== void 0;
|
|
28690
|
+
}
|
|
28592
28691
|
function getStatePath() {
|
|
28593
28692
|
if (process.env.TELEGRAM_STATE_PATH) {
|
|
28594
28693
|
return process.env.TELEGRAM_STATE_PATH;
|
|
@@ -28600,28 +28699,27 @@ var window = new JSDOM("").window;
|
|
|
28600
28699
|
var DOMPurify = createDOMPurify(window);
|
|
28601
28700
|
var IS_MOCK = process.env.MOCK === "true" || process.env.TELEGRAM_MOCK === "true";
|
|
28602
28701
|
var botToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
28702
|
+
var MAX_TOKEN_REDACT_LENGTH = 256;
|
|
28703
|
+
function redactBotToken(message) {
|
|
28704
|
+
if (!botToken || !message.includes(botToken)) {
|
|
28705
|
+
return message;
|
|
28706
|
+
}
|
|
28707
|
+
if (botToken.length > MAX_TOKEN_REDACT_LENGTH) {
|
|
28708
|
+
return message.split(botToken).join("[REDACTED_TOKEN]");
|
|
28709
|
+
}
|
|
28710
|
+
const escapedToken = botToken.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28711
|
+
return message.replace(new RegExp(escapedToken, "g"), "[REDACTED_TOKEN]");
|
|
28712
|
+
}
|
|
28603
28713
|
var allowedUserId = process.env.ALLOWED_USER_ID;
|
|
28604
28714
|
var allowedRecipients = process.env.ALLOWED_RECIPIENTS?.split(",").map((id) => id.trim()) || [];
|
|
28605
28715
|
var enableRecipientWhitelist = process.env.ENABLE_RECIPIENT_WHITELIST === "true";
|
|
28606
28716
|
var originalError = console.error;
|
|
28607
28717
|
console.error = (...args) => {
|
|
28608
|
-
|
|
28609
|
-
if (botToken && message.includes(botToken)) {
|
|
28610
|
-
message = message.replace(
|
|
28611
|
-
new RegExp(botToken.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
|
|
28612
|
-
"[REDACTED_TOKEN]"
|
|
28613
|
-
);
|
|
28614
|
-
}
|
|
28718
|
+
const message = redactBotToken(args.map((arg) => String(arg)).join(" "));
|
|
28615
28719
|
originalError(message);
|
|
28616
28720
|
};
|
|
28617
28721
|
process.on("uncaughtException", (err) => {
|
|
28618
|
-
|
|
28619
|
-
if (botToken && message.includes(botToken)) {
|
|
28620
|
-
message = message.replace(
|
|
28621
|
-
new RegExp(botToken.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
|
|
28622
|
-
"[REDACTED_TOKEN]"
|
|
28623
|
-
);
|
|
28624
|
-
}
|
|
28722
|
+
const message = redactBotToken(err.stack || err.message);
|
|
28625
28723
|
console.error("Uncaught Exception:", message);
|
|
28626
28724
|
process.exit(1);
|
|
28627
28725
|
});
|
|
@@ -28630,13 +28728,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
28630
28728
|
if (reason instanceof Error) {
|
|
28631
28729
|
message = reason.stack || reason.message;
|
|
28632
28730
|
}
|
|
28633
|
-
|
|
28634
|
-
message = message.replace(
|
|
28635
|
-
new RegExp(botToken.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
|
|
28636
|
-
"[REDACTED_TOKEN]"
|
|
28637
|
-
);
|
|
28638
|
-
}
|
|
28639
|
-
console.error("Unhandled Rejection:", message);
|
|
28731
|
+
console.error("Unhandled Rejection:", redactBotToken(message));
|
|
28640
28732
|
});
|
|
28641
28733
|
if (!IS_MOCK && !botToken) {
|
|
28642
28734
|
console.error(
|
|
@@ -28730,14 +28822,16 @@ var server = new Server(
|
|
|
28730
28822
|
capabilities: {
|
|
28731
28823
|
tools: {},
|
|
28732
28824
|
logging: {},
|
|
28733
|
-
// Required by SDK for notifications/message
|
|
28734
28825
|
experimental: {
|
|
28735
28826
|
"claude/channel": {
|
|
28736
|
-
description: "Telegram events are delivered via channel notifications"
|
|
28827
|
+
description: "Telegram events are delivered via claude/channel notifications"
|
|
28828
|
+
},
|
|
28829
|
+
"claude/channel/permission": {
|
|
28830
|
+
description: "Tool approval requests are relayed to Telegram for allow/deny"
|
|
28737
28831
|
}
|
|
28738
28832
|
}
|
|
28739
28833
|
},
|
|
28740
|
-
instructions: "Telegram MCP server.
|
|
28834
|
+
instructions: "Telegram MCP server. Inbound Telegram messages are pushed via claude/channel. Tool approvals can be relayed through Telegram when claude/channel/permission is enabled."
|
|
28741
28835
|
}
|
|
28742
28836
|
);
|
|
28743
28837
|
var isImage = (filePath) => {
|
|
@@ -28747,6 +28841,10 @@ var isImage = (filePath) => {
|
|
|
28747
28841
|
var messageHistory = [];
|
|
28748
28842
|
var MAX_HISTORY = 100;
|
|
28749
28843
|
var pollingOffset = 0;
|
|
28844
|
+
var channelReady = false;
|
|
28845
|
+
var channelPollTimer = null;
|
|
28846
|
+
var CHANNEL_POLL_INTERVAL_MS = 3e3;
|
|
28847
|
+
var pendingPermissionRequests = /* @__PURE__ */ new Map();
|
|
28750
28848
|
var knownChats = /* @__PURE__ */ new Map();
|
|
28751
28849
|
function loadState() {
|
|
28752
28850
|
if (IS_MOCK) return;
|
|
@@ -28766,7 +28864,10 @@ function loadState() {
|
|
|
28766
28864
|
`[telegram:state] loaded ${knownChats.size} chat(s) from ${getStatePath()}`
|
|
28767
28865
|
);
|
|
28768
28866
|
} catch (error48) {
|
|
28769
|
-
console.error(
|
|
28867
|
+
console.error(
|
|
28868
|
+
`[telegram:state] failed to load ${getStatePath()}:`,
|
|
28869
|
+
error48
|
|
28870
|
+
);
|
|
28770
28871
|
}
|
|
28771
28872
|
}
|
|
28772
28873
|
function persistState() {
|
|
@@ -28777,9 +28878,16 @@ function persistState() {
|
|
|
28777
28878
|
pollingOffset
|
|
28778
28879
|
};
|
|
28779
28880
|
fs.mkdirSync(path.dirname(getStatePath()), { recursive: true });
|
|
28780
|
-
fs.writeFileSync(
|
|
28881
|
+
fs.writeFileSync(
|
|
28882
|
+
getStatePath(),
|
|
28883
|
+
JSON.stringify(state, null, 2),
|
|
28884
|
+
"utf-8"
|
|
28885
|
+
);
|
|
28781
28886
|
} catch (error48) {
|
|
28782
|
-
console.error(
|
|
28887
|
+
console.error(
|
|
28888
|
+
`[telegram:state] failed to persist ${getStatePath()}:`,
|
|
28889
|
+
error48
|
|
28890
|
+
);
|
|
28783
28891
|
}
|
|
28784
28892
|
}
|
|
28785
28893
|
function reloadState() {
|
|
@@ -28797,7 +28905,10 @@ function reloadState() {
|
|
|
28797
28905
|
pollingOffset = state.pollingOffset;
|
|
28798
28906
|
}
|
|
28799
28907
|
} catch (error48) {
|
|
28800
|
-
console.error(
|
|
28908
|
+
console.error(
|
|
28909
|
+
`[telegram:state] failed to reload ${getStatePath()}:`,
|
|
28910
|
+
error48
|
|
28911
|
+
);
|
|
28801
28912
|
}
|
|
28802
28913
|
}
|
|
28803
28914
|
function chatTitleFromTelegramChat(chat) {
|
|
@@ -28955,17 +29066,23 @@ function getActiveChats() {
|
|
|
28955
29066
|
);
|
|
28956
29067
|
}
|
|
28957
29068
|
async function fetchNewUpdates() {
|
|
28958
|
-
|
|
29069
|
+
const added = [];
|
|
29070
|
+
if (!bot || IS_MOCK) return added;
|
|
28959
29071
|
try {
|
|
28960
29072
|
await ensurePollingMode();
|
|
28961
29073
|
const updates = await bot.telegram.getUpdates(0, 100, pollingOffset, [
|
|
28962
29074
|
"message",
|
|
28963
29075
|
"edited_message",
|
|
28964
29076
|
"channel_post",
|
|
28965
|
-
"my_chat_member"
|
|
29077
|
+
"my_chat_member",
|
|
29078
|
+
"callback_query"
|
|
28966
29079
|
]);
|
|
28967
29080
|
for (const update of updates) {
|
|
28968
29081
|
pollingOffset = update.update_id + 1;
|
|
29082
|
+
if (isCallbackQueryUpdate(update)) {
|
|
29083
|
+
await handlePermissionCallback(update.callback_query);
|
|
29084
|
+
continue;
|
|
29085
|
+
}
|
|
28969
29086
|
const msgLike = update;
|
|
28970
29087
|
if (!msgLike.message && !msgLike.edited_message && !msgLike.channel_post && !msgLike.my_chat_member)
|
|
28971
29088
|
continue;
|
|
@@ -28974,7 +29091,7 @@ async function fetchNewUpdates() {
|
|
|
28974
29091
|
if (!msg?.text) continue;
|
|
28975
29092
|
const senderId = msg.from?.id?.toString() ?? "unknown";
|
|
28976
29093
|
const chatId = msg.chat.id.toString();
|
|
28977
|
-
const chatTitle = msg.chat
|
|
29094
|
+
const chatTitle = chatTitleFromTelegramChat(msg.chat);
|
|
28978
29095
|
if (messageHistory.some(
|
|
28979
29096
|
(m) => m.metadata?.message_id === msg.message_id
|
|
28980
29097
|
))
|
|
@@ -28988,7 +29105,7 @@ async function fetchNewUpdates() {
|
|
|
28988
29105
|
ALLOWED_ATTR: []
|
|
28989
29106
|
});
|
|
28990
29107
|
content = content.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/[*_~]/g, "\\$&");
|
|
28991
|
-
|
|
29108
|
+
const entry = {
|
|
28992
29109
|
senderId,
|
|
28993
29110
|
chatId,
|
|
28994
29111
|
chatTitle,
|
|
@@ -28999,15 +29116,140 @@ async function fetchNewUpdates() {
|
|
|
28999
29116
|
chatType: msg.chat.type,
|
|
29000
29117
|
message_id: msg.message_id
|
|
29001
29118
|
}
|
|
29002
|
-
}
|
|
29119
|
+
};
|
|
29120
|
+
messageHistory.push(entry);
|
|
29121
|
+
added.push(entry);
|
|
29003
29122
|
if (messageHistory.length > MAX_HISTORY) {
|
|
29004
29123
|
messageHistory.shift();
|
|
29005
29124
|
}
|
|
29125
|
+
if (channelReady) {
|
|
29126
|
+
await pushMessageToChannel(entry);
|
|
29127
|
+
}
|
|
29006
29128
|
}
|
|
29007
29129
|
persistState();
|
|
29008
29130
|
} catch (error48) {
|
|
29009
29131
|
console.error("fetchNewUpdates failed:", error48);
|
|
29010
29132
|
}
|
|
29133
|
+
return added;
|
|
29134
|
+
}
|
|
29135
|
+
async function pushMessageToChannel(entry) {
|
|
29136
|
+
const meta3 = buildChannelMeta({
|
|
29137
|
+
chat_id: entry.chatId,
|
|
29138
|
+
sender_id: entry.senderId,
|
|
29139
|
+
sender_name: entry.chatTitle ?? entry.senderId,
|
|
29140
|
+
message_id: entry.metadata?.message_id,
|
|
29141
|
+
timestamp: entry.timestamp
|
|
29142
|
+
});
|
|
29143
|
+
const sent = await sendChannelNotification(server, entry.content, meta3);
|
|
29144
|
+
if (sent) {
|
|
29145
|
+
console.error(
|
|
29146
|
+
`[telegram:channel] pushed message_id=${entry.metadata?.message_id ?? "unknown"} chat_id=${entry.chatId}`
|
|
29147
|
+
);
|
|
29148
|
+
}
|
|
29149
|
+
}
|
|
29150
|
+
async function relayPermissionRequestToTelegram(params) {
|
|
29151
|
+
pendingPermissionRequests.set(params.request_id, params);
|
|
29152
|
+
if (IS_MOCK || !bot) {
|
|
29153
|
+
console.error(
|
|
29154
|
+
`[telegram:channel] permission request (mock): ${params.tool_name} (${params.request_id})`
|
|
29155
|
+
);
|
|
29156
|
+
return;
|
|
29157
|
+
}
|
|
29158
|
+
const targetId = allowedUserId;
|
|
29159
|
+
if (!targetId) {
|
|
29160
|
+
console.error(
|
|
29161
|
+
"[telegram:channel] cannot relay permission \u2014 ALLOWED_USER_ID not set"
|
|
29162
|
+
);
|
|
29163
|
+
return;
|
|
29164
|
+
}
|
|
29165
|
+
try {
|
|
29166
|
+
await bot.telegram.sendMessage(
|
|
29167
|
+
targetId,
|
|
29168
|
+
formatPermissionRequestMessage(params),
|
|
29169
|
+
{
|
|
29170
|
+
reply_markup: {
|
|
29171
|
+
inline_keyboard: [
|
|
29172
|
+
[
|
|
29173
|
+
{
|
|
29174
|
+
text: "Allow",
|
|
29175
|
+
callback_data: buildPermissionCallbackData(
|
|
29176
|
+
"allow",
|
|
29177
|
+
params.request_id
|
|
29178
|
+
)
|
|
29179
|
+
},
|
|
29180
|
+
{
|
|
29181
|
+
text: "Deny",
|
|
29182
|
+
callback_data: buildPermissionCallbackData(
|
|
29183
|
+
"deny",
|
|
29184
|
+
params.request_id
|
|
29185
|
+
)
|
|
29186
|
+
}
|
|
29187
|
+
]
|
|
29188
|
+
]
|
|
29189
|
+
}
|
|
29190
|
+
}
|
|
29191
|
+
);
|
|
29192
|
+
} catch (error48) {
|
|
29193
|
+
console.error(
|
|
29194
|
+
"[telegram:channel] failed to relay permission request:",
|
|
29195
|
+
error48
|
|
29196
|
+
);
|
|
29197
|
+
}
|
|
29198
|
+
}
|
|
29199
|
+
async function handlePermissionCallback(callbackQuery) {
|
|
29200
|
+
if (!callbackQuery.data) return;
|
|
29201
|
+
const parsed = parsePermissionCallbackData(callbackQuery.data);
|
|
29202
|
+
if (!parsed) return;
|
|
29203
|
+
const currentAllowedUserId = process.env.ALLOWED_USER_ID;
|
|
29204
|
+
if (currentAllowedUserId && callbackQuery.from) {
|
|
29205
|
+
if (callbackQuery.from.id.toString() !== currentAllowedUserId) {
|
|
29206
|
+
console.error(
|
|
29207
|
+
`[telegram:channel] permission callback rejected from ${callbackQuery.from.id}`
|
|
29208
|
+
);
|
|
29209
|
+
return;
|
|
29210
|
+
}
|
|
29211
|
+
}
|
|
29212
|
+
if (!pendingPermissionRequests.has(parsed.requestId)) {
|
|
29213
|
+
console.error(
|
|
29214
|
+
`[telegram:channel] unknown permission request_id=${parsed.requestId}`
|
|
29215
|
+
);
|
|
29216
|
+
return;
|
|
29217
|
+
}
|
|
29218
|
+
pendingPermissionRequests.delete(parsed.requestId);
|
|
29219
|
+
const sent = await sendPermissionVerdict(
|
|
29220
|
+
server,
|
|
29221
|
+
parsed.requestId,
|
|
29222
|
+
parsed.behavior
|
|
29223
|
+
);
|
|
29224
|
+
if (sent) {
|
|
29225
|
+
console.error(
|
|
29226
|
+
`[telegram:channel] permission verdict ${parsed.behavior} for ${parsed.requestId}`
|
|
29227
|
+
);
|
|
29228
|
+
}
|
|
29229
|
+
if (bot && !IS_MOCK) {
|
|
29230
|
+
try {
|
|
29231
|
+
await bot.telegram.answerCbQuery(
|
|
29232
|
+
callbackQuery.id,
|
|
29233
|
+
parsed.behavior === "allow" ? "Approved" : "Denied"
|
|
29234
|
+
);
|
|
29235
|
+
} catch (error48) {
|
|
29236
|
+
console.error("[telegram:channel] answerCbQuery failed:", error48);
|
|
29237
|
+
}
|
|
29238
|
+
}
|
|
29239
|
+
}
|
|
29240
|
+
function startChannelPolling() {
|
|
29241
|
+
if (channelPollTimer || IS_MOCK || !bot) return;
|
|
29242
|
+
channelPollTimer = setInterval(() => {
|
|
29243
|
+
void fetchNewUpdates();
|
|
29244
|
+
}, CHANNEL_POLL_INTERVAL_MS);
|
|
29245
|
+
console.error(
|
|
29246
|
+
`[telegram:channel] background polling started (${CHANNEL_POLL_INTERVAL_MS}ms)`
|
|
29247
|
+
);
|
|
29248
|
+
}
|
|
29249
|
+
function stopChannelPolling() {
|
|
29250
|
+
if (!channelPollTimer) return;
|
|
29251
|
+
clearInterval(channelPollTimer);
|
|
29252
|
+
channelPollTimer = null;
|
|
29011
29253
|
}
|
|
29012
29254
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
29013
29255
|
return {
|
|
@@ -29129,9 +29371,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
29129
29371
|
const source = { source: safePath };
|
|
29130
29372
|
const isPhoto = mediaType === "photo" || !mediaType && isImage(safePath);
|
|
29131
29373
|
if (isPhoto) {
|
|
29132
|
-
const sent = await bot.telegram.sendPhoto(
|
|
29133
|
-
|
|
29134
|
-
|
|
29374
|
+
const sent = await bot.telegram.sendPhoto(
|
|
29375
|
+
targetId,
|
|
29376
|
+
source,
|
|
29377
|
+
{
|
|
29378
|
+
caption: content
|
|
29379
|
+
}
|
|
29380
|
+
);
|
|
29135
29381
|
recordKnownChatFromTelegramMessage(sent);
|
|
29136
29382
|
} else {
|
|
29137
29383
|
const sent = await bot.telegram.sendDocument(
|
|
@@ -29299,12 +29545,31 @@ ${formatPaginationFooter(offset, limit, activeChats.length)}` : "No active chats
|
|
|
29299
29545
|
);
|
|
29300
29546
|
}
|
|
29301
29547
|
});
|
|
29548
|
+
server.setNotificationHandler(
|
|
29549
|
+
ChannelPermissionRequestNotificationSchema,
|
|
29550
|
+
async (notification) => {
|
|
29551
|
+
await relayPermissionRequestToTelegram(notification.params);
|
|
29552
|
+
}
|
|
29553
|
+
);
|
|
29554
|
+
server.oninitialized = () => {
|
|
29555
|
+
channelReady = true;
|
|
29556
|
+
console.error(
|
|
29557
|
+
"[telegram:channel] client initialized \u2014 channel push enabled"
|
|
29558
|
+
);
|
|
29559
|
+
startChannelPolling();
|
|
29560
|
+
};
|
|
29302
29561
|
async function run() {
|
|
29303
29562
|
loadState();
|
|
29304
29563
|
const transport = new StdioServerTransport();
|
|
29305
29564
|
await server.connect(transport);
|
|
29306
29565
|
console.error("Telegram MCP Server running on stdio");
|
|
29307
29566
|
}
|
|
29567
|
+
process.on("SIGINT", () => {
|
|
29568
|
+
stopChannelPolling();
|
|
29569
|
+
});
|
|
29570
|
+
process.on("SIGTERM", () => {
|
|
29571
|
+
stopChannelPolling();
|
|
29572
|
+
});
|
|
29308
29573
|
if (process.env.NODE_ENV !== "test") {
|
|
29309
29574
|
run().catch((error48) => {
|
|
29310
29575
|
console.error("Fatal error in run():", error48);
|
package/package.json
CHANGED