110 lines
3.6 KiB
TypeScript
110 lines
3.6 KiB
TypeScript
|
|
import { Bot, Context, InlineKeyboard } from "grammy";
|
||
|
|
import { type AbortSignal } from "grammy/out/shim.node";
|
||
|
|
import { qrCodePlacements } from "@hereconnect/constants";
|
||
|
|
import type { QRCodeDocument } from "@hereconnect/types";
|
||
|
|
|
||
|
|
const BOT_TOKEN = process.env.BOT_TOKEN;
|
||
|
|
if (!BOT_TOKEN) {
|
||
|
|
throw new Error("Необходимо указать BOT_TOKEN в переменных окружения.");
|
||
|
|
}
|
||
|
|
|
||
|
|
export const bot = new Bot(BOT_TOKEN);
|
||
|
|
|
||
|
|
export const init = async (signal: AbortSignal) => {
|
||
|
|
await bot.init(signal);
|
||
|
|
|
||
|
|
// Настройка команд для английского языка (по умолчанию)
|
||
|
|
await bot.api.setMyCommands([
|
||
|
|
{ command: "create_qr", description: "Create a QR code" },
|
||
|
|
{ command: "help", description: "Get help" },
|
||
|
|
]);
|
||
|
|
|
||
|
|
// Настройка команд для русского языка
|
||
|
|
await bot.api.setMyCommands(
|
||
|
|
[
|
||
|
|
{ command: "create_qr", description: "Создать QR-код" },
|
||
|
|
{ command: "help", description: "Получить помощь" },
|
||
|
|
],
|
||
|
|
{ language_code: "ru" },
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
const actionsOptions = [
|
||
|
|
{
|
||
|
|
type: "sendMessage",
|
||
|
|
label: "Отправить сообщение",
|
||
|
|
},
|
||
|
|
{ type: "viewContactInfo", label: "Посмотреть ваши контактные данные" },
|
||
|
|
];
|
||
|
|
|
||
|
|
bot.command("start", async (ctx) => {
|
||
|
|
const user = ctx.from;
|
||
|
|
|
||
|
|
const message = `Привет${user?.first_name ? ", " + user?.first_name : ""}!\n\nЯ бот сервиса "НаСвязи". Помогу вам создать QR-код (для автомобиля, питомца, входной двери и т.д.).!`;
|
||
|
|
|
||
|
|
// Отправляем сообщение
|
||
|
|
return ctx.reply(message, {
|
||
|
|
reply_markup: {
|
||
|
|
inline_keyboard: [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
text: "Создать QR-код",
|
||
|
|
callback_data: "create_qr",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
],
|
||
|
|
},
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
const createQrCode = async (ctx: Context) => {
|
||
|
|
const keyboard = new InlineKeyboard();
|
||
|
|
for (const { type, label } of qrCodePlacements) {
|
||
|
|
keyboard.text(label, `select_placement=${type}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
await ctx.reply(
|
||
|
|
"Где вы хотите разместить QR‑код?\n\nЭтот выбор поможет настроить QR‑код с подходящими действиями.",
|
||
|
|
{ reply_markup: { inline_keyboard: keyboard.toFlowed(1).inline_keyboard } },
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
bot.command("create_qr", createQrCode);
|
||
|
|
|
||
|
|
bot.callbackQuery("cancel", async (ctx) => {
|
||
|
|
await ctx.deleteMessage();
|
||
|
|
});
|
||
|
|
|
||
|
|
bot.callbackQuery(
|
||
|
|
/^(select_action=|select_placement=|create_qr$)/,
|
||
|
|
async (ctx) => {
|
||
|
|
const selectedActions: QRCodeDocument["actions"] = [];
|
||
|
|
const keyboard = new InlineKeyboard();
|
||
|
|
for (const { type, label } of actionsOptions) {
|
||
|
|
keyboard.text(
|
||
|
|
(selectedActions.includes(type) ? "✓ " : "") + label,
|
||
|
|
`select_action=${type}`,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
await ctx.reply(
|
||
|
|
"Выберите доступные действия?\n\nУкажите, какие действия будут доступны для сканирующих QR‑код.\nВы сможете изменить эти настройки позже.",
|
||
|
|
{ reply_markup: { inline_keyboard: keyboard.inline_keyboard } },
|
||
|
|
);
|
||
|
|
},
|
||
|
|
);
|
||
|
|
|
||
|
|
if (process.argv.includes("start")) {
|
||
|
|
const abortController = new AbortController();
|
||
|
|
|
||
|
|
process.on("SIGINT", async () => {
|
||
|
|
abortController.abort();
|
||
|
|
setTimeout(() => process.exit(1), 1_000).unref();
|
||
|
|
});
|
||
|
|
|
||
|
|
init(abortController.signal as AbortSignal)
|
||
|
|
.then(() => bot.start())
|
||
|
|
.then(() => console.log("Bot started"))
|
||
|
|
.catch((error) => console.error(error));
|
||
|
|
}
|