import { MyContext } from "../../types/myContext"; import { Conversation } from "@grammyjs/conversations"; import { defaultMessages } from "@hereconnect/constants"; import { InlineKeyboardMarkup } from "@grammyjs/types"; // Тип разговора type MyConversation = Conversation; export async function selectPredefinedMessages( conversation: MyConversation, ctx: MyContext, placement: keyof typeof defaultMessages, ): Promise { const messages: string[] = [...defaultMessages[placement]]; let mode: "default" | "edit" | "sort" = "default"; let selectedIndex: number | null = null; let sortOrder: number[] = []; const updateKeyboard = (): InlineKeyboardMarkup => ({ inline_keyboard: messages .map((message, index) => { const prefix = mode === "edit" && selectedIndex === index ? "📝 " : mode === "sort" && sortOrder.includes(index) ? `${sortOrder.indexOf(index) + 1}. ` : ""; return [ { text: `${prefix}${message}`, callback_data: `select:${index}`, }, ]; }) .concat( mode === "sort" ? [ [{ text: "✅ Завершить сортировку", callback_data: "done_sort" }], [ { text: "❌ Отменить сортировку", callback_data: "cancel_sort", }, ], ] : mode === "edit" && selectedIndex !== null ? [ [ { text: `❌ Удалить «${messages[selectedIndex]}»`, callback_data: `delete:${selectedIndex}`, }, ], [ { text: "❌ Отменить редактирование", callback_data: "cancel_edit", }, ], ] : messages.length > 0 ? [ [{ text: "🔀 Поменять порядок", callback_data: "sort" }], [{ text: "✅ Готово", callback_data: "done" }], ] : [[{ text: "✅ Готово", callback_data: "done" }]], ), }); // Функция для отправки или редактирования сообщения const sendOrEditMessage = async ( text: string, options: { reply_markup: InlineKeyboardMarkup; parse_mode?: "Markdown" | "MarkdownV2" | "HTML"; }, forceNew = false, ) => { try { if (forceNew && ctx.session.messageId) { try { await ctx.api.deleteMessage(ctx.chat!.id, ctx.session.messageId); ctx.session.messageId = undefined; console.log("deleteMessage", ctx.session.messageId); } catch (deleteErr) { console.warn( "Ошибка удаления старого сообщения:", ctx.session.messageId, deleteErr, ); ctx.session.messageId = undefined; } } if (ctx.session.messageId) { await ctx.api.editMessageText( ctx.chat!.id, ctx.session.messageId, text, options, ); } else { const replyMessage = await ctx.reply(text, options); console.log("replyMessage.message_id", replyMessage.message_id); ctx.session.messageId = replyMessage.message_id; } } catch (err) { console.error( "Ошибка обновления сообщения, создаем новое:", ctx.session.messageId, err, ); if (ctx.session.messageId) { try { await ctx.api.deleteMessage(ctx.chat!.id, ctx.session.messageId); console.log("deleteMessage", ctx.session.messageId); } catch (deleteErr) { console.warn( "Ошибка удаления старого сообщения:", ctx.session.messageId, deleteErr, ); } } const newMessage = await ctx.reply(text, options); console.log("newMessage.message_id", newMessage.message_id); ctx.session.messageId = newMessage.message_id; } }; // Начальное сообщение await sendOrEditMessage( `**Настройка предустановленных сообщений** Эти сообщения будут предлагаться пользователю при сканировании QR‑кода. Он сможет выбрать одно из них или написать своё. Напишите сообщение для добавления, нажмите на сообщение для редактирования или выберите "🔀 Поменять порядок" для сортировки.`, { parse_mode: "Markdown", reply_markup: updateKeyboard() }, ); while (true) { const actionChoice = await conversation.waitFor([ "callback_query:data", "message:text", ]); const choice = actionChoice.update.callback_query?.data; if (!choice && !actionChoice.message) { if (choice) { // await actionChoice.answerCallbackQuery({ // text: "Произошла ошибка. Попробуйте снова.", // }); continue; } ctx.session.messageId = undefined; break; } const messageText = actionChoice.message?.text.trim(); if (!choice) { if (messageText) { if (mode === "edit" && selectedIndex !== null) { messages[selectedIndex] = messageText; mode = "default"; selectedIndex = null; // await ctx.reply(`Сообщение обновлено: ${messageText}`); await sendOrEditMessage( "Сообщение обновлено.", { parse_mode: "Markdown", reply_markup: updateKeyboard(), }, true, ); } else { messages.push(messageText); // await ctx.reply(`Сообщение добавлено: ${messageText}`); await sendOrEditMessage( "Сообщение добавлено.", { parse_mode: "Markdown", reply_markup: updateKeyboard(), }, true, ); } } else { await ctx.reply(`Введите текст сообщения.`); } continue; } if (choice === "done") { // await actionChoice.answerCallbackQuery({ text: "Настройка завершена!" }); await ctx.api.deleteMessage(ctx.chat!.id, ctx.session.messageId!); ctx.session.messageId = undefined; break; } if (choice === "sort") { mode = "sort"; sortOrder.length = 0; // await actionChoice.answerCallbackQuery({ text: "Режим сортировки." }); await sendOrEditMessage("Нажмите на сообщения по порядку.", { parse_mode: "Markdown", reply_markup: updateKeyboard(), }); continue; } if (mode === "sort" && choice.startsWith("select:")) { const index = parseInt(choice.replace("select:", ""), 10); if (sortOrder.includes(index)) { sortOrder.splice(sortOrder.indexOf(index), 1); } else { sortOrder.push(index); } const sortedMessages: string[] = []; sortOrder.forEach((sortIndex, messagesIndex) => { sortedMessages[messagesIndex] = messages[sortIndex]; }); messages.forEach((message, index) => { if (!sortOrder.includes(index)) { sortedMessages.push(message); } }); // Обновляем порядок сообщений for (let i = 0; i < sortedMessages.length; i++) { messages[i] = sortedMessages[i]; } for (let i = 0; i < sortOrder.length; i++) { sortOrder[i] = i; } // await actionChoice.answerCallbackQuery({ text: "Сообщение перемещено." }); await sendOrEditMessage( "Нажмите на сообщения по порядку, начиная с первого.", { parse_mode: "Markdown", reply_markup: updateKeyboard() }, ); continue; } if (choice === "cancel_sort") { mode = "default"; sortOrder.length = 0; // await actionChoice.answerCallbackQuery({ text: "Сортировка отменена." }); await sendOrEditMessage( "Сортировка отменена. Возврат к стандартному режиму.", { parse_mode: "Markdown", reply_markup: updateKeyboard() }, ); continue; } if (choice === "done_sort") { mode = "default"; sortOrder.length = 0; // await actionChoice.answerCallbackQuery({ text: "Сортировка завершена." }); await sendOrEditMessage("Сортировка завершена.", { parse_mode: "Markdown", reply_markup: updateKeyboard(), }); continue; } if (choice.startsWith("select:")) { const index = parseInt(choice.replace("select:", ""), 10); if (selectedIndex === index) { // await actionChoice.answerCallbackQuery({ // text: "Редактирование отменено.", // }); mode = "default"; selectedIndex = null; await sendOrEditMessage("Редактирование отменено.", { parse_mode: "Markdown", reply_markup: updateKeyboard(), }); continue; } mode = "edit"; selectedIndex = index; // await actionChoice.answerCallbackQuery({ // text: `Редактирование сообщения: "${messages[index]}"`, // }); await sendOrEditMessage( `Редактирование сообщения: "${messages[index]}"`, { parse_mode: "Markdown", reply_markup: updateKeyboard() }, ); continue; } if (choice === "cancel_edit") { mode = "default"; selectedIndex = null; // await actionChoice.answerCallbackQuery({ // text: "Редактирование отменено.", // }); await sendOrEditMessage("Редактирование отменено.", { parse_mode: "Markdown", reply_markup: updateKeyboard(), }); continue; } if (choice.startsWith("delete:")) { const index = parseInt(choice.replace("delete:", ""), 10); const deletedMessage = messages.splice(index, 1)[0]; mode = "default"; selectedIndex = null; // await actionChoice.answerCallbackQuery({ // text: `Сообщение "${deletedMessage}" удалено.`, // }); await sendOrEditMessage(`Сообщение "${deletedMessage}" удалено.`, { parse_mode: "Markdown", reply_markup: updateKeyboard(), }); } } return messages; }