diff --git a/olgram/commands/menu.py b/olgram/commands/menu.py index 3eddf09..9ca36f3 100644 --- a/olgram/commands/menu.py +++ b/olgram/commands/menu.py @@ -1,7 +1,7 @@ from olgram.router import dp from aiogram import types, Bot as AioBot -from olgram.models.models import Bot, User +from olgram.models.models import Bot, User, DefaultAnswer from aiogram.dispatcher import FSMContext from aiogram.utils.callback_data import CallbackData from textwrap import dedent @@ -158,7 +158,7 @@ async def send_bot_text_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] = ) text = dedent(""" - Сейчас вы редактируете текст, который отправляется после того, как пользователь отправит вашему боту {0} + Сейчас вы редактируете текст, который отправляется после того, как пользователь отправит вашему боту @{0} команду /start Текущий текст: @@ -188,6 +188,11 @@ async def send_bot_second_text_menu(bot: Bot, call: ty.Optional[types.CallbackQu callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="text", chat=empty)) ) + keyboard.insert( + types.InlineKeyboardButton(text="Шаблоны ответов...", + callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="templates", + chat=empty)) + ) keyboard.insert( types.InlineKeyboardButton(text="Сбросить текст", callback_data=menu_callback.new(level=3, bot_id=bot.id, @@ -211,6 +216,37 @@ async def send_bot_second_text_menu(bot: Bot, call: ty.Optional[types.CallbackQu await AioBot.get_current().send_message(chat_id, text, reply_markup=keyboard, parse_mode="HTML") +async def send_bot_templates_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] = None, + chat_id: ty.Optional[int] = None): + if call: + await call.answer() + keyboard = types.InlineKeyboardMarkup(row_width=2) + keyboard.insert( + types.InlineKeyboardButton(text="<< Завершить редактирование", + callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty)) + ) + + text = dedent(""" + Сейчас вы редактируете шаблоны ответов для @{0}. Текущие шаблоны: + +
+ {1} ++ Отправьте какую-нибудь фразу (например: "Ваш заказ готов, ожидайте!"), чтобы добавить её в шаблон. + Чтобы удалить шаблон из списка, отправьте его номер в списке (например, 4) + """) + + templates = await bot.answers + templates_text = "\n".join(f"{n}. {template.text}" for n, template in enumerate(templates)) + if not templates_text: + templates_text = "(нет шаблонов)" + text = text.format(bot.name, templates_text) + if call: + await edit_or_create(call, text, keyboard, parse_mode="HTML") + else: + await AioBot.get_current().send_message(chat_id, text, reply_markup=keyboard, parse_mode="HTML") + + @dp.message_handler(state="wait_start_text", content_types="text", regexp="^[^/].+") # Not command async def start_text_received(message: types.Message, state: FSMContext): async with state.proxy() as proxy: @@ -231,6 +267,28 @@ async def second_text_received(message: types.Message, state: FSMContext): await send_bot_second_text_menu(bot, chat_id=message.chat.id) +@dp.message_handler(state="wait_template", content_types="text", regexp="^[^/](.+)?") # Not command +async def template_received(message: types.Message, state: FSMContext): + async with state.proxy() as proxy: + bot_id = proxy.get("bot_id") + bot = await Bot.get_or_none(pk=bot_id) + + if message.text.isdigit(): + # Delete template + number = int(message.text) + templates = await bot.answers + if number < 0 or number >= len(templates): + await message.answer(f"Неправильное число. Чтобы удалить шаблон, введите число от 0 до {len(templates)}") + return + await templates[number].delete() + else: + # Add template + template = DefaultAnswer(text=message.text, bot=bot) + await template.save() + + await send_bot_templates_menu(bot, chat_id=message.chat.id) + + @dp.callback_query_handler(menu_callback.filter(), state="*") async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMContext): level = callback_data.get("level") @@ -245,6 +303,7 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon return if level == "1": + await state.reset_state() return await send_bot_menu(bot, call) operation = callback_data.get("operation") @@ -276,3 +335,8 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon if operation == "reset_second_text": await bot_actions.reset_bot_second_text(bot, call) return await send_bot_second_text_menu(bot, call) + if operation == "templates": + await state.set_state("wait_template") + async with state.proxy() as proxy: + proxy["bot_id"] = bot.id + return await send_bot_templates_menu(bot, call) diff --git a/olgram/migrations/models/7_20220210194635_update.sql b/olgram/migrations/models/7_20220210194635_update.sql new file mode 100644 index 0000000..f1f9392 --- /dev/null +++ b/olgram/migrations/models/7_20220210194635_update.sql @@ -0,0 +1,7 @@ +-- upgrade -- +CREATE TABLE IF NOT EXISTS "defaultanswer" ( + "id" BIGSERIAL NOT NULL PRIMARY KEY, + "bot_id" INT NOT NULL REFERENCES "bot" ("id") ON DELETE CASCADE +); +-- downgrade -- +DROP TABLE IF EXISTS "defaultanswer"; diff --git a/olgram/migrations/models/8_20220210201740_update.sql b/olgram/migrations/models/8_20220210201740_update.sql new file mode 100644 index 0000000..6f91d13 --- /dev/null +++ b/olgram/migrations/models/8_20220210201740_update.sql @@ -0,0 +1,4 @@ +-- upgrade -- +ALTER TABLE "defaultanswer" ADD "text" TEXT NOT NULL; +-- downgrade -- +ALTER TABLE "defaultanswer" DROP COLUMN "text"; diff --git a/olgram/models/models.py b/olgram/models/models.py index 42c5ed8..a336638 100644 --- a/olgram/models/models.py +++ b/olgram/models/models.py @@ -83,3 +83,9 @@ class BannedUser(Model): class Meta: table = "bot_banned_user" + + +class DefaultAnswer(Model): + id = fields.BigIntField(pk=True) + bot = fields.ForeignKeyField("models.Bot", related_name="answers", on_delete=fields.relational.CASCADE) + text = fields.TextField() \ No newline at end of file