Skip to content

Instantly share code, notes, and snippets.

@waptik
Last active July 2, 2024 10:18
Show Gist options
  • Save waptik/2038ad8f167b7af6d25d34ff9b070a2f to your computer and use it in GitHub Desktop.
Save waptik/2038ad8f167b7af6d25d34ff9b070a2f to your computer and use it in GitHub Desktop.
This is a minimal codebase of getting grammY to work with nextjs pages directory. Please use this version of `next-connect`: `"next-connect": "^0.13.0",`
import { Bot, Context } from "grammy";
export const bot = new Bot<Context>(process.env.TELEGRAM_BOT_TOKEN ?? "");
import { bot } from "path/to/bot";
const WEBAPP_URL = "" // URL to your production main site(eg. https://my-secrete-webapp.tld)
const handleGracefulShutdown = async () => {
await bot.stop();
process.exit();
};
if (process.env.NODE_ENV==="development") {
// Graceful shutdown handlers
process.once("SIGTERM", handleGracefulShutdown);
process.once("SIGINT", handleGracefulShutdown);
}
export const startTelegramBotInDev = async () => {
if (!bot.isInited()) {
await bot.start();
}
};
export const startTelegramBotInProduction = async () => {
const webhookUrl = `${WEBAPP_URL}/api/telegram-webhook?token=${env.TELEGRAM_BOT_WEBHOOK_TOKEN}`;
const webhookInfo = await bot.api.getWebhookInfo();
if (webhookInfo.url !== webhookUrl) {
await bot.api.deleteWebhook();
await bot.api.setWebhook(webhookUrl);
}
} catch (_) { }
};
import { NextApiRequest, NextApiResponse } from "next";
import nc from "next-connect";
import { BotError } from "grammy";
import { startTelegramBotInDev } from "path/to/start";
// this is to test the bot locally by visiting http://localhost:3000/api/telegram-dev?action=start
const handler = nc<NextApiRequest, NextApiResponse>({
attachParams: true,
onError: (err, _req, res, next) => {
if (err instanceof BotError) {
res.status(200).send({});
} else {
console.error(err);
res.status(500).end("Something broke!");
}
next();
},
})
.get((req, _res, next) => {
if (process.env.NODE_ENV==="development") {
next();
}
})
.get(async (req: NextApiRequest, res: NextApiResponse) => {
try {
if (req.query && req.query.action !== "start") {
res.status(500).send({ error: { message: "Wrong gateway." } });
return;
}
await startTelegramBotInDev();
res.status(200).send("ok");
} catch (error) {
res.status(500).json({ error });
}
});
export default handler;
// path: /pages/api/telegram-dev.ts
import { NextApiRequest, NextApiResponse } from "next";
import nc from "next-connect";
import { BotError, webhookCallback } from "grammy";
import { bot } from "path/to/bot";
import { startTelegramBotInProduction } from "path/to/start";
const isProd = process.env.NODE_ENV === "production"
const handler = nc<NextApiRequest, NextApiResponse>({
attachParams: true,
onError: (err, _req, res, next) => {
if (err instanceof BotError) {
res.status(200).send({});
} else {
res.status(500).end("Something broke!");
}
next();
},
})
.post((req, _res, next) => {
if (req.query && req.query.token === process.env.TELEGRAM_BOT_WEBHOOK_TOKEN) {
next();
}
})
.post(webhookCallback(bot, "next-js"))
.get(async (req, res) => {
// this is used to automatically setup your webhook by visiting https://my-secrete-webapp.tld/api/telegram-webhook?token=[YOUR-BOT-TOKEN]
// replace [YOUR-BOT-TOKEN] with your telegram bot token
// only do so after you have deployed your bot in production
try {
if (process.env.NODE_ENV !=="production" || (req.query && req.query.token !== process.env.TELEGRAM_BOT_WEBHOOK_TOKEN)) {
return res.status(500).send({ error: { message: "Wrong gateway." } });
}
await startTelegramBotInProduction();
} finally {
return res.status(200).send("ok");
}
});
export default handler;
// path: /pages/api/telegram-webhook.ts
@mortezae
Copy link

mortezae commented Jul 2, 2024

typo in start.ts#L6: console.info

@waptik
Copy link
Author

waptik commented Jul 2, 2024

typo in start.ts#L6: console.info

Thanks! I fixed it and removed non important code from the entire structure so as to minimize unexpected errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment