From 863f4eddbf3496a4b71e5f38bbcce7c8fa723229 Mon Sep 17 00:00:00 2001 From: qstokkink Date: Fri, 21 Feb 2025 13:18:42 +0100 Subject: [PATCH] Add stopping download after metadata functionality --- .../libtorrent/download_manager/download.py | 13 ++++++++++ .../download_manager/download_config.py | 13 ++++++++++ .../libtorrent/restapi/downloads_endpoint.py | 25 +++++++++++++------ src/tribler/ui/public/locales/en_US.json | 1 + src/tribler/ui/public/locales/es_ES.json | 1 + src/tribler/ui/public/locales/ko_KR.json | 1 + src/tribler/ui/public/locales/pt_BR.json | 1 + src/tribler/ui/public/locales/ru_RU.json | 1 + src/tribler/ui/public/locales/zh_CN.json | 1 + src/tribler/ui/src/dialogs/SaveAs.tsx | 14 +++++++++++ 10 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/tribler/core/libtorrent/download_manager/download.py b/src/tribler/core/libtorrent/download_manager/download.py index 665725ef7cc..4e538bb26b4 100644 --- a/src/tribler/core/libtorrent/download_manager/download.py +++ b/src/tribler/core/libtorrent/download_manager/download.py @@ -132,6 +132,9 @@ def __init__(self, # noqa: PLR0913 if self.download_manager.config.get("libtorrent/check_after_complete"): self.register_task("Recheck torrent after finish", self._recheck_after_finish) + if config and config.get_stop_after_metainfo(): + self.stop_after_metainfo() + alert_handlers = {"tracker_reply_alert": self.on_tracker_reply_alert, "tracker_error_alert": self.on_tracker_error_alert, "tracker_warning_alert": self.on_tracker_warning_alert, @@ -185,6 +188,16 @@ async def _recheck_after_finish(self) -> None: await self.future_finished self.force_recheck() + @task + async def stop_after_metainfo(self) -> None: + """ + Wait for the metadata to be received, then stop. + """ + self.config.set_stop_after_metainfo(True) # Persist between restarts + await self.future_metainfo + await self.stop() + self.config.set_stop_after_metainfo(False) # We succeeded without shutdown: no longer persist + def add_stream(self) -> None: """ Initialize a stream for this download. diff --git a/src/tribler/core/libtorrent/download_manager/download_config.py b/src/tribler/core/libtorrent/download_manager/download_config.py index 5515917f1d9..4422763b4ab 100644 --- a/src/tribler/core/libtorrent/download_manager/download_config.py +++ b/src/tribler/core/libtorrent/download_manager/download_config.py @@ -78,6 +78,7 @@ def write(self) -> None: ... # noqa: D102 add_download_to_channel = boolean(default=False) saveas = string(default=None) completed_dir = string(default=None) +stop_after_metainfo = boolean(default=False) [state] metainfo = string(default='ZGU=') @@ -312,3 +313,15 @@ def get_engineresumedata(self) -> dict | None: Get the engine resume data dict for this download or None if it cannot be decoded. """ return _to_dict(self.config["state"]["engineresumedata"]) + + def set_stop_after_metainfo(self, value: bool) -> None: + """ + Set the download to stop after receiving the metainfo. + """ + self.config["download_defaults"]["stop_after_metainfo"] = value + + def get_stop_after_metainfo(self) -> bool: + """ + Get whether the download should stop after receiving the metainfo. + """ + return self.config["download_defaults"].get("stop_after_metainfo", False) diff --git a/src/tribler/core/libtorrent/restapi/downloads_endpoint.py b/src/tribler/core/libtorrent/restapi/downloads_endpoint.py index 05a6db40b1f..04d406929c9 100644 --- a/src/tribler/core/libtorrent/restapi/downloads_endpoint.py +++ b/src/tribler/core/libtorrent/restapi/downloads_endpoint.py @@ -394,22 +394,29 @@ def _get_default_trackers(self) -> list[bytes]: summary="Start a download from a provided URI.", parameters=[{ "in": "query", - "name": "get_peers", - "description": "Flag indicating whether or not to include peers", - "type": "boolean", + "name": "anon_hops", + "description": "Number of hops for the anonymous download. No hops is equivalent to a plain download", + "type": "integer", "required": False }, { "in": "query", - "name": "get_pieces", - "description": "Flag indicating whether or not to include pieces", + "name": "safe_seeding", + "description": "Whether the seeding of the download should be anonymous or not", "type": "boolean", "required": False }, { "in": "query", - "name": "get_files", - "description": "Flag indicating whether or not to include files", + "name": "destination", + "description": "The download destination path of the torrent", + "type": "string", + "required": False + }, + { + "in": "query", + "name": "only_metadata", + "description": "Stop the download after the metadata has been received", "type": "boolean", "required": False }], @@ -423,7 +430,7 @@ def _get_default_trackers(self) -> list[bytes]: @json_schema(schema(AddDownloadRequest={ "anon_hops": (Integer, "Number of hops for the anonymous download. No hops is equivalent to a plain download"), "safe_seeding": (Boolean, "Whether the seeding of the download should be anonymous or not"), - "destination": (String, "the download destination path of the torrent"), + "destination": (String, "The download destination path of the torrent"), "uri*": (String, "The URI of the torrent file that should be downloaded. This URI can either represent a file " "location, a magnet link or a HTTP(S) url."), })) @@ -471,6 +478,8 @@ async def add_download(self, request: Request) -> RESTResponse: # noqa: C901, P if self.download_manager.config.get("libtorrent/download_defaults/trackers_file"): await download.get_handle() # We can only add trackers to a valid handle, wait for it. download.add_trackers(self._get_default_trackers()) + if params.get("only_metadata", "false") != "false": + download.stop_after_metainfo() except Exception as e: return RESTResponse({"error": { "handled": True, diff --git a/src/tribler/ui/public/locales/en_US.json b/src/tribler/ui/public/locales/en_US.json index e8ec4079adb..d6c68d528c1 100644 --- a/src/tribler/ui/public/locales/en_US.json +++ b/src/tribler/ui/public/locales/en_US.json @@ -26,6 +26,7 @@ "AlwaysAsk": "Always ask download settings", "DownloadAnon": "Download anonymously using proxies", "SeedAnon": "Encrypted anonymous seeding using proxies", + "StopAfterMetadata": "Stop download after metadata is received", "TorrentWatchFolder": "Torrent watch folder", "WatchFolder": "Watch Folder", "EnableWatchFolder": "Enable watch folder (requires restart)", diff --git a/src/tribler/ui/public/locales/es_ES.json b/src/tribler/ui/public/locales/es_ES.json index 2b54da13a24..9ae3a7bbb4f 100644 --- a/src/tribler/ui/public/locales/es_ES.json +++ b/src/tribler/ui/public/locales/es_ES.json @@ -26,6 +26,7 @@ "AlwaysAsk": "¿Preguntar siempre donde guardar las descargas?", "DownloadAnon": "Descarga anónima mediante proxies", "SeedAnon": "Siembra anónima cifrada mediante proxies", + "StopAfterMetadata": "Detener la descarga después de que se reciba los metadatos", "TorrentWatchFolder": "Carpeta de seguimiento de torrents", "WatchFolder": "Carpeta de seguimiento", "EnableWatchFolder": "Habilitar carpeta de vigilancia (es necesario reiniciar)", diff --git a/src/tribler/ui/public/locales/ko_KR.json b/src/tribler/ui/public/locales/ko_KR.json index 6344a593151..92f8f809d9d 100644 --- a/src/tribler/ui/public/locales/ko_KR.json +++ b/src/tribler/ui/public/locales/ko_KR.json @@ -26,6 +26,7 @@ "AlwaysAsk": "항상 내려받기 설정 확인", "DownloadAnon": "프록시를 사용하여 익명으로 내려받기", "SeedAnon": "프록시를 사용하여 암호화된 익명 시딩", + "StopAfterMetadata": "메타 데이터를받은 후 다운로드 중지", "TorrentWatchFolder": "토렌트 폴더 보기", "WatchFolder": "폴더 보기", "EnableWatchFolder": "감시 폴더 활성화(다시 시작해야 함)", diff --git a/src/tribler/ui/public/locales/pt_BR.json b/src/tribler/ui/public/locales/pt_BR.json index a91498e2a4d..22f99637715 100644 --- a/src/tribler/ui/public/locales/pt_BR.json +++ b/src/tribler/ui/public/locales/pt_BR.json @@ -26,6 +26,7 @@ "AlwaysAsk": "Sempre peça configurações de download", "DownloadAnon": "Baixe anonimamente usando proxies", "SeedAnon": "Semear anonimamente usando proxies", + "StopAfterMetadata": "Parar do download após os metadados forem recebidos", "TorrentWatchFolder": "Observar pasta torrent", "WatchFolder": "Monitoramento de pasta", "EnableWatchFolder": "Ativar pasta monitorada (requer reinicialização)", diff --git a/src/tribler/ui/public/locales/ru_RU.json b/src/tribler/ui/public/locales/ru_RU.json index beeb8b2e625..8165b6c3159 100644 --- a/src/tribler/ui/public/locales/ru_RU.json +++ b/src/tribler/ui/public/locales/ru_RU.json @@ -26,6 +26,7 @@ "AlwaysAsk": "Всегда спрашивать настройки закачки", "DownloadAnon": "Загружать торренты анонимно (через других участников)", "SeedAnon": "Раздавать торренты анонимно (через других участников)", + "StopAfterMetadata": "Остановите загрузку после получения метаданных", "TorrentWatchFolder": "Папка автоскачивания:", "WatchFolder": "Автоскачивание торрентов из папки", "EnableWatchFolder": "Включить папку просмотра (требуется перезагрузка)", diff --git a/src/tribler/ui/public/locales/zh_CN.json b/src/tribler/ui/public/locales/zh_CN.json index 41ebd1490ef..4b1adbb92f3 100644 --- a/src/tribler/ui/public/locales/zh_CN.json +++ b/src/tribler/ui/public/locales/zh_CN.json @@ -26,6 +26,7 @@ "AlwaysAsk": "总是询问下载设置", "DownloadAnon": "使用代理匿名下载", "SeedAnon": "使用代理加密地匿名做种", + "StopAfterMetadata": "收到元数据后停止下载", "TorrentWatchFolder": "种子监视文件夹", "WatchFolder": "监视文件夹", "EnableWatchFolder": "启用监视文件夹(需要重新启动)", diff --git a/src/tribler/ui/src/dialogs/SaveAs.tsx b/src/tribler/ui/src/dialogs/SaveAs.tsx index 774b27c0907..0ecf3dc55bf 100644 --- a/src/tribler/ui/src/dialogs/SaveAs.tsx +++ b/src/tribler/ui/src/dialogs/SaveAs.tsx @@ -290,6 +290,20 @@ export default function SaveAs(props: SaveAsProps & JSX.IntrinsicAttributes & Di {t('SeedAnon')} +
+
{warning && (