claude-telegram-bot 0.3.13 → 0.3.14

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.
Files changed (2) hide show
  1. package/bot.mjs +38 -4
  2. package/package.json +1 -1
package/bot.mjs CHANGED
@@ -794,6 +794,7 @@ async function downloadAttachment(att) {
794
794
  // ── 메시지 처리 ───────────────────────────────────────────────────────────
795
795
  let busy = false;
796
796
  const msgQueue = []; // { msg, receivedAt } — busy 중 수신 메시지 대기열
797
+ const mediaGroups = new Map(); // media_group_id → { msgs, timer } — 미디어 그룹 수집 대기
797
798
  let currentChild = null; // 실행 중인 claude child process (/stop 용)
798
799
  let currentTyping = null; // 타이핑 인터벌 (/stop 시 정리용)
799
800
  let prevSessionId; // /stop --reset 복원 대상
@@ -804,8 +805,8 @@ async function handle(msg) {
804
805
  if (!chatId) return;
805
806
  const l = langOf(msg);
806
807
  const text = (msg.text || msg.caption || "").trim();
807
- const attachment = pickAttachment(msg);
808
- if (!text && !attachment) return;
808
+ const attachment = msg._mediaGroup ? null : pickAttachment(msg);
809
+ if (!text && !attachment && !msg._mediaGroup?.length) return;
809
810
 
810
811
  // 화이트리스트
811
812
  if (!cfg.allowedChatId) {
@@ -951,7 +952,18 @@ async function handle(msg) {
951
952
 
952
953
  try {
953
954
  let prompt = text;
954
- if (attachment) {
955
+ if (msg._mediaGroup?.length) {
956
+ const notes = [];
957
+ for (const fileId of msg._mediaGroup) {
958
+ try {
959
+ const { dest, name } = await downloadAttachment({ fileId, name: null });
960
+ notes.push(`[Attachment] Absolute path: ${dest} (filename: ${name}). Open it with the Read tool if needed.`);
961
+ } catch (e) {
962
+ await send(chatId, t(l, "attachFail", e.message));
963
+ }
964
+ }
965
+ if (notes.length) prompt = text ? `${text}\n\n${notes.join("\n")}` : notes.join("\n");
966
+ } else if (attachment) {
955
967
  try {
956
968
  const { dest, name } = await downloadAttachment(attachment);
957
969
  const note = `[Attachment] Absolute path: ${dest} (filename: ${name}). Open it with the Read tool if needed.`;
@@ -996,6 +1008,28 @@ function drainQueue() {
996
1008
  return { ...group[group.length - 1].msg, text: merged, caption: undefined };
997
1009
  }
998
1010
 
1011
+ // 미디어 그룹(여러 장 동시 전송) — 1초 대기 후 일괄 처리
1012
+ function mergeMediaGroup(msgs) {
1013
+ const captions = msgs.map((m) => m.caption || "").filter(Boolean);
1014
+ const fileIds = msgs
1015
+ .filter((m) => m.photo?.length)
1016
+ .map((m) => m.photo[m.photo.length - 1].file_id);
1017
+ return { ...msgs[0], text: captions.join("\n"), caption: undefined, _mediaGroup: fileIds };
1018
+ }
1019
+
1020
+ function dispatch(msg) {
1021
+ const gid = msg.media_group_id;
1022
+ if (!gid) { handle(msg).catch((e) => console.error("Handle error:", e.message)); return; }
1023
+ if (!mediaGroups.has(gid)) mediaGroups.set(gid, { msgs: [], timer: null });
1024
+ const g = mediaGroups.get(gid);
1025
+ g.msgs.push(msg);
1026
+ clearTimeout(g.timer);
1027
+ g.timer = setTimeout(() => {
1028
+ mediaGroups.delete(gid);
1029
+ handle(mergeMediaGroup(g.msgs)).catch((e) => console.error("Handle error:", e.message));
1030
+ }, 1000);
1031
+ }
1032
+
999
1033
  // ── 롱폴링 루프 ───────────────────────────────────────────────────────────
1000
1034
  async function main() {
1001
1035
  console.log("Bot started. Polling Telegram...");
@@ -1033,7 +1067,7 @@ async function main() {
1033
1067
  }
1034
1068
  for (const upd of res.result) {
1035
1069
  offset = upd.update_id + 1;
1036
- if (upd.message) handle(upd.message).catch((e) => console.error("Handle error:", e.message));
1070
+ if (upd.message) dispatch(upd.message);
1037
1071
  }
1038
1072
  } catch (e) {
1039
1073
  console.error("Polling error:", e.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-telegram-bot",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
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": {