diff --git a/src/tribler/core/libtorrent/download_manager/download.py b/src/tribler/core/libtorrent/download_manager/download.py index 0dc553adc5..4e538bb26b 100644 --- a/src/tribler/core/libtorrent/download_manager/download.py +++ b/src/tribler/core/libtorrent/download_manager/download.py @@ -129,6 +129,12 @@ def __init__(self, # noqa: PLR0913 self.future_finished = self.wait_for_alert("torrent_finished_alert") self.future_metainfo = self.wait_for_alert("metadata_received_alert", lambda a: self.tdef.get_metainfo()) + 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, @@ -173,6 +179,25 @@ def __repr__(self) -> str: """ return self.__str__() + async def _recheck_after_finish(self) -> None: + """ + Wait for the torrent to finish downloading, then recheck. + + Note: a finished recheck causes a ``torrent_finished_alert``: hooking into that causes an infinite loop! + """ + 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 5515917f1d..878ea4e2d0 100644 --- a/src/tribler/core/libtorrent/download_manager/download_config.py +++ b/src/tribler/core/libtorrent/download_manager/download_config.py @@ -31,6 +31,7 @@ class DownloadConfigDefaultsSection(TypedDict): add_download_to_channel: bool saveas: str | None completed_dir: str | None + stop_after_metainfo: bool class StateConfigSection(TypedDict): @@ -78,6 +79,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 +314,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 05a6db40b1..04d406929c 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/test_unit/core/libtorrent/download_manager/test_download.py b/src/tribler/test_unit/core/libtorrent/download_manager/test_download.py index baa7947f24..058b8f9a6b 100644 --- a/src/tribler/test_unit/core/libtorrent/download_manager/test_download.py +++ b/src/tribler/test_unit/core/libtorrent/download_manager/test_download.py @@ -16,6 +16,7 @@ from tribler.core.libtorrent.torrentdef import TorrentDef, TorrentDefNoMetainfo from tribler.core.notifier import Notification, Notifier from tribler.test_unit.core.libtorrent.mocks import TORRENT_UBUNTU_FILE_CONTENT, TORRENT_WITH_DIRS_CONTENT +from tribler.test_unit.mocks import MockTriblerConfigManager class PermissionErrorDownloadConfig(DownloadConfig): @@ -36,6 +37,8 @@ class TestDownload(TestBase): Tests for the Download class. """ + dlmngr = Mock(config=MockTriblerConfigManager()) + def create_mock_download_config(self) -> DownloadConfig: """ Create a mocked DownloadConfig. @@ -52,8 +55,8 @@ def test_download_get_magnet_link_no_handle(self) -> None: """ Test if a download without a handle does not have a magnet link. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertIsNone(download.get_magnet_link()) @@ -61,8 +64,8 @@ def test_download_get_atp(self) -> None: """ Test if the atp can be retrieved from a download. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) atp = download.get_atp() @@ -75,8 +78,8 @@ def test_download_resume(self) -> None: """ Test if a download can be resumed. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) download.resume() @@ -89,8 +92,8 @@ async def test_save_resume(self) -> None: """ Test if a download is resumed after fetching the save/resume data. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.futures["save_resume_data"] = succeed(True) future = ensure_future(download.save_resume_data()) @@ -105,8 +108,8 @@ def test_move_storage(self) -> None: """ Test if storage can be moved. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) success = download.move_storage(Path("some_path")) @@ -119,7 +122,7 @@ def test_move_storage_no_metainfo(self) -> None: """ Test if storage is not moved for torrents without metainfo. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -133,7 +136,7 @@ async def test_save_checkpoint_disabled(self) -> None: """ Test if checkpoints are not saved if checkpointing is disabled. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=False)) @@ -145,7 +148,7 @@ async def test_save_checkpoint_handle_no_data(self) -> None: """ Test if checkpoints are not saved if the handle specifies that it does not need resume data. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.checkpoint_disabled = False download.handle = Mock(is_valid=Mock(return_value=True), need_save_resume_data=Mock(return_value=False)) @@ -159,7 +162,7 @@ async def test_save_checkpoint_no_handle_no_existing(self) -> None: Test if checkpoints are saved for torrents without a handle and no existing checkpoint file. """ alerts = [] - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.checkpoint_disabled = False download.download_manager = Mock(get_checkpoint_dir=Mock(return_value=Path("foo"))) @@ -180,7 +183,7 @@ async def test_save_checkpoint_no_handle_existing(self) -> None: Test if existing checkpoints are not overwritten by checkpoints without data. """ alerts = [] - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.checkpoint_disabled = False download.download_manager = Mock(get_checkpoint_dir=Mock(return_value=Path("foo"))) @@ -197,7 +200,7 @@ def test_selected_files_default(self) -> None: """ Test if the default selected files are no files. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(file_priorities=Mock(return_value=[0, 0])) @@ -208,7 +211,7 @@ def test_selected_files_last(self) -> None: """ Test if the last selected file in a list of files gets correctly selected. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(file_priorities=Mock(return_value=[0, 4])) @@ -221,8 +224,8 @@ def test_selected_files_first(self) -> None: """ Test if the first selected file in a list of files gets correctly selected. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(file_priorities=Mock(return_value=[4, 0])) download.set_selected_files([0]) @@ -234,8 +237,8 @@ def test_selected_files_all(self) -> None: """ Test if all files can be selected. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(file_priorities=Mock(return_value=[4, 4])) download.set_selected_files([0, 1]) @@ -247,8 +250,8 @@ def test_selected_files_all_through_none(self) -> None: """ Test if all files can be selected by selecting None. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(file_priorities=Mock(return_value=[4, 4])) download.set_selected_files() @@ -260,8 +263,8 @@ def test_selected_files_all_through_empty_list(self) -> None: """ Test if all files can be selected by selecting an empty list. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(file_priorities=Mock(return_value=[4, 4])) download.set_selected_files([]) @@ -273,7 +276,7 @@ def test_get_share_mode_enabled(self) -> None: """ Test if we forward the enabled share mode when requested in the download. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.config.set_share_mode(True) @@ -283,7 +286,7 @@ def test_get_share_mode_disabled(self) -> None: """ Test if we forward the disabled share mode when requested in the download. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.config.set_share_mode(False) @@ -293,7 +296,7 @@ async def test_enable_share_mode(self) -> None: """ Test if the share mode can be enabled in a download. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -307,7 +310,7 @@ async def test_disable_share_mode(self) -> None: """ Test if the share mode can be disabled in a download. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -321,7 +324,7 @@ def test_get_num_connected_seeds_peers_no_handle(self) -> None: """ Test if connected peers and seeds are 0 if there is no handle. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) num_seeds, num_peers = download.get_num_connected_seeds_peers() @@ -333,7 +336,7 @@ def test_get_num_connected_seeds_peers(self) -> None: """ Test if connected peers and seeds are correctly returned. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True), get_peer_info=Mock(return_value=[ Mock(flags=140347, seed=1024), @@ -350,7 +353,7 @@ async def test_set_priority(self) -> None: """ Test if setting the priority calls the right methods in download. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -363,7 +366,7 @@ def test_add_trackers(self) -> None: """ Test if trackers are added to the libtorrent handle. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -376,7 +379,7 @@ def test_process_error_alert(self) -> None: """ Test if error alerts are processed correctly. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.process_alert(Mock(msg=None, status_code=123, url="http://google.com", @@ -389,7 +392,7 @@ def test_process_error_alert_timeout(self) -> None: """ Test if timeout error alerts are processed correctly. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.process_alert(Mock(msg=None, status_code=0, url="http://google.com", @@ -402,7 +405,7 @@ def test_process_error_alert_not_working(self) -> None: """ Test if not working error alerts are processed correctly. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.process_alert(Mock(msg=None, status_code=-1, url="http://google.com", @@ -415,7 +418,7 @@ def test_tracker_warning_alert(self) -> None: """ Test if a tracking warning alert is processed correctly. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.process_alert(Mock(message=Mock(return_value="test"), url="http://google.com", @@ -429,7 +432,7 @@ async def test_on_metadata_received_alert(self) -> None: Test if the right operations happen when we receive metadata. """ tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) - download = Download(tdef, None, checkpoint_disabled=True, config=self.create_mock_download_config()) + download = Download(tdef, self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(torrent_file=Mock(return_value=download.tdef.torrent_info), trackers=Mock(return_value=[{"url": "http://google.com"}])) download.tdef = None @@ -445,7 +448,7 @@ def test_on_metadata_received_alert_unicode_error_encode(self) -> None: Test if no exception is raised when the url is not unicode compatible. """ tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) - download = Download(tdef, None, checkpoint_disabled=True, config=self.create_mock_download_config()) + download = Download(tdef, self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(trackers=Mock(return_value=[{"url": "\uD800"}]), torrent_file=Mock(return_value=download.tdef.torrent_info), get_peer_info=Mock(return_value=[])) @@ -464,7 +467,7 @@ def test_on_metadata_received_alert_unicode_error_decode(self) -> None: See: https://github.com/Tribler/tribler/issues/7223 """ tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) - download = Download(tdef, None, checkpoint_disabled=True, config=self.create_mock_download_config()) + download = Download(tdef, self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(trackers=lambda: [{"url": b"\xFD".decode()}], torrent_file=Mock(return_value=download.tdef.torrent_info), get_peer_info=Mock(return_value=[])) @@ -481,7 +484,7 @@ def test_metadata_received_invalid_torrent_with_error(self) -> None: Test if no torrent def is loaded when a RuntimeError/ValueError occurs when parsing the metadata. """ tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) - download = Download(tdef, None, checkpoint_disabled=True, config=self.create_mock_download_config()) + download = Download(tdef, self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(trackers=Mock(return_value=[]), torrent_file=Mock(return_value=Mock(metadata=Mock(return_value=b""))), get_peer_info=Mock(return_value=[])) @@ -495,7 +498,7 @@ def test_torrent_checked_alert_no_pause_no_checkpoint(self) -> None: """ Test if no pause or checkpoint happens if the download state is such. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.checkpoint_disabled = False download.handle = Mock(is_valid=Mock(return_value=True), need_save_resume_data=Mock(return_value=False)) @@ -513,7 +516,7 @@ def test_torrent_checked_alert_no_pause_checkpoint(self) -> None: """ Test if no pause but a checkpoint happens if the download state is such. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.checkpoint_disabled = False download.handle = Mock(is_valid=Mock(return_value=True), need_save_resume_data=Mock(return_value=False)) @@ -531,7 +534,7 @@ def test_torrent_checked_alert_pause_no_checkpoint(self) -> None: """ Test if a pause but no checkpoint happens if the download state is such. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.checkpoint_disabled = False download.handle = Mock(is_valid=Mock(return_value=True), need_save_resume_data=Mock(return_value=False)) @@ -549,7 +552,7 @@ def test_torrent_checked_alert_pause_checkpoint(self) -> None: """ Test if both a pause and a checkpoint happens if the download state is such. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.checkpoint_disabled = False download.handle = Mock(is_valid=Mock(return_value=True), need_save_resume_data=Mock(return_value=False)) @@ -567,7 +570,7 @@ def test_tracker_reply_alert(self) -> None: """ Test if the tracker status is extracted from a reply alert. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.on_tracker_reply_alert(Mock(url="http://google.com", num_peers=42)) @@ -578,7 +581,7 @@ def test_get_pieces_bitmask(self) -> None: """ Test if a correct pieces bitmask is returned when requested. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(status=Mock(return_value=Mock(pieces=[True, False, True, False, False]))) @@ -588,7 +591,7 @@ async def test_resume_data_failed(self) -> None: """ Test if an error is raised when loading resume data failed. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) future = download.wait_for_alert("save_resume_data_alert", None, "save_resume_data_failed_alert", @@ -602,7 +605,7 @@ async def test_on_state_changed_apply_ip_filter(self) -> None: """ Test if the ip filter gets enabled when in torrent status seeding (5) when hops are not zero. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.config.set_hops(1) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -616,7 +619,7 @@ async def test_on_state_changed_no_filter(self) -> None: """ Test if the ip filter does not get enabled when the hop count is zero. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.config.set_hops(0) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -630,7 +633,7 @@ async def test_on_state_changed_not_seeding(self) -> None: """ Test if the ip filter does not get enabled when the hop count is zero. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.config.set_hops(1) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -644,7 +647,7 @@ async def test_checkpoint_timeout(self) -> None: """ Testing whether making a checkpoint times out when we receive no alert from libtorrent. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.futures["save_resume_data"] = [Future()] @@ -659,7 +662,7 @@ def test_on_save_resume_data_alert_permission_denied(self) -> None: """ Test if permission error in writing the download config does not crash the save resume alert handler. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=PermissionErrorDownloadConfig(self.create_mock_download_config().config)) download.checkpoint_disabled = False download.download_manager = Mock(get_checkpoint_dir=Mock(return_value=Path(__file__).absolute().parent)) @@ -675,7 +678,7 @@ async def test_get_tracker_status_unicode_decode_error(self) -> None: See: https://github.com/Tribler/tribler/issues/7036 """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) fut = Future() fut.set_result(Mock(is_dht_running=Mock(return_value=False))) @@ -694,7 +697,7 @@ def test_get_tracker_status_get_peer_info_error(self) -> None: """ Test if a tracker status is returned when getting peer info leads to a RuntimeError. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.download_manager = Mock(get_session=Mock(return_value=Mock(is_dht_running=Mock(return_value=True)))) download.handle = Mock(is_valid=Mock(return_value=True), get_peer_info=Mock(side_effect=RuntimeError), @@ -709,7 +712,7 @@ async def test_shutdown(self) -> None: """ Test if the shutdown method closes the stream and clears the futures dictionary. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name"), self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) download.stream = Mock() @@ -722,8 +725,8 @@ def test_file_piece_range_flat(self) -> None: """ Test if the piece range of a single-file torrent is correctly determined. """ - download = Download(TorrentDef.load_from_memory(TORRENT_UBUNTU_FILE_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_UBUNTU_FILE_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) total_pieces = download.tdef.torrent_info.num_pieces() piece_range = download.file_piece_range(Path("ubuntu-15.04-desktop-amd64.iso")) @@ -734,8 +737,8 @@ def test_file_piece_range_minifiles(self) -> None: """ Test if the piece range of a file is correctly determined if multiple files exist in the same piece. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) piece_range_a = download.file_piece_range(Path("torrent_create") / "abc" / "file2.txt") piece_range_b = download.file_piece_range(Path("torrent_create") / "abc" / "file3.txt") @@ -749,7 +752,7 @@ def test_file_piece_range_wide(self) -> None: tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) tdef.metainfo[b"info"][b"files"][0][b"length"] = 60000 tdef.metainfo[b"info"][b"pieces"] = b'\x01' * 80 - download = Download(tdef, None, checkpoint_disabled=True, config=self.create_mock_download_config()) + download = Download(tdef, self.dlmngr, checkpoint_disabled=True, config=self.create_mock_download_config()) file1 = download.file_piece_range(Path("torrent_create") / "abc" / "file2.txt") other_indices = [download.file_piece_range(Path("torrent_create") / Path( @@ -764,8 +767,8 @@ def test_file_piece_range_nonexistent(self) -> None: """ Test if the piece range of a non-existent file is correctly determined. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) piece_range = download.file_piece_range(Path("I don't exist")) @@ -775,8 +778,8 @@ def test_file_completion_full(self) -> None: """ Test if a complete file shows 1.0 completion. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True), have_piece=Mock(return_value=True)) self.assertEqual(1.0, download.get_file_completion(Path("torrent_create") / "abc" / "file2.txt")) @@ -785,8 +788,8 @@ def test_file_completion_nonexistent(self) -> None: """ Test if an unknown path (does not exist in a torrent) shows 1.0 completion. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) self.assertEqual(1.0, download.get_file_completion(Path("I don't exist"))) @@ -795,8 +798,8 @@ def test_file_completion_directory(self) -> None: """ Test if a directory (does not exist in a torrent) shows 1.0 completion. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True), have_piece=Mock(return_value=True)) self.assertEqual(1.0, download.get_file_completion(Path("torrent_create"))) @@ -805,8 +808,8 @@ def test_file_completion_nohandle(self) -> None: """ Test if a file shows 0.0 completion if the torrent handle is not valid. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=False), have_piece=Mock(return_value=True)) self.assertEqual(0.0, download.get_file_completion(Path("torrent_create") / "abc" / "file2.txt")) @@ -815,8 +818,8 @@ def test_file_completion_partial(self) -> None: """ Test if a file shows 0.0 completion if the torrent handle is not valid. """ - download = Download(TorrentDef.load_from_memory(TORRENT_UBUNTU_FILE_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_UBUNTU_FILE_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) total_pieces = download.tdef.torrent_info.num_pieces() expected = (total_pieces // 2) / total_pieces @@ -833,8 +836,8 @@ def test_file_length(self) -> None: """ Test if we can get the length of a file. """ - download = Download(TorrentDef.load_from_memory(TORRENT_UBUNTU_FILE_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_UBUNTU_FILE_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertEqual(1150844928, download.get_file_length(Path("ubuntu-15.04-desktop-amd64.iso"))) @@ -842,8 +845,8 @@ def test_file_length_two(self) -> None: """ Test if we can get the length of a file in a multi-file torrent. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertEqual(6, download.get_file_length(Path("torrent_create") / "abc" / "file2.txt")) self.assertEqual(6, download.get_file_length(Path("torrent_create") / "abc" / "file3.txt")) @@ -852,8 +855,8 @@ def test_file_length_nonexistent(self) -> None: """ Test if the length of a non-existent file is 0. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertEqual(0, download.get_file_length(Path("I don't exist"))) @@ -861,8 +864,8 @@ def test_file_index_unloaded(self) -> None: """ Test if a non-existent path leads to the special unloaded index. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertEqual(IllegalFileIndex.unloaded.value, download.get_file_index(Path("I don't exist"))) @@ -870,8 +873,8 @@ def test_file_index_directory_collapsed(self) -> None: """ Test if a collapsed-dir path leads to the special collapsed dir index. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertEqual(IllegalFileIndex.collapsed_dir.value, download.get_file_index(Path("torrent_create"))) @@ -879,8 +882,8 @@ def test_file_index_directory_expanded(self) -> None: """ Test if an expanded-dir path leads to the special expanded dir index. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.tdef.torrent_file_tree.expand(Path("torrent_create")) self.assertEqual(IllegalFileIndex.expanded_dir.value, download.get_file_index(Path("torrent_create"))) @@ -889,8 +892,8 @@ def test_file_index_file(self) -> None: """ Test if we can get the index of a file. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertEqual(1, download.get_file_index(Path("torrent_create") / "abc" / "file3.txt")) @@ -898,8 +901,8 @@ def test_file_selected_nonexistent(self) -> None: """ Test if a non-existent file does not register as selected. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertFalse(download.is_file_selected(Path("I don't exist"))) @@ -907,8 +910,8 @@ def test_file_selected_realfile(self) -> None: """ Test if a file starts off as selected. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertTrue(download.is_file_selected(Path("torrent_create") / "abc" / "file3.txt")) @@ -916,8 +919,8 @@ def test_file_selected_directory(self) -> None: """ Test if a directory does not register as selected. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.assertFalse(download.is_file_selected(Path("torrent_create") / "abc")) @@ -926,8 +929,8 @@ def test_on_torrent_finished_alert(self) -> None: Test if the torrent_finished notification is called when the torrent finishes. """ callback = Mock() - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, + checkpoint_disabled=True, config=self.create_mock_download_config()) download.stream = Mock() download.handle = Mock(is_valid=Mock(return_value=True), status=Mock(return_value=Mock(total_download=7))) download.notifier = Notifier() diff --git a/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py b/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py index a7516f4e4f..2a054590c7 100644 --- a/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py +++ b/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py @@ -63,7 +63,7 @@ async def test_get_metainfo_valid_metadata(self) -> None: """ Testing if the metainfo is retrieved when the handle has valid metadata immediately. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True)) download.get_state = Mock(return_value=Mock(get_num_seeds_peers=Mock(return_value=(42, 7)))) @@ -91,7 +91,7 @@ async def test_get_metainfo_duplicate_request(self) -> None: """ Test if the same request is returned when invoking get_metainfo twice with the same infohash. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True)) config = DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT))) @@ -116,7 +116,7 @@ async def test_get_metainfo_with_already_added_torrent(self) -> None: """ Test if metainfo can be fetched for a torrent which is already in session. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True)) self.manager.downloads[download.tdef.infohash] = download @@ -127,7 +127,7 @@ async def test_start_download_while_getting_metainfo(self) -> None: """ Test if a torrent can be added while a metainfo request is running. """ - info_download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + info_download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=self.create_mock_download_config()) info_download.handle = Mock(is_valid=Mock(return_value=True)) self.manager.downloads[info_download.tdef.infohash] = info_download @@ -163,7 +163,7 @@ async def test_start_handle_wait_for_dht_timeout(self) -> None: """ Test if start handle waits no longer than the set timeout for the DHT to be ready. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) self.manager.dht_ready_task = Future() @@ -175,7 +175,7 @@ async def test_start_handle_wait_for_dht(self) -> None: """ Test if start handle waits for the DHT to be ready. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) self.manager.dht_ready_task = Future() @@ -191,7 +191,7 @@ async def test_start_handle_empty_save_path(self) -> None: """ Test if the "save_path" is always set in the resume_data, otherwise we SEGFAULT on win32! """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=self.create_mock_download_config()) download.handle = Mock(is_valid=Mock(return_value=True)) self.manager.get_session = AsyncMock(return_value=Mock(get_torrents=Mock(return_value=[]))) @@ -248,7 +248,7 @@ async def test_start_download_existing_download(self) -> None: """ Test if torrents can be added when there is a pre-existing download. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, checkpoint_disabled=True, config=self.create_mock_download_config()) self.manager.downloads[download.tdef.infohash] = download @@ -395,7 +395,7 @@ async def test_readd_download_safe_seeding(self) -> None: """ config = self.create_mock_download_config() config.set_safe_seeding(True) - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.manager, checkpoint_disabled=True, config=config) download.futures["save_resume_data"] = succeed(True) download_state = DownloadState(download, Mock(state=4, paused=False, error=None), None) @@ -419,7 +419,7 @@ def test_get_downloads_by_name(self) -> None: """ Test if downloads can be retrieved by name. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.manager, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) self.manager.downloads = {b"\x01" * 20: download} @@ -485,8 +485,8 @@ def test_update_trackers(self) -> None: """ Test if trackers can be updated for an existing download. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.manager.downloads[download.tdef.infohash] = download self.manager.update_trackers(download.tdef.infohash, [b"127.0.0.1/test-announce1"]) @@ -498,8 +498,8 @@ def test_update_trackers_list(self) -> None: """ Test if multiple trackers are correctly added as an announce list instead of a the singular announce. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.manager.downloads[download.tdef.infohash] = download self.manager.update_trackers(download.tdef.infohash, [f"127.0.0.1/test-announce{i}".encode() for i in range(2)]) @@ -512,8 +512,8 @@ def test_update_trackers_list_append(self) -> None: """ Test if trackers can be updated in sequence. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, checkpoint_disabled=True, - config=self.create_mock_download_config()) + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.manager, + checkpoint_disabled=True, config=self.create_mock_download_config()) self.manager.downloads[download.tdef.infohash] = download self.manager.update_trackers(download.tdef.infohash, [b"127.0.0.1/test-announce0"]) diff --git a/src/tribler/test_unit/core/libtorrent/download_manager/test_download_state.py b/src/tribler/test_unit/core/libtorrent/download_manager/test_download_state.py index 1a8acd0307..41eb7da2a5 100644 --- a/src/tribler/test_unit/core/libtorrent/download_manager/test_download_state.py +++ b/src/tribler/test_unit/core/libtorrent/download_manager/test_download_state.py @@ -11,6 +11,7 @@ from tribler.core.libtorrent.download_manager.download_state import DOWNLOAD, UPLOAD, DownloadState, DownloadStatus from tribler.core.libtorrent.torrentdef import TorrentDef, TorrentDefNoMetainfo from tribler.test_unit.core.libtorrent.mocks import TORRENT_WITH_DIRS_CONTENT +from tribler.test_unit.mocks import MockTriblerConfigManager class TestDownloadState(TestBase): @@ -21,12 +22,13 @@ class TestDownloadState(TestBase): base_peer_info = {"client": "unknown", "pid": Mock(to_bytes=Mock(return_value=b"\x01")), "ip": ("127.0.0.1", 42), "flags":0, "local_connection": 1, "remote_interested": 0, "remote_choked": 0, "upload_only": 1, "upload_queue_length": 1, "used_send_buffer": 1, "interesting": 1, "choked": 0, "seed": 1} + dlmngr = Mock(config=MockTriblerConfigManager()) def test_initialize(self) -> None: """ Test if DownloadState gets properly initialized from a download without a status. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download_state = DownloadState(download, None, None) @@ -47,7 +49,7 @@ def test_initialize_with_status(self) -> None: """ Test if DownloadState gets properly initialized from a download with a status. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download_state = DownloadState(download, libtorrent.torrent_status(), None) @@ -66,7 +68,7 @@ def test_initialize_with_mocked_status(self) -> None: """ Test if DownloadState gets properly initialized from a download with a mocked status. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.config.set_selected_files(["test"]) download_state = DownloadState(download, Mock(num_pieces=6, pieces=[1, 1, 1, 0, 0, 0], progress=0.75, @@ -126,7 +128,7 @@ def test_get_files_completion(self) -> None: Each file is 6 bytes, so a file progress of 3 bytes is 0.5 completion. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True), file_progress=Mock(return_value=[3] * 6)) download_state = DownloadState(download, Mock(), None) @@ -140,7 +142,7 @@ def test_get_files_completion_no_progress(self) -> None: """ Testing if file progress is not given if no file progress is available. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True), file_progress=Mock(return_value=[])) download_state = DownloadState(download, Mock(), None) @@ -151,7 +153,7 @@ def test_get_files_completion_zero_length_file(self) -> None: """ Testing if file progress is 100% for a file of 0 bytes. """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) for file_spec in download.tdef.metainfo[b"info"][b"files"]: file_spec[b"length"] = 0 @@ -165,7 +167,7 @@ def test_get_availability_incomplete(self) -> None: """ Testing if the right availability of a file is returned if another peer has no pieces. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True), file_progress=Mock(return_value=[]), get_peer_info=Mock(return_value=[Mock(**TestDownloadState.base_peer_info, @@ -178,7 +180,7 @@ def test_get_availability_complete(self) -> None: """ Testing if the right availability of a file is returned if another peer has all pieces. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True), file_progress=Mock(return_value=[]), get_peer_info=Mock(return_value=[Mock(**TestDownloadState.base_peer_info, @@ -191,7 +193,7 @@ def test_get_availability_mixed(self) -> None: """ Testing if the right availability of a file is returned if one peer is complete and the other is not. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True), file_progress=Mock(return_value=[]), get_peer_info=Mock(return_value=[Mock(**TestDownloadState.base_peer_info, @@ -208,7 +210,7 @@ def test_get_files_completion_semivalid_handle(self) -> None: This case mirrors https://github.com/Tribler/tribler/issues/6454 """ - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True), file_progress=Mock(side_effect=RuntimeError("invalid torrent handle used"))) diff --git a/src/tribler/test_unit/core/libtorrent/download_manager/test_stream.py b/src/tribler/test_unit/core/libtorrent/download_manager/test_stream.py index 7da8ce2949..eaf323adcd 100644 --- a/src/tribler/test_unit/core/libtorrent/download_manager/test_stream.py +++ b/src/tribler/test_unit/core/libtorrent/download_manager/test_stream.py @@ -13,6 +13,7 @@ from tribler.core.libtorrent.download_manager.stream import NoAvailableStreamError, Stream, StreamReader from tribler.core.libtorrent.torrentdef import TorrentDef from tribler.test_unit.core.libtorrent.mocks import TORRENT_WITH_DIRS_CONTENT +from tribler.test_unit.mocks import MockTriblerConfigManager class MockStreamReader(StreamReader): @@ -138,6 +139,8 @@ class TestStream(TestBase): Tests for the Stream class. """ + dlmngr = Mock(config=MockTriblerConfigManager()) + def create_mock_download(self, piece_size: int | None = None, pieces: list[bool] | None = None) -> Download: """ Create a mocked DownloadConfig. @@ -148,7 +151,7 @@ def create_mock_download(self, piece_size: int | None = None, pieces: list[bool] conf.validate(Validator()) config = DownloadConfig(conf) config.set_dest_dir(Path("")) - download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None, config, + download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), self.dlmngr, config, checkpoint_disabled=True) download.handle = Mock(is_valid=Mock(return_value=True), file_priorities=Mock(return_value=[0] * 6), torrent_file=Mock(return_value=download.tdef.torrent_info)) diff --git a/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py b/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py index 6c052c8b26..c226a64857 100644 --- a/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py +++ b/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py @@ -87,7 +87,7 @@ def create_mock_download(self) -> Download: conf.validate(Validator()) config = DownloadConfig(conf) config.set_dest_dir(Path("")) - return Download(TorrentDefNoMetainfo(b"\x01" * 20, b"test"), None, config, hidden=False, + return Download(TorrentDefNoMetainfo(b"\x01" * 20, b"test"), self.download_manager, config, hidden=False, checkpoint_disabled=True) async def test_get_downloads_unloaded(self) -> None: @@ -129,7 +129,7 @@ async def test_get_downloads_hidden_download(self) -> None: """ Test if an empty list is returned if there are only hidden downloads. """ - self.set_loaded_downloads([Download(TorrentDefNoMetainfo(b"\x01" * 20, b"test"), None, Mock(), + self.set_loaded_downloads([Download(TorrentDefNoMetainfo(b"\x01" * 20, b"test"), self.download_manager, Mock(), hidden=True, checkpoint_disabled=True)]) request = MockRequest("/api/downloads", query={}) diff --git a/src/tribler/test_unit/core/libtorrent/test_torrents.py b/src/tribler/test_unit/core/libtorrent/test_torrents.py index a2b12e661a..8b548b6188 100644 --- a/src/tribler/test_unit/core/libtorrent/test_torrents.py +++ b/src/tribler/test_unit/core/libtorrent/test_torrents.py @@ -16,6 +16,7 @@ get_info_from_handle, require_handle, ) +from tribler.test_unit.mocks import MockTriblerConfigManager class TestTorrents(TestBase): @@ -23,11 +24,13 @@ class TestTorrents(TestBase): Tests for the torrent-related functionality. """ + dlmngr = Mock(config=MockTriblerConfigManager()) + def test_check_handle_default_missing_handle(self) -> None: """ Test if the default value is returned for missing handles. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) self.assertEqual("default", (check_handle("default")(Download.get_def)(download))) @@ -36,7 +39,7 @@ def test_check_handle_default_invalid_handle(self) -> None: """ Test if the default value is returned for invalid handles. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=False)) @@ -46,7 +49,7 @@ def test_check_handle_default_valid_handle(self) -> None: """ Test if the given method is called for valid handles. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -56,7 +59,7 @@ async def test_require_handle_invalid_handle(self) -> None: """ Test if None is returned for invalid handles. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=False)) @@ -68,7 +71,7 @@ async def test_require_handle_valid_handle(self) -> None: """ Test if the result of the given method is given for valid handles. """ - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -86,7 +89,7 @@ def callback(_: Download) -> None: """ raise RuntimeError - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True)) @@ -105,7 +108,7 @@ def callback(_: Download) -> None: """ raise ValueError - download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True, + download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), self.dlmngr, checkpoint_disabled=True, config=DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))) download.handle = Mock(is_valid=Mock(return_value=True)) diff --git a/src/tribler/tribler_config.py b/src/tribler/tribler_config.py index 56ffe9173e..5619785e0c 100644 --- a/src/tribler/tribler_config.py +++ b/src/tribler/tribler_config.py @@ -103,6 +103,7 @@ class LibtorrentConfig(TypedDict): announce_to_all_tiers: bool announce_to_all_trackers: bool max_concurrent_http_announces: int + check_after_complete: bool download_defaults: DownloadDefaultsConfig @@ -223,6 +224,7 @@ class TriblerConfig(TypedDict): announce_to_all_tiers=False, announce_to_all_trackers=False, max_concurrent_http_announces=50, + check_after_complete=False, download_defaults=DownloadDefaultsConfig( anonymity_enabled=True, number_hops=1, diff --git a/src/tribler/ui/public/locales/en_US.json b/src/tribler/ui/public/locales/en_US.json index 7e844c63d3..d6c68d528c 100644 --- a/src/tribler/ui/public/locales/en_US.json +++ b/src/tribler/ui/public/locales/en_US.json @@ -26,8 +26,10 @@ "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)", "Save": "Save", "Tags": "Tags", "ProxySettings": "Torrent proxy settings", @@ -183,6 +185,7 @@ "ToastErrorTrackerCheck": "Failed to check tracker!", "MoveAfterCompletion": "Move after completion", "MoveAfterCompletionInfo": "Once completed, files will move to", + "CheckAfterCompletion": "Check torrent after completion", "Create": "Create", "Select": "Select", "PleaseSelectDirectory": "Please select a directory", diff --git a/src/tribler/ui/public/locales/es_ES.json b/src/tribler/ui/public/locales/es_ES.json index e0a8e73d88..9ae3a7bbb4 100644 --- a/src/tribler/ui/public/locales/es_ES.json +++ b/src/tribler/ui/public/locales/es_ES.json @@ -26,8 +26,10 @@ "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)", "Save": "Guardar", "Tags": "Etiquetas", "ProxySettings": "Configuración del proxy torrent", @@ -183,6 +185,7 @@ "ToastErrorTrackerCheck": "¡No se pudo verificar el rastreador!", "MoveAfterCompletion": "Muévete después de completarlo", "MoveAfterCompletionInfo": "Una vez completado, los archivos se moverán a", + "CheckAfterCompletion": "Verifique el torrent después de la finalización", "Create": "Crear", "Select": "Seleccionar", "PleaseSelectDirectory": "Por favor seleccione un directorio", diff --git a/src/tribler/ui/public/locales/ko_KR.json b/src/tribler/ui/public/locales/ko_KR.json index 7ae7e13d0b..92f8f809d9 100644 --- a/src/tribler/ui/public/locales/ko_KR.json +++ b/src/tribler/ui/public/locales/ko_KR.json @@ -26,8 +26,10 @@ "AlwaysAsk": "항상 내려받기 설정 확인", "DownloadAnon": "프록시를 사용하여 익명으로 내려받기", "SeedAnon": "프록시를 사용하여 암호화된 익명 시딩", + "StopAfterMetadata": "메타 데이터를받은 후 다운로드 중지", "TorrentWatchFolder": "토렌트 폴더 보기", "WatchFolder": "폴더 보기", + "EnableWatchFolder": "감시 폴더 활성화(다시 시작해야 함)", "Save": "저장", "Tags": "태그", "ProxySettings": "토렌트 프록시 설정", @@ -180,6 +182,7 @@ "ToastErrorTrackerCheck": "트래커 확인에 실패했습니다!", "MoveAfterCompletion": "완료 후 이동", "MoveAfterCompletionInfo": "완료되면 파일이 이동됩니다.", + "CheckAfterCompletion": "완료 후 급류를 확인하십시오", "Create": "만들다", "Select": "선택하다", "PleaseSelectDirectory": "디렉토리를 선택해주세요", diff --git a/src/tribler/ui/public/locales/pt_BR.json b/src/tribler/ui/public/locales/pt_BR.json index 40ce97126b..22f9963771 100644 --- a/src/tribler/ui/public/locales/pt_BR.json +++ b/src/tribler/ui/public/locales/pt_BR.json @@ -26,8 +26,10 @@ "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)", "Save": "Salvar", "ProxySettings": "Configurações de proxy torrent", "P2PSettings": "Configurações ponto a ponto", @@ -177,6 +179,7 @@ "ToastErrorTrackerCheck": "Falha ao verificar o rastreador!", "MoveAfterCompletion": "Mover após a conclusão", "MoveAfterCompletionInfo": "Uma vez concluído, os arquivos serão movidos para", + "CheckAfterCompletion": "Verifique a torrent após a conclusão", "Create": "Criar", "Select": "Selecione", "PleaseSelectDirectory": "Selecione um diretório", diff --git a/src/tribler/ui/public/locales/ru_RU.json b/src/tribler/ui/public/locales/ru_RU.json index 0fdfa5f98c..8165b6c315 100644 --- a/src/tribler/ui/public/locales/ru_RU.json +++ b/src/tribler/ui/public/locales/ru_RU.json @@ -26,8 +26,10 @@ "AlwaysAsk": "Всегда спрашивать настройки закачки", "DownloadAnon": "Загружать торренты анонимно (через других участников)", "SeedAnon": "Раздавать торренты анонимно (через других участников)", + "StopAfterMetadata": "Остановите загрузку после получения метаданных", "TorrentWatchFolder": "Папка автоскачивания:", "WatchFolder": "Автоскачивание торрентов из папки", + "EnableWatchFolder": "Включить папку просмотра (требуется перезагрузка)", "HideTags": "Скрыть тэги контента", "Save": "Сохранить", "Tags": "Тэги", @@ -184,6 +186,7 @@ "ToastErrorTrackerCheck": "Не удалось проверить трекер!", "MoveAfterCompletion": "Переезд после завершения", "MoveAfterCompletionInfo": "После завершения файлы будут перемещены в", + "CheckAfterCompletion": "Проверьте торрент после завершения", "Create": "Создавать", "Select": "Выбирать", "PleaseSelectDirectory": "Пожалуйста, выберите каталог", diff --git a/src/tribler/ui/public/locales/zh_CN.json b/src/tribler/ui/public/locales/zh_CN.json index 6f98c78cc9..4b1adbb92f 100644 --- a/src/tribler/ui/public/locales/zh_CN.json +++ b/src/tribler/ui/public/locales/zh_CN.json @@ -26,8 +26,10 @@ "AlwaysAsk": "总是询问下载设置", "DownloadAnon": "使用代理匿名下载", "SeedAnon": "使用代理加密地匿名做种", + "StopAfterMetadata": "收到元数据后停止下载", "TorrentWatchFolder": "种子监视文件夹", "WatchFolder": "监视文件夹", + "EnableWatchFolder": "启用监视文件夹(需要重新启动)", "Save": "保存", "ProxySettings": "种子代理设置", "P2PSettings": "点对点设置", @@ -183,6 +185,7 @@ "ToastErrorTrackerCheck": "检查追踪器失败!", "MoveAfterCompletion": "完成后搬移", "MoveAfterCompletionInfo": "完成后,文件将移至", + "CheckAfterCompletion": "完成后检查洪流", "Create": "创造", "Select": "选择", "PleaseSelectDirectory": "请选择一个目录", diff --git a/src/tribler/ui/src/dialogs/SaveAs.tsx b/src/tribler/ui/src/dialogs/SaveAs.tsx index 774b27c090..0ecf3dc55b 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 && (
diff --git a/src/tribler/ui/src/models/downloadconfig.model.tsx b/src/tribler/ui/src/models/downloadconfig.model.tsx index b608a7f752..13fa07b3bb 100644 --- a/src/tribler/ui/src/models/downloadconfig.model.tsx +++ b/src/tribler/ui/src/models/downloadconfig.model.tsx @@ -6,5 +6,6 @@ export interface DownloadConfig { completed_dir?: string, anon_hops?: number, selected_files?: number[], - safe_seeding?: boolean + safe_seeding?: boolean, + only_metadata?: boolean } diff --git a/src/tribler/ui/src/models/settings.model.tsx b/src/tribler/ui/src/models/settings.model.tsx index 4b46e01115..c93e30b152 100644 --- a/src/tribler/ui/src/models/settings.model.tsx +++ b/src/tribler/ui/src/models/settings.model.tsx @@ -67,6 +67,7 @@ export interface Settings { announce_to_all_tiers: boolean; announce_to_all_trackers: boolean; max_concurrent_http_announces: number; + check_after_complete: boolean; download_defaults: { anonymity_enabled: boolean; number_hops: number; diff --git a/src/tribler/ui/src/pages/Settings/General.tsx b/src/tribler/ui/src/pages/Settings/General.tsx index 78fe733bda..b24b8adbd7 100644 --- a/src/tribler/ui/src/pages/Settings/General.tsx +++ b/src/tribler/ui/src/pages/Settings/General.tsx @@ -140,6 +140,29 @@ export default function General() { />
+
+ { + if (settings) { + setSettings({ + ...settings, + libtorrent: { + ...settings.libtorrent, + check_after_complete: !!value + } + }); + } + }} + id="check_after_complete" /> + +
+