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)