Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions scripts/telegram-bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ if (!API_KEY) { console.error("NVIDIA_API_KEY required"); process.exit(1); }
let offset = 0;
const activeSessions = new Map(); // chatId → message history

const COOLDOWN_MS = 5000;
const lastMessageTime = new Map();
const busyChats = new Set();

// ── Telegram API helpers ──────────────────────────────────────────

function tgApi(method, body) {
Expand Down Expand Up @@ -198,6 +202,24 @@ async function poll() {
continue;
}

// Rate limiting: per-chat cooldown
const now = Date.now();
const lastTime = lastMessageTime.get(chatId) || 0;
if (now - lastTime < COOLDOWN_MS) {
const wait = Math.ceil((COOLDOWN_MS - (now - lastTime)) / 1000);
await sendMessage(chatId, `Please wait ${wait}s before sending another message.`, msg.message_id);
continue;
}

// Per-chat serialization: reject if this chat already has an active session
if (busyChats.has(chatId)) {
await sendMessage(chatId, "Still processing your previous message.", msg.message_id);
continue;
}

lastMessageTime.set(chatId, now);
busyChats.add(chatId);

// Send typing indicator
await sendTyping(chatId);

Expand All @@ -212,15 +234,17 @@ async function poll() {
} catch (err) {
clearInterval(typingInterval);
await sendMessage(chatId, `Error: ${err.message}`, msg.message_id);
} finally {
busyChats.delete(chatId);
}
}
}
} catch (err) {
console.error("Poll error:", err.message);
}

// Continue polling
setTimeout(poll, 100);
// Continue polling (1s floor prevents tight-loop resource waste)
setTimeout(poll, 1000);
}

// ── Main ──────────────────────────────────────────────────────────
Expand Down
Loading