Coverage for seedboxsync/core/sync/services/blackhole.py: 89%
56 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-26 17:46 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-26 17:46 +0000
1#
2# Copyright (C) 2015-2026 Guillaume Kulakowski <guillaume@kulakowski.fr>
3#
4# For the full copyright and license information, please view the LICENSE
5# file that was distributed with this source code.
6#
7"""SeedboxSync sync service for blackhole."""
9from os import fspath
10from pathlib import Path
11from paramiko import SSHException
12from seedboxsync.core import current_app as app, utils
13from seedboxsync.core.dao import Torrent
14from seedboxsync.core.taskmanager import track_taskstatus
16LOCK_NAME = "sync-blackhole"
17PRIORITY = 10
20@track_taskstatus(LOCK_NAME)
21def blackhole(dry_run: bool, ping: bool) -> None:
22 """
23 Perform the blackhole synchronization.
25 Uploads torrent files from the local watch folder to the seedbox.
26 Optional dry-run, file permissions, database persistence, and error handling.
28 Args:
29 dry_run (bool): Whether to perform a dry run.
30 ping (bool): Whether to ping a service during execution.
31 """
32 if not app.seedboxsync_config.get("sync_blackhole_enabled"):
33 app.logger.info("Blackhole synchronization task is disabled")
34 return
36 app.logger.debug(f'sync blackhole dry-run: "{dry_run}"')
37 app.logger.debug(f'sync blackhole ping: "{ping}"')
39 # Call ping.start() if enabled
40 if ping:
41 app.ping.start("sync_blackhole")
43 # Gather all torrent files
44 local_watch_path = app.seedboxsync_config.get("local_watch_path", "")
45 app.logger.debug(f'Scanning for torrent files in "{local_watch_path}"')
46 torrents = list(Path(local_watch_path).expanduser().resolve().glob("*.torrent"))
48 if len(torrents) == 0:
49 app.logger.info('No torrent files found in "{}"'.format(app.seedboxsync_config.get("local_watch_path")))
50 # Call ping.success() if enabled
51 if ping:
52 app.ping.success("sync_blackhole")
53 return
55 for torrent_file in torrents:
56 torrent_name = torrent_file.name
58 # Dry-run mode
59 if dry_run:
60 app.logger.info(f'Dry-run: not uploading torrent "{torrent_name}"')
61 continue
63 tmp_path = app.seedboxsync_config.get("seedbox_tmp_path", "")
64 watch_path = app.seedboxsync_config.get("seedbox_watch_path", "")
66 app.logger.info(f'Upload torrent: "{torrent_name}"')
67 app.logger.debug(f'Upload "{torrent_file}" to "{tmp_path}"')
69 try:
70 app.sync.chdir(None) # type: ignore[arg-type]
71 app.sync.put(torrent_file, Path(tmp_path) / torrent_name)
73 # Apply chmod if configured
74 chmod = app.seedboxsync_config.get("seedbox_chmod", False)
75 if isinstance(chmod, str):
76 app.logger.debug(f"Change permissions to {chmod}")
77 app.sync.chmod(Path(tmp_path) / torrent_name, int(chmod, 8))
79 # Move file from tmp to watch directory
80 app.logger.debug(f'Move from "{tmp_path}" to "{watch_path}"')
81 app.sync.rename(
82 Path(tmp_path) / torrent_name,
83 Path(watch_path) / torrent_name,
84 )
86 # Store torrent info in database
87 torrent_info = utils.get_torrent_infos(torrent_file)
88 torrent = Torrent.create(name=torrent_name)
89 if torrent_info is not None and isinstance(torrent_info, dict):
90 torrent.announce = torrent_info.get("announce")
91 torrent.save()
93 # Remove local torrent file
94 app.logger.debug(f'Remove local torrent "{torrent_file}"')
95 Path(torrent_file).unlink()
96 else:
97 app.logger.warning(f'Rename local "{torrent_file}" to .torrent.fail')
98 Path(torrent_file).rename(fspath(torrent_file) + ".fail")
99 except SSHException as exc:
100 app.logger.warning(f"SSH client exception > {exc!s}")
102 # Call ping.success() if enabled
103 if ping:
104 app.ping.success("sync_blackhole")