@fre4x/telegram 1.1.5 → 1.1.7
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 +310 -41
- 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;
|
|
@@ -28599,29 +28698,29 @@ function getStatePath() {
|
|
|
28599
28698
|
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
|
-
var botToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
28603
|
-
var
|
|
28604
|
-
|
|
28701
|
+
var botToken = process.env.TELEGRAM_BOT_TOKEN || process.env.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
|
+
}
|
|
28713
|
+
var allowedUserId = process.env.ALLOWED_USER_ID || process.env.TELEGRAM_ALLOWED_USER_ID || process.env.TELEGRAM_CHAT_ID || process.env.CHAT_ID;
|
|
28714
|
+
var rawAllowedRecipients = process.env.ALLOWED_RECIPIENTS || process.env.TELEGRAM_ALLOWED_RECIPIENTS;
|
|
28715
|
+
var allowedRecipients = rawAllowedRecipients?.split(",").map((id) => id.trim()).filter(Boolean) || [];
|
|
28605
28716
|
var enableRecipientWhitelist = process.env.ENABLE_RECIPIENT_WHITELIST === "true";
|
|
28606
28717
|
var originalError = console.error;
|
|
28607
28718
|
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
|
-
}
|
|
28719
|
+
const message = redactBotToken(args.map((arg) => String(arg)).join(" "));
|
|
28615
28720
|
originalError(message);
|
|
28616
28721
|
};
|
|
28617
28722
|
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
|
-
}
|
|
28723
|
+
const message = redactBotToken(err.stack || err.message);
|
|
28625
28724
|
console.error("Uncaught Exception:", message);
|
|
28626
28725
|
process.exit(1);
|
|
28627
28726
|
});
|
|
@@ -28630,13 +28729,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
28630
28729
|
if (reason instanceof Error) {
|
|
28631
28730
|
message = reason.stack || reason.message;
|
|
28632
28731
|
}
|
|
28633
|
-
|
|
28634
|
-
message = message.replace(
|
|
28635
|
-
new RegExp(botToken.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
|
|
28636
|
-
"[REDACTED_TOKEN]"
|
|
28637
|
-
);
|
|
28638
|
-
}
|
|
28639
|
-
console.error("Unhandled Rejection:", message);
|
|
28732
|
+
console.error("Unhandled Rejection:", redactBotToken(message));
|
|
28640
28733
|
});
|
|
28641
28734
|
if (!IS_MOCK && !botToken) {
|
|
28642
28735
|
console.error(
|
|
@@ -28730,14 +28823,16 @@ var server = new Server(
|
|
|
28730
28823
|
capabilities: {
|
|
28731
28824
|
tools: {},
|
|
28732
28825
|
logging: {},
|
|
28733
|
-
// Required by SDK for notifications/message
|
|
28734
28826
|
experimental: {
|
|
28735
28827
|
"claude/channel": {
|
|
28736
|
-
description: "Telegram events are delivered via channel notifications"
|
|
28828
|
+
description: "Telegram events are delivered via claude/channel notifications"
|
|
28829
|
+
},
|
|
28830
|
+
"claude/channel/permission": {
|
|
28831
|
+
description: "Tool approval requests are relayed to Telegram for allow/deny"
|
|
28737
28832
|
}
|
|
28738
28833
|
}
|
|
28739
28834
|
},
|
|
28740
|
-
instructions: "Telegram MCP server.
|
|
28835
|
+
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
28836
|
}
|
|
28742
28837
|
);
|
|
28743
28838
|
var isImage = (filePath) => {
|
|
@@ -28747,6 +28842,10 @@ var isImage = (filePath) => {
|
|
|
28747
28842
|
var messageHistory = [];
|
|
28748
28843
|
var MAX_HISTORY = 100;
|
|
28749
28844
|
var pollingOffset = 0;
|
|
28845
|
+
var channelReady = false;
|
|
28846
|
+
var channelPollTimer = null;
|
|
28847
|
+
var CHANNEL_POLL_INTERVAL_MS = 3e3;
|
|
28848
|
+
var pendingPermissionRequests = /* @__PURE__ */ new Map();
|
|
28750
28849
|
var knownChats = /* @__PURE__ */ new Map();
|
|
28751
28850
|
function loadState() {
|
|
28752
28851
|
if (IS_MOCK) return;
|
|
@@ -28766,7 +28865,10 @@ function loadState() {
|
|
|
28766
28865
|
`[telegram:state] loaded ${knownChats.size} chat(s) from ${getStatePath()}`
|
|
28767
28866
|
);
|
|
28768
28867
|
} catch (error48) {
|
|
28769
|
-
console.error(
|
|
28868
|
+
console.error(
|
|
28869
|
+
`[telegram:state] failed to load ${getStatePath()}:`,
|
|
28870
|
+
error48
|
|
28871
|
+
);
|
|
28770
28872
|
}
|
|
28771
28873
|
}
|
|
28772
28874
|
function persistState() {
|
|
@@ -28777,9 +28879,16 @@ function persistState() {
|
|
|
28777
28879
|
pollingOffset
|
|
28778
28880
|
};
|
|
28779
28881
|
fs.mkdirSync(path.dirname(getStatePath()), { recursive: true });
|
|
28780
|
-
fs.writeFileSync(
|
|
28882
|
+
fs.writeFileSync(
|
|
28883
|
+
getStatePath(),
|
|
28884
|
+
JSON.stringify(state, null, 2),
|
|
28885
|
+
"utf-8"
|
|
28886
|
+
);
|
|
28781
28887
|
} catch (error48) {
|
|
28782
|
-
console.error(
|
|
28888
|
+
console.error(
|
|
28889
|
+
`[telegram:state] failed to persist ${getStatePath()}:`,
|
|
28890
|
+
error48
|
|
28891
|
+
);
|
|
28783
28892
|
}
|
|
28784
28893
|
}
|
|
28785
28894
|
function reloadState() {
|
|
@@ -28797,7 +28906,10 @@ function reloadState() {
|
|
|
28797
28906
|
pollingOffset = state.pollingOffset;
|
|
28798
28907
|
}
|
|
28799
28908
|
} catch (error48) {
|
|
28800
|
-
console.error(
|
|
28909
|
+
console.error(
|
|
28910
|
+
`[telegram:state] failed to reload ${getStatePath()}:`,
|
|
28911
|
+
error48
|
|
28912
|
+
);
|
|
28801
28913
|
}
|
|
28802
28914
|
}
|
|
28803
28915
|
function chatTitleFromTelegramChat(chat) {
|
|
@@ -28955,17 +29067,23 @@ function getActiveChats() {
|
|
|
28955
29067
|
);
|
|
28956
29068
|
}
|
|
28957
29069
|
async function fetchNewUpdates() {
|
|
28958
|
-
|
|
29070
|
+
const added = [];
|
|
29071
|
+
if (!bot || IS_MOCK) return added;
|
|
28959
29072
|
try {
|
|
28960
29073
|
await ensurePollingMode();
|
|
28961
29074
|
const updates = await bot.telegram.getUpdates(0, 100, pollingOffset, [
|
|
28962
29075
|
"message",
|
|
28963
29076
|
"edited_message",
|
|
28964
29077
|
"channel_post",
|
|
28965
|
-
"my_chat_member"
|
|
29078
|
+
"my_chat_member",
|
|
29079
|
+
"callback_query"
|
|
28966
29080
|
]);
|
|
28967
29081
|
for (const update of updates) {
|
|
28968
29082
|
pollingOffset = update.update_id + 1;
|
|
29083
|
+
if (isCallbackQueryUpdate(update)) {
|
|
29084
|
+
await handlePermissionCallback(update.callback_query);
|
|
29085
|
+
continue;
|
|
29086
|
+
}
|
|
28969
29087
|
const msgLike = update;
|
|
28970
29088
|
if (!msgLike.message && !msgLike.edited_message && !msgLike.channel_post && !msgLike.my_chat_member)
|
|
28971
29089
|
continue;
|
|
@@ -28974,7 +29092,7 @@ async function fetchNewUpdates() {
|
|
|
28974
29092
|
if (!msg?.text) continue;
|
|
28975
29093
|
const senderId = msg.from?.id?.toString() ?? "unknown";
|
|
28976
29094
|
const chatId = msg.chat.id.toString();
|
|
28977
|
-
const chatTitle = msg.chat
|
|
29095
|
+
const chatTitle = chatTitleFromTelegramChat(msg.chat);
|
|
28978
29096
|
if (messageHistory.some(
|
|
28979
29097
|
(m) => m.metadata?.message_id === msg.message_id
|
|
28980
29098
|
))
|
|
@@ -28988,7 +29106,7 @@ async function fetchNewUpdates() {
|
|
|
28988
29106
|
ALLOWED_ATTR: []
|
|
28989
29107
|
});
|
|
28990
29108
|
content = content.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/[*_~]/g, "\\$&");
|
|
28991
|
-
|
|
29109
|
+
const entry = {
|
|
28992
29110
|
senderId,
|
|
28993
29111
|
chatId,
|
|
28994
29112
|
chatTitle,
|
|
@@ -28999,15 +29117,140 @@ async function fetchNewUpdates() {
|
|
|
28999
29117
|
chatType: msg.chat.type,
|
|
29000
29118
|
message_id: msg.message_id
|
|
29001
29119
|
}
|
|
29002
|
-
}
|
|
29120
|
+
};
|
|
29121
|
+
messageHistory.push(entry);
|
|
29122
|
+
added.push(entry);
|
|
29003
29123
|
if (messageHistory.length > MAX_HISTORY) {
|
|
29004
29124
|
messageHistory.shift();
|
|
29005
29125
|
}
|
|
29126
|
+
if (channelReady) {
|
|
29127
|
+
await pushMessageToChannel(entry);
|
|
29128
|
+
}
|
|
29006
29129
|
}
|
|
29007
29130
|
persistState();
|
|
29008
29131
|
} catch (error48) {
|
|
29009
29132
|
console.error("fetchNewUpdates failed:", error48);
|
|
29010
29133
|
}
|
|
29134
|
+
return added;
|
|
29135
|
+
}
|
|
29136
|
+
async function pushMessageToChannel(entry) {
|
|
29137
|
+
const meta3 = buildChannelMeta({
|
|
29138
|
+
chat_id: entry.chatId,
|
|
29139
|
+
sender_id: entry.senderId,
|
|
29140
|
+
sender_name: entry.chatTitle ?? entry.senderId,
|
|
29141
|
+
message_id: entry.metadata?.message_id,
|
|
29142
|
+
timestamp: entry.timestamp
|
|
29143
|
+
});
|
|
29144
|
+
const sent = await sendChannelNotification(server, entry.content, meta3);
|
|
29145
|
+
if (sent) {
|
|
29146
|
+
console.error(
|
|
29147
|
+
`[telegram:channel] pushed message_id=${entry.metadata?.message_id ?? "unknown"} chat_id=${entry.chatId}`
|
|
29148
|
+
);
|
|
29149
|
+
}
|
|
29150
|
+
}
|
|
29151
|
+
async function relayPermissionRequestToTelegram(params) {
|
|
29152
|
+
pendingPermissionRequests.set(params.request_id, params);
|
|
29153
|
+
if (IS_MOCK || !bot) {
|
|
29154
|
+
console.error(
|
|
29155
|
+
`[telegram:channel] permission request (mock): ${params.tool_name} (${params.request_id})`
|
|
29156
|
+
);
|
|
29157
|
+
return;
|
|
29158
|
+
}
|
|
29159
|
+
const targetId = allowedUserId;
|
|
29160
|
+
if (!targetId) {
|
|
29161
|
+
console.error(
|
|
29162
|
+
"[telegram:channel] cannot relay permission \u2014 ALLOWED_USER_ID not set"
|
|
29163
|
+
);
|
|
29164
|
+
return;
|
|
29165
|
+
}
|
|
29166
|
+
try {
|
|
29167
|
+
await bot.telegram.sendMessage(
|
|
29168
|
+
targetId,
|
|
29169
|
+
formatPermissionRequestMessage(params),
|
|
29170
|
+
{
|
|
29171
|
+
reply_markup: {
|
|
29172
|
+
inline_keyboard: [
|
|
29173
|
+
[
|
|
29174
|
+
{
|
|
29175
|
+
text: "Allow",
|
|
29176
|
+
callback_data: buildPermissionCallbackData(
|
|
29177
|
+
"allow",
|
|
29178
|
+
params.request_id
|
|
29179
|
+
)
|
|
29180
|
+
},
|
|
29181
|
+
{
|
|
29182
|
+
text: "Deny",
|
|
29183
|
+
callback_data: buildPermissionCallbackData(
|
|
29184
|
+
"deny",
|
|
29185
|
+
params.request_id
|
|
29186
|
+
)
|
|
29187
|
+
}
|
|
29188
|
+
]
|
|
29189
|
+
]
|
|
29190
|
+
}
|
|
29191
|
+
}
|
|
29192
|
+
);
|
|
29193
|
+
} catch (error48) {
|
|
29194
|
+
console.error(
|
|
29195
|
+
"[telegram:channel] failed to relay permission request:",
|
|
29196
|
+
error48
|
|
29197
|
+
);
|
|
29198
|
+
}
|
|
29199
|
+
}
|
|
29200
|
+
async function handlePermissionCallback(callbackQuery) {
|
|
29201
|
+
if (!callbackQuery.data) return;
|
|
29202
|
+
const parsed = parsePermissionCallbackData(callbackQuery.data);
|
|
29203
|
+
if (!parsed) return;
|
|
29204
|
+
const currentAllowedUserId = process.env.ALLOWED_USER_ID;
|
|
29205
|
+
if (currentAllowedUserId && callbackQuery.from) {
|
|
29206
|
+
if (callbackQuery.from.id.toString() !== currentAllowedUserId) {
|
|
29207
|
+
console.error(
|
|
29208
|
+
`[telegram:channel] permission callback rejected from ${callbackQuery.from.id}`
|
|
29209
|
+
);
|
|
29210
|
+
return;
|
|
29211
|
+
}
|
|
29212
|
+
}
|
|
29213
|
+
if (!pendingPermissionRequests.has(parsed.requestId)) {
|
|
29214
|
+
console.error(
|
|
29215
|
+
`[telegram:channel] unknown permission request_id=${parsed.requestId}`
|
|
29216
|
+
);
|
|
29217
|
+
return;
|
|
29218
|
+
}
|
|
29219
|
+
pendingPermissionRequests.delete(parsed.requestId);
|
|
29220
|
+
const sent = await sendPermissionVerdict(
|
|
29221
|
+
server,
|
|
29222
|
+
parsed.requestId,
|
|
29223
|
+
parsed.behavior
|
|
29224
|
+
);
|
|
29225
|
+
if (sent) {
|
|
29226
|
+
console.error(
|
|
29227
|
+
`[telegram:channel] permission verdict ${parsed.behavior} for ${parsed.requestId}`
|
|
29228
|
+
);
|
|
29229
|
+
}
|
|
29230
|
+
if (bot && !IS_MOCK) {
|
|
29231
|
+
try {
|
|
29232
|
+
await bot.telegram.answerCbQuery(
|
|
29233
|
+
callbackQuery.id,
|
|
29234
|
+
parsed.behavior === "allow" ? "Approved" : "Denied"
|
|
29235
|
+
);
|
|
29236
|
+
} catch (error48) {
|
|
29237
|
+
console.error("[telegram:channel] answerCbQuery failed:", error48);
|
|
29238
|
+
}
|
|
29239
|
+
}
|
|
29240
|
+
}
|
|
29241
|
+
function startChannelPolling() {
|
|
29242
|
+
if (channelPollTimer || IS_MOCK || !bot) return;
|
|
29243
|
+
channelPollTimer = setInterval(() => {
|
|
29244
|
+
void fetchNewUpdates();
|
|
29245
|
+
}, CHANNEL_POLL_INTERVAL_MS);
|
|
29246
|
+
console.error(
|
|
29247
|
+
`[telegram:channel] background polling started (${CHANNEL_POLL_INTERVAL_MS}ms)`
|
|
29248
|
+
);
|
|
29249
|
+
}
|
|
29250
|
+
function stopChannelPolling() {
|
|
29251
|
+
if (!channelPollTimer) return;
|
|
29252
|
+
clearInterval(channelPollTimer);
|
|
29253
|
+
channelPollTimer = null;
|
|
29011
29254
|
}
|
|
29012
29255
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
29013
29256
|
return {
|
|
@@ -29129,9 +29372,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
29129
29372
|
const source = { source: safePath };
|
|
29130
29373
|
const isPhoto = mediaType === "photo" || !mediaType && isImage(safePath);
|
|
29131
29374
|
if (isPhoto) {
|
|
29132
|
-
const sent = await bot.telegram.sendPhoto(
|
|
29133
|
-
|
|
29134
|
-
|
|
29375
|
+
const sent = await bot.telegram.sendPhoto(
|
|
29376
|
+
targetId,
|
|
29377
|
+
source,
|
|
29378
|
+
{
|
|
29379
|
+
caption: content
|
|
29380
|
+
}
|
|
29381
|
+
);
|
|
29135
29382
|
recordKnownChatFromTelegramMessage(sent);
|
|
29136
29383
|
} else {
|
|
29137
29384
|
const sent = await bot.telegram.sendDocument(
|
|
@@ -29299,12 +29546,34 @@ ${formatPaginationFooter(offset, limit, activeChats.length)}` : "No active chats
|
|
|
29299
29546
|
);
|
|
29300
29547
|
}
|
|
29301
29548
|
});
|
|
29549
|
+
server.setNotificationHandler(
|
|
29550
|
+
ChannelPermissionRequestNotificationSchema,
|
|
29551
|
+
async (notification) => {
|
|
29552
|
+
await relayPermissionRequestToTelegram(notification.params);
|
|
29553
|
+
}
|
|
29554
|
+
);
|
|
29555
|
+
server.oninitialized = () => {
|
|
29556
|
+
channelReady = true;
|
|
29557
|
+
console.error(
|
|
29558
|
+
"[telegram:channel] client initialized \u2014 channel push enabled"
|
|
29559
|
+
);
|
|
29560
|
+
startChannelPolling();
|
|
29561
|
+
};
|
|
29302
29562
|
async function run() {
|
|
29303
29563
|
loadState();
|
|
29304
29564
|
const transport = new StdioServerTransport();
|
|
29305
29565
|
await server.connect(transport);
|
|
29306
29566
|
console.error("Telegram MCP Server running on stdio");
|
|
29567
|
+
if (!IS_MOCK && bot) {
|
|
29568
|
+
void discoverChatsFromApi();
|
|
29569
|
+
}
|
|
29307
29570
|
}
|
|
29571
|
+
process.on("SIGINT", () => {
|
|
29572
|
+
stopChannelPolling();
|
|
29573
|
+
});
|
|
29574
|
+
process.on("SIGTERM", () => {
|
|
29575
|
+
stopChannelPolling();
|
|
29576
|
+
});
|
|
29308
29577
|
if (process.env.NODE_ENV !== "test") {
|
|
29309
29578
|
run().catch((error48) => {
|
|
29310
29579
|
console.error("Fatal error in run():", error48);
|
package/package.json
CHANGED