From 4f5fbf9a39c9af0425824a8faec912ba724bd1e1 Mon Sep 17 00:00:00 2001 From: DerrtSML <93052047+DerrtSML@users.noreply.github.com> Date: Mon, 23 Jun 2025 19:40:32 +0300 Subject: [PATCH] Update bot.py --- bot.py | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/bot.py b/bot.py index b2157fb..9711f6a 100644 --- a/bot.py +++ b/bot.py @@ -70,6 +70,7 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: ) return + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text( "Привет! Я бот для управления qBittorrent.\n" "Отправь мне magnet-ссылку или URL torrent-файла, " @@ -79,7 +80,7 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: "Используй /help для списка команд." ) -# --- Команда /help (новая функция) --- +# --- Команда /help (исправленная функция) --- async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: if update.message is None: logger.warning("Received an update without a message object in help handler.") @@ -87,13 +88,14 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No logger.info(f"Received /help command from {update.effective_user.id}") + # Здесь Markdown используется, parse_mode="Markdown" необходим help_text = ( "Вот список доступных команд:\n\n" "**/start** - Начать работу с ботом и проверить подключение к qBittorrent.\n" "**/status** - Показать текущий статус всех активных загрузок.\n" "**/stop_torrent** - Выбрать и остановить загрузку торрента.\n" "**/help** - Показать это справочное сообщение.\n\n" - "Также вы можете отправить мне *magnet-ссылку* или *URL torrent-файла* " + "Также вы можете отправить мне *magnet-ссылку* или *URL torrent-файла* " "для добавления загрузки. Бот предложит выбрать категорию и директорию." ) await update.message.reply_text(help_text, parse_mode="Markdown") @@ -116,6 +118,7 @@ async def status(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: try: torrents = qb.torrents_info() if not torrents: + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text("Загрузок не найдено.") return @@ -143,6 +146,7 @@ async def status(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: eta_str = "Завершено" + # Здесь Markdown используется, поэтому важно, чтобы он был корректным status_messages.append( f"📊 *{torrent.name}*\n" f" Состояние: {torrent.state}\n" @@ -158,9 +162,11 @@ async def status(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: except APIError as e: logger.error(f"Error getting torrent status: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text(f"Ошибка при получении статуса торрентов: {e}") except Exception as e: logger.error(f"An unexpected error occurred in status command: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text(f"Произошла непредвиденная ошибка: {e}") # --- Команда /stop_torrent --- @@ -178,8 +184,9 @@ async def stop_torrent(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No return try: - torrents = qb.torrents_info(status_filter='downloading') # Только активные загрузки + torrents = qb.torrents_info(status_filter='downloading') if not torrents: + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text("Нет активных загрузок для остановки.") return @@ -192,13 +199,16 @@ async def stop_torrent(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No keyboard.append([InlineKeyboardButton(display_name, callback_data=f"stop_hash_{torrent.hash}")]) reply_markup = InlineKeyboardMarkup(keyboard) + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text("Выберите торрент для остановки:", reply_markup=reply_markup) except APIError as e: logger.error(f"Error fetching torrents for stopping: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text(f"Ошибка при получении списка торрентов для остановки: {e}") except Exception as e: logger.error(f"An unexpected error occurred in stop_torrent command: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text(f"Произошла непредвиденная ошибка: {e}") # --- Обработка кнопки "Остановить торрент" --- @@ -210,6 +220,7 @@ async def stop_torrent_callback(update: Update, context: ContextTypes.DEFAULT_TY logger.info(f"Attempting to stop torrent with hash: {torrent_hash}") if not init_qbittorrent_client(): + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text( "Не удалось подключиться к qBittorrent. Проверьте переменные окружения и доступность сервера." ) @@ -217,12 +228,15 @@ async def stop_torrent_callback(update: Update, context: ContextTypes.DEFAULT_TY try: qb.torrents_stop(torrent_hashes=torrent_hash) + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text(f"Торрент ({torrent_hash[:6]}...) успешно остановлен.") except APIError as e: logger.error(f"Error stopping torrent {torrent_hash}: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text(f"Ошибка при остановке торрента: {e}") except Exception as e: logger.error(f"An unexpected error occurred during torrent stopping: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text(f"Произошла непредвиденная ошибка: {e}") # --- Обработка magnet-ссылок и URL --- @@ -235,6 +249,7 @@ async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None logger.info(f"Received URL/Magnet: {text} from {update.effective_user.id}") if not init_qbittorrent_client(): + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text( "Не удалось подключиться к qBittorrent. Проверьте переменные окружения и доступность сервера." ) @@ -251,13 +266,16 @@ async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None category_keyboard.append([InlineKeyboardButton("Без категории", callback_data="select_category_no_category")]) reply_markup = InlineKeyboardMarkup(category_keyboard) + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text('Выберите категорию для загрузки:', reply_markup=reply_markup) except APIError as e: logger.error(f"Error fetching categories: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text(f"Ошибка при получении категорий: {e}") except Exception as e: logger.error(f"An unexpected error occurred in handle_url: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text(f"Произошла непредвиденная ошибка: {e}") @@ -273,12 +291,14 @@ async def select_category_callback(update: Update, context: ContextTypes.DEFAULT context.user_data['selected_category'] = selected_category + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text("Выберите директорию загрузки:") await send_directory_options(query, context) # --- Отправка опций директорий --- async def send_directory_options(query, context): if not init_qbittorrent_client(): + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text( "Не удалось подключиться к qBittorrent. Проверьте переменные окружения и доступность сервера." ) @@ -287,9 +307,9 @@ async def send_directory_options(query, context): try: available_paths = [ qb.app.default_save_path, - "/share/Data/Films", # ЗАМЕНИТЕ НА СВОИ АКТУАЛЬНЫЕ ПУТИ - "/share/Data/Serials", - "/share/Data/torrents", + "/mnt/user/downloads/movies", # ЗАМЕНИТЕ НА СВОИ АКТУАЛЬНЫЕ ПУТИ + "/mnt/user/downloads/tv-shows", + "/var/lib/qbittorrent/data/completed", ] available_paths = sorted(list(set([p.replace(os.sep, '/') for p in available_paths if p]))) @@ -300,13 +320,17 @@ async def send_directory_options(query, context): directory_keyboard.append([InlineKeyboardButton(display_path, callback_data=f"select_dir_{path}")]) reply_markup = InlineKeyboardMarkup(directory_keyboard) + # В этом сообщении нет Markdown, поэтому parse_mode не нужен + # edit_message_reply_markup не принимает parse_mode await query.edit_message_reply_markup(reply_markup=reply_markup) except APIError as e: logger.error(f"Error fetching default save path: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text(f"Ошибка при получении директорий сохранения: {e}") except Exception as e: logger.error(f"An unexpected error occurred in send_directory_options: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text(f"Произошла непредвиденная ошибка: {e}") @@ -324,10 +348,12 @@ async def select_directory_callback(update: Update, context: ContextTypes.DEFAUL category = context.user_data.get('selected_category') if not torrent_url: + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text("Ошибка: URL торрента не найден. Пожалуйста, попробуйте снова.") return if not init_qbittorrent_client(): + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text( "Не удалось подключиться к qBittorrent. Проверьте переменные окружения и доступность сервера." ) @@ -339,6 +365,7 @@ async def select_directory_callback(update: Update, context: ContextTypes.DEFAUL category=category, save_path=selected_directory ) + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text( f"Торрент успешно добавлен в qBittorrent.\n" f"Категория: {category or 'Без категории'}\n" @@ -350,9 +377,11 @@ async def select_directory_callback(update: Update, context: ContextTypes.DEFAUL del context.user_data['selected_category'] except APIError as e: logger.error(f"Error adding torrent with path: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text(f"Ошибка при добавлении торрента: {e}") except Exception as e: logger.error(f"An unexpected error occurred during torrent addition with path: {e}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await query.edit_message_text(f"Произошла непредвиденная ошибка: {e}") @@ -360,6 +389,7 @@ async def select_directory_callback(update: Update, context: ContextTypes.DEFAUL async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None: logger.error(f"Exception while handling an update: {context.error}") if update and update.effective_message: + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.effective_message.reply_text(f"Произошла внутренняя ошибка бота: {context.error}") # --- Обработчик для неизвестных команд --- @@ -368,6 +398,7 @@ async def unknown_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> logger.warning("Received an unknown command update without a message object.") return logger.info(f"Received unknown command: {update.message.text} from {update.effective_user.id}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text("Извините, я не понял эту команду.") # --- Обработчик для любого другого текста (для отладки) --- @@ -376,6 +407,7 @@ async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: logger.warning(f"Received non-text update in echo handler: {update}") return logger.info(f"Received non-command text: {update.message.text} from {update.effective_user.id}") + # В этом сообщении нет Markdown, поэтому parse_mode не нужен await update.message.reply_text(f"Вы сказали: {update.message.text}") @@ -391,7 +423,7 @@ def main() -> None: application.add_handler(CommandHandler("start", start)) application.add_handler(CommandHandler("status", status)) application.add_handler(CommandHandler("stop_torrent", stop_torrent)) - application.add_handler(CommandHandler("help", help_command)) # Новая команда /help + application.add_handler(CommandHandler("help", help_command)) # --- Добавление обработчиков сообщений --- url_regex = r"magnet:\?xt=urn:[a-z0-9]+"