From af1c76b3155aa25d9f474b3253e73fc41ad047b2 Mon Sep 17 00:00:00 2001 From: KotaHv <92137267+KotaHv@users.noreply.github.com> Date: Tue, 28 May 2024 11:51:25 +0800 Subject: [PATCH] fix: Mikan some torrents are not a valid torrent file --- backend/requirements.txt | 2 ++ .../src/module/downloader/download_client.py | 34 ++++++++++++++++--- .../src/module/network/request_contents.py | 8 +++++ backend/src/module/utils/__init__.py | 3 +- backend/src/module/utils/torrent.py | 11 ++++++ 5 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 backend/src/module/utils/torrent.py diff --git a/backend/requirements.txt b/backend/requirements.txt index 02ed21578..ec4be9699 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -27,3 +27,5 @@ sqlmodel==0.0.8 sse-starlette==1.6.5 semver==3.0.1 openai==0.28.1 +torrentool==1.2.0 +lxml==5.2.2 diff --git a/backend/src/module/downloader/download_client.py b/backend/src/module/downloader/download_client.py index d01d4fa3c..609e8d96e 100644 --- a/backend/src/module/downloader/download_client.py +++ b/backend/src/module/downloader/download_client.py @@ -1,8 +1,11 @@ import logging +from lxml import etree + from module.conf import settings from module.models import Bangumi, Torrent from module.network import RequestContent +from module.utils import check_torrent from .path import TorrentPath @@ -118,23 +121,44 @@ def add_torrent(self, torrent: Torrent | list, bangumi: Bangumi) -> bool: if not bangumi.save_path: bangumi.save_path = self._gen_save_path(bangumi) with RequestContent() as req: + + def get_torrent_or_magnet(_torrent: Torrent): + content = req.get_content(_torrent.url) + if check_torrent(content): + return content, None + if _torrent.homepage: + magnet = req.get_magnet(_torrent.homepage) + if magnet: + return None, magnet + logger.error( + f'[Downloader] {_torrent.name} torrent is corrupted; it is recommended to manually add the magnet link to qBittorrent, with the save path: "{bangumi.save_path}".' + ) + return None, None + if isinstance(torrent, list): if len(torrent) == 0: - logger.debug(f"[Downloader] No torrent found: {bangumi.official_title}") + logger.debug( + f"[Downloader] No torrent found: {bangumi.official_title}" + ) return False if "magnet" in torrent[0].url: torrent_url = [t.url for t in torrent] torrent_file = None else: - torrent_file = [req.get_content(t.url) for t in torrent] - torrent_url = None + torrent_file = [] + torrent_url = [] + for t in torrent: + file, magnet = get_torrent_or_magnet(t) + if file: + torrent_file.append(file) + if magnet: + torrent_url.append(magnet) else: if "magnet" in torrent.url: torrent_url = torrent.url torrent_file = None else: - torrent_file = req.get_content(torrent.url) - torrent_url = None + torrent_file, torrent_url = get_torrent_or_magnet(torrent) if self.client.add_torrents( torrent_urls=torrent_url, torrent_files=torrent_file, diff --git a/backend/src/module/network/request_contents.py b/backend/src/module/network/request_contents.py index 05abca023..4d3a74416 100644 --- a/backend/src/module/network/request_contents.py +++ b/backend/src/module/network/request_contents.py @@ -2,6 +2,8 @@ import re import xml.etree.ElementTree +from lxml import etree + from module.conf import settings from module.models import Torrent @@ -73,3 +75,9 @@ def get_rss_title(self, _url): soup = self.get_xml(_url) if soup: return soup.find("./channel/title").text + + def get_magnet(self, _url) -> str | None: + html = etree.HTML(self.get_html(_url)) + magnet = html.xpath('//a[starts-with(@href, "magnet")]/@href') + if magnet: + return magnet[0] diff --git a/backend/src/module/utils/__init__.py b/backend/src/module/utils/__init__.py index a95499d60..75a082393 100644 --- a/backend/src/module/utils/__init__.py +++ b/backend/src/module/utils/__init__.py @@ -1 +1,2 @@ -from .cache_image import save_image, load_image \ No newline at end of file +from .cache_image import save_image, load_image +from .torrent import check_torrent diff --git a/backend/src/module/utils/torrent.py b/backend/src/module/utils/torrent.py new file mode 100644 index 000000000..10cee08a7 --- /dev/null +++ b/backend/src/module/utils/torrent.py @@ -0,0 +1,11 @@ +from torrentool.bencode import Bencode +from torrentool.exceptions import BencodeDecodingError + + +def check_torrent(content: bytes) -> bool: + try: + if Bencode.decode(content): + return True + return False + except BencodeDecodingError: + return False