- Install grammy v2 for long polling Telegram bot - telegramService: text relay handler, agent prefix, session map, deleteWebhook lifecycle - telegramRoutes: POST /telegram/token (getMe validation), GET /telegram/status - telegram.ts under 500 lines (187 lines)
70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { Router } from "express";
|
|
import { Bot } from "grammy";
|
|
import { assertBoard } from "./authz.js";
|
|
import { nexusSettingsService } from "../services/nexus-settings.js";
|
|
import type { TelegramService } from "../services/telegram.js";
|
|
import type { Db } from "@paperclipai/db";
|
|
|
|
export function telegramRoutes(db: Db, svc: TelegramService): Router {
|
|
const router = Router();
|
|
|
|
// POST /telegram/token — validate and save bot token, restart bot
|
|
router.post("/telegram/token", async (req, res) => {
|
|
try {
|
|
assertBoard(req);
|
|
|
|
const { token } = req.body as { token?: string };
|
|
if (!token || typeof token !== "string" || token.trim() === "") {
|
|
res.status(400).json({ error: "token is required" });
|
|
return;
|
|
}
|
|
|
|
// Validate token by calling getMe
|
|
let botUsername: string;
|
|
try {
|
|
const tempBot = new Bot(token.trim());
|
|
const me = await tempBot.api.getMe();
|
|
botUsername = me.username ?? me.first_name;
|
|
} catch {
|
|
res.status(400).json({ error: "Invalid Telegram bot token" });
|
|
return;
|
|
}
|
|
|
|
// Save token to nexus settings
|
|
await nexusSettingsService().set({ telegramToken: token.trim() });
|
|
|
|
// Stop old bot and start new one with new token
|
|
await svc.stop();
|
|
svc.start(token.trim()).catch((err) => {
|
|
// Log but don't fail the request — token is saved
|
|
void err;
|
|
});
|
|
|
|
res.json({ ok: true, botUsername });
|
|
} catch (err: unknown) {
|
|
if (err && typeof err === "object" && "status" in err) {
|
|
const e = err as { status: number; message: string };
|
|
res.status(e.status).json({ error: e.message });
|
|
return;
|
|
}
|
|
res.status(500).json({ error: "Unexpected error" });
|
|
}
|
|
});
|
|
|
|
// GET /telegram/status — return running state
|
|
router.get("/telegram/status", async (req, res) => {
|
|
try {
|
|
assertBoard(req);
|
|
res.json({ running: svc.isRunning() });
|
|
} catch (err: unknown) {
|
|
if (err && typeof err === "object" && "status" in err) {
|
|
const e = err as { status: number; message: string };
|
|
res.status(e.status).json({ error: e.message });
|
|
return;
|
|
}
|
|
res.status(500).json({ error: "Unexpected error" });
|
|
}
|
|
});
|
|
|
|
return router;
|
|
}
|