0e37ebfe5f
Deploy db-migrations / db-migrations (push) Successful in 49s
Deploy service message-delivery-method-web-push / service message-delivery-method-web-push (push) Successful in 1m9s
Deploy app frontend / app frontend (push) Successful in 1m53s
Deploy service tg-bot / service tg-bot (push) Successful in 1m36s
326 lines
11 KiB
TypeScript
326 lines
11 KiB
TypeScript
import { MyContext } from "../../types/myContext";
|
|
import { Conversation } from "@grammyjs/conversations";
|
|
import { defaultMessages } from "@hereconnect/constants";
|
|
import { InlineKeyboardMarkup } from "@grammyjs/types";
|
|
|
|
// Тип разговора
|
|
type MyConversation = Conversation<MyContext>;
|
|
export async function selectPredefinedMessages(
|
|
conversation: MyConversation,
|
|
ctx: MyContext,
|
|
placement: keyof typeof defaultMessages,
|
|
): Promise<string[]> {
|
|
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;
|
|
}
|