152 lines
5.0 KiB
TypeScript
152 lines
5.0 KiB
TypeScript
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";
|
|
import { publicSettingsDb } from "../../dbs";
|
|
|
|
export async function newQRCodeConversation(
|
|
conversation: Conversation<MyContext>,
|
|
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"),
|
|
);
|
|
|
|
const { value: instruction } = await publicSettingsDb
|
|
.get(`public_settings:placement_instructions_${typedPlacement}`)
|
|
.catch((error) => {
|
|
console.error(error);
|
|
return { value: "Разместите этот код на вашем объекте." };
|
|
});
|
|
|
|
await ctx.reply(
|
|
`${instruction}\n\nПри сканировании по адресу ${url} посетители смогут взаимодействовать с вами.`.trim(),
|
|
{ parse_mode: "Markdown" },
|
|
);
|
|
|
|
// Завершаем разговор
|
|
}
|