import requests from loguru import logger from dataService.dto.SeedInfo import SeedInfo # 请求超时: (连接超时, 读取超时),防止 qBittorrent 不可达时程序卡死 REQUEST_TIMEOUT = (5, 15) class QbittorrentDownloader: """使用 qBittorrent Web API 进行下载""" def __init__(self, host="192.168.123.199", api_port=8085, username="admin", password="GUOxy.5157"): """ 初始化 qBittorrent 下载器 Args: host: qBittorrent 主机地址 api_port: qBittorrent Web API 端口 username: 用户名(如果启用用户认证) password: 密码(如果启用用户认证) """ self.host = host self.api_port = api_port self.username = username self.password = password self.api_base_url = f"http://{host}:{api_port}/api/v2" # 创建 session 并进行登录 self.session = requests.Session() if username and password: self._login() def _login(self): """登录 qBittorrent 并获取 session cookie""" login_url = f"{self.api_base_url}/auth/login" try: response = self.session.post(login_url, data={"username": self.username, "password": self.password}, timeout=REQUEST_TIMEOUT) if response.status_code == 200: logger.debug("qBittorrent 登录成功") else: logger.warning(f"qBittorrent 登录失败,状态码: {response.status_code}") except Exception as e: logger.error(f"qBittorrent 登录异常: {str(e)}") def download_by_magnet(self, magnet_url, save_path="", category="", tags=""): """ 通过 magnet 链接添加下载任务 Args: magnet_url: magnet 链接 save_path: 保存路径 category: 下载分类 tags: 下载标签 Returns: str: "1"表示成功,"0"表示失败,"-1"表示请求异常 """ add_url = f"{self.api_base_url}/torrents/add" # 构造添加下载的参数 form_data = { 'urls': magnet_url } # 如果有保存路径、分类或标签,添加到表单数据 if save_path: form_data['savepath'] = save_path if category: form_data['category'] = category if tags: form_data['tags'] = tags logger.debug(f"开始向 qBittorrent 添加下载任务,magnet 链接: {magnet_url}") try: response = self.session.post(add_url, data=form_data, timeout=REQUEST_TIMEOUT) if response.status_code == 200: logger.info(f"请求成功,magnet 链接 {magnet_url} 已添加至下载队列") return "1" else: logger.warning( f"请求返回非200状态码,magnet 链接 {magnet_url} 添加失败。状态码: {response.status_code}, 响应: {response.text}" ) return "-1" # 请求成功,但失败了 except Exception as e: logger.error( f"请求过程中出现异常,magnet 链接 {magnet_url} 添加失败。错误信息: {str(e)}" ) return "0" # 请求过程中发生异常 def download_by_seed(self, seed_info: SeedInfo, save_path="", category="", tags=""): """ 通过种子信息添加下载任务(主要处理 magnet 链接) Args: seed_info: 种子信息对象 save_path: 保存路径 category: 下载分类 tags: 下载标签 Returns: str: "1"表示成功,"0"表示失败,"-1"表示请求异常 """ # seedInfo 中的 seedUrl 应该是 magnet 链接 if not seed_info.seedUrl: logger.error("种子信息中缺少种子链接 (seedUrl)") return "0" return self.download_by_magnet( seed_info.seedUrl, save_path=save_path, category=category, tags=tags ) def test_connection(self): """ 测试与 qBittorrent 的连接 Returns: bool: 连接成功返回 True,否则返回 False """ try: version_url = f"{self.api_base_url}/app/version" response = self.session.get(version_url, timeout=REQUEST_TIMEOUT) if response.status_code == 200: logger.info(f"qBittorrent 连接成功,版本: {response.text}") return True else: logger.error(f"qBittorrent 连接失败,状态码: {response.status_code}") return False except Exception as e: logger.error(f"qBittorrent 连接测试异常: {str(e)}") return False def get_downloads(self): """ 获取当前下载列表 Returns: list: 下载任务列表 """ try: torrents_url = f"{self.api_base_url}/torrents/info" response = self.session.get(torrents_url, timeout=REQUEST_TIMEOUT) if response.status_code == 200: return response.json() else: logger.error(f"获取下载列表失败,状态码: {response.status_code}") return [] except Exception as e: logger.error(f"获取下载列表异常: {str(e)}") return []