diff --git a/bot/handlers/commands/settings/set_description_cmd.py b/bot/handlers/commands/settings/set_description_cmd.py new file mode 100644 index 0000000..ebcca9c --- /dev/null +++ b/bot/handlers/commands/settings/set_description_cmd.py @@ -0,0 +1,173 @@ +from aiogram import Router, F, Bot +from aiogram.exceptions import TelegramAPIError, TelegramRetryAfter +from aiogram.filters import Command, CommandObject +from aiogram.fsm.context import FSMContext +from aiogram.fsm.state import StatesGroup, State +from aiogram.types import Message, CallbackQuery +from aiogram.utils.i18n import gettext as _ + +from bot.core.bots import BotInfo +from bot.filters import IsOwner +from bot.handlers.commands.settings.settings_cmd import settings_keyboard +from bot.templates import msg +from bot.utils import format_retry_time, status_clear +from configs import COMMANDS +from middleware.loggers import logger + +__all__ = ("router",) + +# Название команды +CMD: str = "set_description".lower() + +# Роутер для обработки команды /set_description +router: Router = Router(name=f"{CMD}_cmd_router") + + +class SetBotDescriptionForm(StatesGroup): + """Состояния FSM для изменения короткого описания бота.""" + new_description: State = State() + + +async def handle_set_bot_description( + description: str, + message: Message | CallbackQuery, + state: FSMContext, + bot: Bot +) -> None: + """ + Установка короткого описания (short description) бота с обработкой FSM и ошибок API. + + Args: + description (str): Новый текст описания (до 120 символов). + message (Message | CallbackQuery): Сообщение или callback-запрос. + state (FSMContext): Контекст FSM. + bot (Bot): Экземпляр бота. + """ + # Проверка ограничения Telegram + if len(description) > 120: + await msg( + update=message, + text=_("❌ Короткое описание бота должно быть не более 120 символов. Текущая длина: {length}").format( + length=len(description) + ), + markup=settings_keyboard(), + state=state + ) + return + + try: + # Установка нового короткого описания + await bot.set_my_short_description(short_description=description) + + # Сохраняем текущее значение в BotInfo + BotInfo.short_description = description + + # Сбрасываем состояние FSM + await state.clear() + + # Отправляем сообщение об успехе + await msg( + update=message, + text=_("✅ Короткое описание бота успешно изменено на: {description}").format( + description=description + ), + markup=settings_keyboard(), + state=state + ) + + logger.info(f"Короткое описание бота изменено на: {description}") + + except TelegramRetryAfter as e: + retry_text: str = format_retry_time(e.retry_after) + logger.warning(f"Превышен лимит запросов при смене short description. Попробуйте через {retry_text}") + await msg( + update=message, + text=_("⚠️ Слишком частая смена короткого описания!\nПопробуйте снова через: {retry_text}").format( + retry_text=retry_text + ), + markup=settings_keyboard(), + state=state + ) + + except TelegramAPIError as e: + logger.error(f"Ошибка Telegram API при изменении короткого описания: {e}") + await msg( + update=message, + text=_("❌ Ошибка Telegram API при изменении короткого описания:
{error}").format(error=str(e)),
+ markup=settings_keyboard(),
+ state=state
+ )
+
+ except Exception as e:
+ logger.error(f"Непредвиденная ошибка при изменении короткого описания: {e}")
+ await msg(
+ update=message,
+ text=_("❌ Непредвиденная ошибка при изменении короткого описания: {error}").format(error=str(e)),
+ markup=settings_keyboard(),
+ state=state
+ )
+
+
+@router.callback_query(F.data.lower() == CMD, IsOwner())
+@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner())
+async def settings_cmd(
+ message: Message | CallbackQuery,
+ state: FSMContext,
+ bot: Bot,
+ command: CommandObject | None = None
+) -> None:
+ """
+ Обработчик команды /set_description для короткого описания.
+
+ Поддерживает:
+ 1. Немедленное изменение через аргумент (/set_description TEXT).
+ 2. Callback-запрос.
+ 3. FSM-ввод.
+ """
+ current_description: str = BotInfo.description
+
+ # Вариант 1: если пользователь передал аргумент к команде
+ if command and command.args:
+ description: str = command.args.strip()
+ if len(description) > 120:
+ await msg(
+ update=message,
+ text=_("❌ Короткое описание не должно превышать 120 символов. Текущая длина: {length}").format(
+ length=len(description)
+ ),
+ markup=settings_keyboard(),
+ state=state
+ )
+ return
+
+ await handle_set_bot_description(description, message, state, bot)
+ return
+
+ # Вариант 2: без аргумента → включаем FSM
+ await status_clear(update=message, state=state)
+ text: str = _(
+ "📝 Смена короткого описания бота\n\n"
+ "Текущее короткое описание: {current}\n\n"
+ "Введите новое короткое описание (максимум 120 символов):"
+ ).format(current=current_description)
+
+ await msg(update=message, text=text, markup=settings_keyboard(), state=state)
+ await state.set_state(SetBotDescriptionForm.new_description)
+
+
+@router.message(SetBotDescriptionForm.new_description, IsOwner())
+async def process_new_bot_description(
+ message: Message,
+ state: FSMContext,
+ bot: Bot
+) -> None:
+ """
+ Обработка ввода нового короткого описания через FSM.
+ """
+ description: str = message.text.strip()
+
+ if not description:
+ await message.answer(_("❌ Пожалуйста, введите корректное короткое описание."))
+ return
+
+ await handle_set_bot_description(description, message, state, bot)