-
Notifications
You must be signed in to change notification settings - Fork 451
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
101 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 59 additions & 46 deletions
105
src/tribler/core/components/watch_folder/watch_folder.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,86 +1,99 @@ | ||
import asyncio | ||
import logging | ||
import os | ||
from pathlib import Path | ||
|
||
from ipv8.taskmanager import TaskManager | ||
|
||
from tribler.core import notifications | ||
from tribler.core.components.libtorrent.download_manager.download_config import DownloadConfig | ||
from tribler.core.components.libtorrent.download_manager.download_manager import DownloadManager | ||
from tribler.core.components.libtorrent.torrentdef import TorrentDef | ||
from tribler.core.components.reporter.exception_handler import NoCrashException | ||
from tribler.core.components.watch_folder.settings import WatchFolderSettings | ||
from tribler.core.utilities import path_util | ||
from tribler.core.utilities.async_group import AsyncGroup | ||
from tribler.core.utilities.notifier import Notifier | ||
from tribler.core.utilities.path_util import Path | ||
|
||
WATCH_FOLDER_CHECK_INTERVAL = 10 | ||
|
||
|
||
class WatchFolder(TaskManager): | ||
class WatchFolder: | ||
def __init__(self, state_dir: Path, settings: WatchFolderSettings, download_manager: DownloadManager, | ||
notifier: Notifier): | ||
super().__init__() | ||
self.state_dir = state_dir | ||
self.settings = settings | ||
self.download_manager = download_manager | ||
self.notifier = notifier | ||
|
||
self.group = AsyncGroup() | ||
self._logger = logging.getLogger(self.__class__.__name__) | ||
self._logger.info(f'Initialised with {settings}') | ||
|
||
def start(self): | ||
self.register_task("check watch folder", self.check_watch_folder, interval=WATCH_FOLDER_CHECK_INTERVAL) | ||
self.group.add(self.run()) | ||
|
||
async def stop(self): | ||
await self.shutdown_task_manager() | ||
await self.group.cancel() | ||
|
||
def cleanup_torrent_file(self, root, name): | ||
fullpath = root / name | ||
if not fullpath.exists(): | ||
self._logger.warning("File with path %s does not exist (anymore)", root / name) | ||
return | ||
path = Path(str(fullpath) + ".corrupt") | ||
try: | ||
path.unlink(missing_ok=True) | ||
fullpath.rename(path) | ||
except (PermissionError, FileExistsError) as e: | ||
self._logger.warning(f'Cant rename the file to {path}. Exception: {e}') | ||
async def run(self): | ||
while True: | ||
await asyncio.sleep(WATCH_FOLDER_CHECK_INTERVAL) | ||
self.group.add(self.check_watch_folder_handle_exceptions()) | ||
|
||
self._logger.warning("Watch folder - corrupt torrent file %s", name) | ||
self.notifier[notifications.watch_folder_corrupt_file](name) | ||
async def check_watch_folder_handle_exceptions(self): | ||
try: | ||
self.check_watch_folder() | ||
except Exception as e: | ||
self._logger.exception(f'Failed download attempt: {e}') | ||
raise NoCrashException from e | ||
|
||
def check_watch_folder(self): | ||
self._logger.debug('Checking watch folder...') | ||
|
||
if not self.settings.enabled or not self.state_dir: | ||
self._logger.debug(f'Cancelled. Enabled: {self.settings.enabled}. State dir: {self.state_dir}.') | ||
return | ||
|
||
directory = self.settings.get_path_as_absolute('directory', self.state_dir) | ||
self._logger.debug(f'Watch dir: {directory}') | ||
if not directory.is_dir(): | ||
self._logger.debug(f'Cancelled. Is not directory: {directory}.') | ||
return | ||
|
||
# Make sure that we pass a str to os.walk | ||
watch_dir = str(directory) | ||
self._logger.debug(f'Watch dir: {watch_dir}') | ||
|
||
for root, _, files in os.walk(watch_dir): | ||
root = path_util.Path(root) | ||
for root, _, files in os.walk(str(directory)): | ||
for name in files: | ||
if not name.endswith(".torrent"): | ||
continue | ||
|
||
try: | ||
tdef = TorrentDef.load(root / name) | ||
if not tdef.get_metainfo(): | ||
self.cleanup_torrent_file(root, name) | ||
continue | ||
except: # torrent appears to be corrupt | ||
self.cleanup_torrent_file(root, name) | ||
continue | ||
|
||
infohash = tdef.get_infohash() | ||
|
||
if not self.download_manager.download_exists(infohash): | ||
self._logger.info("Starting download from torrent file %s", name) | ||
self.download_manager.start_download(torrent_file=root / name) | ||
path = Path(root) / name | ||
self.process_torrent_file(path) | ||
|
||
self._logger.debug('Checking watch folder completed.') | ||
|
||
def process_torrent_file(self, path: Path): | ||
if not path.name.endswith(".torrent"): | ||
return | ||
|
||
self._logger.info(f'Torrent file found: {path}') | ||
exception = None | ||
try: | ||
self.start_download(path) | ||
except Exception as e: # pylint: disable=broad-except | ||
self._logger.error(f'{e.__class__.__name__}: {e}') | ||
exception = e | ||
|
||
if exception: | ||
self._logger.info(f'Corrupted: {path}') | ||
try: | ||
path.replace(f'{path}.corrupt') | ||
except OSError as e: | ||
self._logger.warning(f'{e.__class__.__name__}: {e}') | ||
|
||
def start_download(self, path: Path): | ||
tdef = TorrentDef.load(path) | ||
if not tdef.get_metainfo(): | ||
self._logger.warning(f'Missed metainfo: {path}') | ||
return | ||
|
||
infohash = tdef.get_infohash() | ||
|
||
if not self.download_manager.download_exists(infohash): | ||
self._logger.info("Starting download from torrent file %s", path.name) | ||
|
||
download_config = DownloadConfig.from_defaults(self.download_manager.download_defaults, | ||
state_dir=self.state_dir) | ||
|
||
self.download_manager.start_download(torrent_file=path, config=download_config) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters