From ee32057c0b083cc82651eac47f7ce5eaa1052e4c Mon Sep 17 00:00:00 2001 From: MrZaiko Date: Sat, 19 Apr 2025 22:16:25 +0200 Subject: [PATCH] Fix torrent api bug --- .envrc | 2 + api/{qbittorrent.py => test.py} | 8 +-- api/torrent.py | 21 ++++-- main.py | 117 +++++++++++++++++++++----------- 4 files changed, 98 insertions(+), 50 deletions(-) create mode 100644 .envrc rename api/{qbittorrent.py => test.py} (76%) diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..93849bb --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +export VIRTUAL_ENV=venv +layout python3 diff --git a/api/qbittorrent.py b/api/test.py similarity index 76% rename from api/qbittorrent.py rename to api/test.py index 1772316..4c2458a 100644 --- a/api/qbittorrent.py +++ b/api/test.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 from qbittorrent import Client +from torrent import TorrentApi # Replace with your qBittorrent Web UI credentials -qb = Client('http://192.168.1.17:8112') -qb.login('admin', 'tMHNjrJr7nhjyhJrYsahi4anq2h6LJ') +torrent = TorrentApi("http://192.168.1.17:8112", "tMHNjrJr7nhjyhJrYsahi4anq2h6LJ") # Retrieve all active torrents -torrents = qb.torrents(filter='downloading') +torrents = torrent.get_torrents() # Print details of each active torrent for torrent in torrents: @@ -17,4 +17,4 @@ for torrent in torrents: print(f"Download Speed: {torrent['dlspeed'] / 1024:.2f} KB/s") print(f"Upload Speed: {torrent['upspeed'] / 1024:.2f} KB/s") print(f"Size: {torrent['size'] / (1024 * 1024):.2f} MB") - print('-' * 40) + print("-" * 40) diff --git a/api/torrent.py b/api/torrent.py index 62611ae..f48c387 100644 --- a/api/torrent.py +++ b/api/torrent.py @@ -2,26 +2,33 @@ from qbittorrent import Client + class TorrentApi: - def __init__(self, ip, password, username='admin'): + def __init__(self, ip, password, username="admin"): # Initialize the qBittorrent client self.qb = Client(ip) self.qb.login(username, password) def get_torrents(self): - return self.get_filtered_torrents('all') - + return self.get_filtered_torrents("all") + def get_filtered_torrents(self, state): + + self.qb.login() + # Retrieve torrents filtered by the given state torrents = self.qb.torrents(filter=state) # Extract relevant information torrent_list = [] for torrent in torrents: torrent_info = { - 'name': torrent['name'], - 'state': torrent['state'], - 'progress': torrent['progress'] * 100, # Convert to percentage - 'eta': torrent['eta'] + "name": torrent["name"], + "state": torrent["state"], + "progress": torrent["progress"] * 100, # Convert to percentage + "eta": torrent["eta"], + "upspeed": torrent["upspeed"], + "dlspeed": torrent["dlspeed"], + "size": torrent["size"], } torrent_list.append(torrent_info) return torrent_list diff --git a/main.py b/main.py index 8bbb858..789a665 100644 --- a/main.py +++ b/main.py @@ -10,92 +10,124 @@ import api.torrent as torrent TOKEN = "7396669954:AAH8_I0Y-qg3j_LfbUdRTOLPDKh80NdijMo" + # --- Menu Definitions --- def main_menu_keyboard(): - return InlineKeyboardMarkup([ - [InlineKeyboardButton("Torrents", callback_data='status_downloading')], - [InlineKeyboardButton("Status", callback_data='menu_status')] - ]) + return InlineKeyboardMarkup( + [ + [InlineKeyboardButton("Torrents", callback_data="status_downloading")], + [InlineKeyboardButton("Status", callback_data="menu_status")], + ] + ) + def torrents_menu_keyboard(): - return InlineKeyboardMarkup([ - # First row: Display the status counts for downloading, paused, seeding - [InlineKeyboardButton(f"Downloading", callback_data='status_downloading')], - [InlineKeyboardButton(f"Active", callback_data='status_active')], - [InlineKeyboardButton(f"All", callback_data='status_all')], - # Second row: Back button - [InlineKeyboardButton("πŸ”™ Back", callback_data='menu_main')] - ]) + return InlineKeyboardMarkup( + [ + # First row: Display the status counts for downloading, paused, seeding + [InlineKeyboardButton(f"Downloading", callback_data="status_downloading")], + [InlineKeyboardButton(f"Active", callback_data="status_active")], + [InlineKeyboardButton(f"All", callback_data="status_all")], + # Second row: Back button + [InlineKeyboardButton("πŸ”™ Back", callback_data="menu_main")], + ] + ) + def status_menu_keyboard(): - return InlineKeyboardMarkup([ - [InlineKeyboardButton("πŸ”™ Back", callback_data='menu_main')] - ]) + return InlineKeyboardMarkup( + [[InlineKeyboardButton("πŸ”™ Back", callback_data="menu_main")]] + ) + # --- Command Handlers --- async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: - await update.message.reply_text("Choose an option:", reply_markup=main_menu_keyboard()) + try: + await update.message.reply_text( + "Choose an option:", reply_markup=main_menu_keyboard() + ) + except Exception as e: + await update.message.reply_text(f"An error occurred: {e}") + # Optionally log the error + print(f"Error: {e}") def format_torrents(torrents): if len(torrents) == 0: return "No torrents." - + text = "" i = 0 for torrent in torrents: - if i > 10: + if i > 5: text += "...\n" return text - + + text += f"Name: {torrent['name']}\n" + text += f"State: {torrent['state']}\n" + text += f"Progress: {torrent['progress']:.2f}%\n" + text += f"ETA: {torrent['eta']}\n" + text += "-" * 20 + "\n" + text += f"- {torrent['name']} - {torrent['progress']} ({torrent['eta']})\n" i += 1 return text + # --- Callback Query Handler --- async def handle_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: query = update.callback_query await query.answer() match query.data: - case 'menu_main': - await query.edit_message_text("Choose an option:", reply_markup=main_menu_keyboard()) + case "menu_main": + await query.edit_message_text( + "Choose an option:", reply_markup=main_menu_keyboard() + ) - case 'status_downloading': + case "status_downloading": t_api = context.bot_data.get("torrent_api", {}) torrents = t_api.get_filtered_torrents("downloading") - text = format_torrents(torrents) - + if len(torrents) == 0: + text = "No downloading torrents." + else: + text = format_torrents(torrents) + await query.edit_message_text(text, reply_markup=torrents_menu_keyboard()) - case 'status_active': + case "status_active": t_api = context.bot_data.get("torrent_api", {}) torrents = t_api.get_filtered_torrents("active") - text = format_torrents(torrents) + if len(torrents) == 0: + text = "No active torrents." + else: + text = format_torrents(torrents) await query.edit_message_text(text, reply_markup=torrents_menu_keyboard()) - - case 'status_all': + case "status_all": t_api = context.bot_data.get("torrent_api", {}) torrents = t_api.get_filtered_torrents("all") - text = format_torrents(torrents) + if len(torrents) == 0: + text = "No torrents." + else: + text = format_torrents(torrents) await query.edit_message_text(text, reply_markup=torrents_menu_keyboard()) - - case 'menu_status': + + case "menu_status": k_api = context.bot_data.get("kuma_api", {}) monitors = k_api.get_status() up_text, down_text, paused_text = "", "", "" for _, monitor in monitors.items(): - status = monitor['status'] - + status = monitor["status"] + if status == MonitorStatus.UP: up_text += f" - {monitor['name']}\n" elif status == MonitorStatus.DOWN: @@ -103,21 +135,27 @@ async def handle_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non else: paused_text += f" - {monitor['name']}\n" - status_text = f"πŸ“‘ *Status:*\n\n 🟒 Up:\n{up_text}\nπŸ”΄ Down\n{down_text}\n⏸️ Paused\n{paused_text}" - - await query.edit_message_text(status_text, reply_markup=status_menu_keyboard()) + + await query.edit_message_text( + status_text, reply_markup=status_menu_keyboard() + ) case _: - await query.edit_message_text("Unknown option selected.", reply_markup=main_menu_keyboard()) + await query.edit_message_text( + "Unknown option selected.", reply_markup=main_menu_keyboard() + ) + # --- Main Function --- def main(): print("Starting Jarvis...") - + # Initiate api kuma_api = kuma.KumaAPI("http://192.168.1.2:36667", "k!PTfyvoIJho9o*gX6F1") - torrent_api = torrent.TorrentApi("http://192.168.1.17:8112", "tMHNjrJr7nhjyhJrYsahi4anq2h6LJ") + torrent_api = torrent.TorrentApi( + "http://192.168.1.17:8112", "tMHNjrJr7nhjyhJrYsahi4anq2h6LJ" + ) app = Application.builder().token(TOKEN).build() app.bot_data["kuma_api"] = kuma_api @@ -129,5 +167,6 @@ def main(): print("Bot is running... Press Ctrl+C to stop.") app.run_polling() + if __name__ == "__main__": main()