claude-telegram-bot 0.3.15 → 0.3.18
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/README.ko.md +2 -0
- package/README.md +2 -0
- package/bot.mjs +19 -13
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/claude-telegram-bot)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
+
텔레그램으로 Claude Code를 — 어디서든, 어떤 기기에서도.
|
|
10
|
+
|
|
9
11
|
텔레그램으로 메시지를 보내면, 집이나 서버에 켜둔 Claude Code가 작업하고 결과를 다시 텔레그램으로 돌려주는 봇입니다.
|
|
10
12
|
|
|
11
13
|
```
|
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/claude-telegram-bot)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
+
Use Claude Code from Telegram — run it anywhere, from any device.
|
|
10
|
+
|
|
9
11
|
**A zero-dependency, single-file, daemonized Claude Code bot — no Bun, no Python, no open session.**
|
|
10
12
|
|
|
11
13
|
A tiny bridge that takes your Telegram messages, runs `claude -p` (Claude Code headless mode)
|
package/bot.mjs
CHANGED
|
@@ -114,6 +114,11 @@ if (!existsSync(CONFIG_PATH)) {
|
|
|
114
114
|
const cfg = JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
|
|
115
115
|
console.log({ ...cfg, token: cfg.token ? "<redacted>" : "(none)" });
|
|
116
116
|
const TG = `https://api.telegram.org/bot${cfg.token}`;
|
|
117
|
+
// allowedChatId 는 문자열 또는 배열 모두 허용 (하위 호환)
|
|
118
|
+
const allowedIds = []
|
|
119
|
+
.concat(cfg.allowedChatId)
|
|
120
|
+
.filter(Boolean)
|
|
121
|
+
.map(String);
|
|
117
122
|
|
|
118
123
|
// ── i18n (영어 기본 + 한국어) ─────────────────────────────────────────────
|
|
119
124
|
// cfg.lang 를 "en"/"ko" 로 주면 그 언어로 고정. 비우면 메시지의 from.language_code 로
|
|
@@ -354,7 +359,7 @@ function isNewer(latest, current) {
|
|
|
354
359
|
}
|
|
355
360
|
|
|
356
361
|
async function checkForUpdate() {
|
|
357
|
-
if (!
|
|
362
|
+
if (!allowedIds.length) return;
|
|
358
363
|
const now = Date.now();
|
|
359
364
|
if (state.lastVersionCheck && now - state.lastVersionCheck < VERSION_CHECK_INTERVAL) return;
|
|
360
365
|
const latest = await fetchLatestVersion();
|
|
@@ -364,9 +369,10 @@ async function checkForUpdate() {
|
|
|
364
369
|
if (state.notifiedVersion === latest) return; // 이미 알린 버전
|
|
365
370
|
state.notifiedVersion = latest;
|
|
366
371
|
saveState(state);
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
372
|
+
for (const id of allowedIds)
|
|
373
|
+
await send(id,
|
|
374
|
+
`✨ 업데이트가 있습니다: ${VERSION} → ${latest}\n\`npm i -g claude-telegram-bot\` 후 /restart`
|
|
375
|
+
).catch(() => {});
|
|
370
376
|
}
|
|
371
377
|
|
|
372
378
|
// ── 퍼시스턴트 메모리 ─────────────────────────────────────────────────────
|
|
@@ -553,9 +559,9 @@ function runClaude(prompt, sessionId, opts = {}) {
|
|
|
553
559
|
: null;
|
|
554
560
|
// opts.injectMemory: 퍼시스턴트 메모리를 시스템 프롬프트에 주입 (/new 로 초기화해도 유지)
|
|
555
561
|
const mem = opts.injectMemory ? loadMemory() : "";
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const appendSys = [cfg.persona, brevity, modelHint
|
|
562
|
+
// 메모리는 persona보다 앞에 배치하고 헤더를 강화 → persona가 덮어쓰는 것 방지
|
|
563
|
+
const memoryBlock = mem ? `## RULES (must follow before anything else)\n${mem}` : null;
|
|
564
|
+
const appendSys = [memoryBlock, cfg.persona, brevity, modelHint].filter(Boolean).join("\n\n");
|
|
559
565
|
if (appendSys) args.push("--append-system-prompt", appendSys);
|
|
560
566
|
if (model) args.push("--model", model);
|
|
561
567
|
if (sessionId) args.push("--resume", sessionId);
|
|
@@ -680,9 +686,9 @@ async function runScheduled(job) {
|
|
|
680
686
|
const footer = res.ok
|
|
681
687
|
? `\n\n— ⏰ ${label} · ${secs}s${res.cost ? ` · $${res.cost.toFixed(4)}` : ""}`
|
|
682
688
|
: `\n\n— ⏰ ${label}`;
|
|
683
|
-
await send(
|
|
689
|
+
for (const id of allowedIds) await send(id, (res.ok ? res.text : `⚠️ ${res.text}`) + footer);
|
|
684
690
|
} catch (e) {
|
|
685
|
-
await send(
|
|
691
|
+
for (const id of allowedIds) await send(id, t(BOT_LANG, "scheduledError", e.message));
|
|
686
692
|
} finally {
|
|
687
693
|
busy = false;
|
|
688
694
|
}
|
|
@@ -691,7 +697,7 @@ async function runScheduled(job) {
|
|
|
691
697
|
function startScheduler() {
|
|
692
698
|
// allowedChatId 없으면 결과를 보낼 곳이 없으니 비활성화. /cron add 로 나중에 작업이
|
|
693
699
|
// 늘 수 있으므로, schedule 이 지금 비어 있어도 인터벌은 항상 돌린다(없으면 no-op).
|
|
694
|
-
if (!
|
|
700
|
+
if (!allowedIds.length) {
|
|
695
701
|
console.warn("allowedChatId missing → scheduler disabled");
|
|
696
702
|
return;
|
|
697
703
|
}
|
|
@@ -822,7 +828,7 @@ async function downloadAttachment(att) {
|
|
|
822
828
|
const dir = ATTACH_DIR;
|
|
823
829
|
mkdirSync(dir, { recursive: true });
|
|
824
830
|
const ext = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")) : "";
|
|
825
|
-
const name = att.name || `tg-${att.fileId.slice(-
|
|
831
|
+
const name = att.name || `tg-${Date.now()}-${att.fileId.slice(-6)}${ext}`;
|
|
826
832
|
const dest = join(dir, name);
|
|
827
833
|
writeFileSync(dest, buf);
|
|
828
834
|
return { dest, name };
|
|
@@ -848,11 +854,11 @@ async function handle(msg) {
|
|
|
848
854
|
if (!text && !attachment && !msg._mediaGroup?.length) return;
|
|
849
855
|
|
|
850
856
|
// 화이트리스트
|
|
851
|
-
if (!
|
|
857
|
+
if (!allowedIds.length) {
|
|
852
858
|
await send(chatId, t(l, "needChatId", chatId));
|
|
853
859
|
return;
|
|
854
860
|
}
|
|
855
|
-
if (String(chatId)
|
|
861
|
+
if (!allowedIds.includes(String(chatId))) {
|
|
856
862
|
console.warn(`Ignoring unauthorized chatId ${chatId}`);
|
|
857
863
|
return;
|
|
858
864
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-telegram-bot",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.18",
|
|
4
4
|
"description": "Drive Claude Code from Telegram — messages run headless `claude -p` in a project dir and replies come back to the chat. Zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|