import { type QRCodeDocument } from "@hereconnect/types"; import { Conversation } from "@grammyjs/conversations"; import { InputFile } from "grammy"; import type { MyContext } from "../../types/myContext"; import { qrCodePlacements } from "../../types/models"; import { buildPlacementKeyboard, buildActionsKeyboard, } from "../utils/keyboards"; import { createQRCode } from "../../api/qrCodes"; import { generateQRCodeImage } from "../../services/qrGenerator"; import { selectMultipleActions } from "./selectMultipleActions"; import { defaultMessages } from "@hereconnect/constants"; import { selectPredefinedMessages } from "./selectPredefinedMessages"; export async function newQRCodeConversation( conversation: Conversation, ctx: MyContext, ) { if (!ctx.userDoc) { await ctx.reply( "Не удалось определить вашего пользователя. Попробуйте позже.", ); return; } const userUuid = ctx.userDoc.user_uuid; if (!userUuid) { await ctx.reply( "У вашего профиля отсутствует UUID. Обратитесь в поддержку.", ); return; } // Выбор типа объекта (placement) await ctx.reply("Выберите объект, для которого будет создан QR-код:", { reply_markup: { inline_keyboard: buildPlacementKeyboard(qrCodePlacements), }, }); const placementChoice = await conversation.waitFor("callback_query:data"); const placement = placementChoice.update.callback_query?.data; // Проверяем, что выбранное значение входит в допустимые типы if (!qrCodePlacements.some((p) => p.type === placement)) { await ctx.reply("Неверный выбор. Попробуйте снова /new"); return; } // Преобразуем `placement` в строго типизированное значение const typedPlacement = placement as QRCodeDocument["placement"]; // Подтверждаем выбор await placementChoice.answerCallbackQuery({ text: "Объект выбран!" }); // Выбор действий const availableActions = [ { action: "sendMessage", label: "Отправить сообщение" }, { action: "viewContactInfo", label: "Посмотреть контактные данные" }, ] as const; const chosenActions = await selectMultipleActions( conversation, ctx, availableActions, ); if (chosenActions.length === 0) { await ctx.reply("Вы не выбрали ни одного действия. Попробуйте снова /new."); return; } // Ввод названия QR-кода let exampleName: string; switch (typedPlacement) { case "car": exampleName = "Моя машина"; break; case "pet": exampleName = "Ошейник Барсика"; break; case "door": exampleName = "Входная дверь квартиры"; break; case "store": exampleName = "Магазин на углу"; break; case "restaurant_table": exampleName = "Столик №12"; break; case "other": exampleName = "Что-то другое"; break; } let predefinedMessages: QRCodeDocument["predefinedMessages"] = undefined; if (chosenActions.includes("sendMessage")) { predefinedMessages = await selectPredefinedMessages( conversation, ctx, typedPlacement, ); } // Отправляем сообщение пользователю с примером await ctx.reply( `Введите название для вашего QR-кода (например: «${exampleName}»):`, ); const nameMsg = await conversation.waitFor("message:text"); const name = nameMsg.message.text.trim(); // Уведомление о создании QR-кода await ctx.reply("Создаём QR-код…"); // Создание документа в БД const { url } = await createQRCode({ userUuid, name, placement: typedPlacement, actions: chosenActions, predefinedMessages, }); // Генерация QR-кода const pngBuffer = await generateQRCodeImage(url, { format: "png" }); // Отправляем пользователю QR-код await ctx.reply("Ваш QR-код готов! Вот он:"); await ctx.replyWithPhoto( new InputFile(new Uint8Array(pngBuffer.buffer), "qr.png"), ); await ctx.reply( `Разместите этот код на вашем объекте. При сканировании по адресу ${url} посетители смогут взаимодействовать с вами.`, ); // Завершаем разговор }