diff --git a/bot.py b/bot.py index f5fc0e6..a34d18e 100644 --- a/bot.py +++ b/bot.py @@ -49,6 +49,7 @@ class UserState: input_type: Optional[str] = None # "name", "description", "icon", "command" parent_menu: Optional[str] = None context: Dict[str, Any] = field(default_factory=dict) + working_directory: Optional[str] = None # Текущая директория пользователя class StateManager: @@ -270,11 +271,16 @@ async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE): state_manager.reset(user.id) + # Показать текущую директорию + working_dir = config.get("working_directory", str(Path.home())) + await update.message.reply_text( f"👋 Привет, {user.first_name}!\n\n" f"{config.icon} *{config.name}*\n" f"_{config.description}_\n\n" f"*Просто отправьте CLI команду в чат* — я её выполню!\n\n" + f"📁 Рабочая директория: `{working_dir}`\n\n" + f"Используйте `cd путь` для смены директории.\n" f"Или используйте кнопки меню для быстрых команд.\n" f"Команда /help покажет справку.", parse_mode="Markdown", @@ -296,6 +302,12 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE): • `df -h` — свободное место на диске • `git status` — статус git +*Навигация по директориям:* +• `cd путь` — сменить директорию (например, `cd git/project`) +• `cd ..` — на уровень вверх +• `cd ~` — в домашнюю директорию +• `pwd` — показать текущую директорию + *Кнопки меню:* • 📋 Предустановленные команды — быстрые команды по категориям • ⚙️ Настройки бота — изменение имени, описания, иконки @@ -490,10 +502,14 @@ async def menu_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): async def execute_cli_command(query, command: str): - """Выполнение CLI команды.""" - working_dir = config.get("working_directory", str(Path.home())) + """Выполнение CLI команды из кнопки меню.""" + user_id = query.from_user.id + state = state_manager.get(user_id) - logger.info(f"Выполнение команды: {command}") + # Определяем рабочую директорию: сначала пользовательская, потом из конфига + working_dir = state.working_directory or config.get("working_directory", str(Path.home())) + + logger.info(f"Выполнение команды: {command} в директории: {working_dir}") await query.edit_message_text( f"⏳ *Выполнение...*\n\n`{command}`", @@ -631,7 +647,39 @@ async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE async def execute_cli_command_from_message(update: Update, command: str): """Выполнение CLI команды из сообщения.""" - working_dir = config.get("working_directory", str(Path.home())) + user_id = update.effective_user.id + state = state_manager.get(user_id) + + # Определяем рабочую директорию: сначала пользовательская, потом из конфига + working_dir = state.working_directory or config.get("working_directory", str(Path.home())) + + # Обработка команды cd - меняем директорию пользователя + if command.strip().startswith("cd "): + parts = command.strip().split(maxsplit=1) + if len(parts) == 2: + target_dir = parts[1] + + # Обработка ~ и относительных путей + if target_dir.startswith("~"): + target_dir = str(Path.home()) + target_dir[1:] + elif not target_dir.startswith("/"): + target_dir = str(Path(working_dir) / target_dir) + + # Проверка существования директории + if Path(target_dir).is_dir(): + state.working_directory = target_dir + await update.message.reply_text( + f"📁 *Директория изменена:*\n`{target_dir}`", + parse_mode="Markdown" + ) + else: + await update.message.reply_text( + f"❌ *Директория не найдена:*\n`{target_dir}`", + parse_mode="Markdown" + ) + return + + logger.info(f"Выполнение команды: {command} в директории: {working_dir}") try: process = await asyncio.create_subprocess_shell(