mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-17 23:23:25 +02:00
161 lines
6.0 KiB
Python
161 lines
6.0 KiB
Python
import logging
|
|
from enum import Enum
|
|
|
|
from media_manager.config import AllEncompassingConfig
|
|
from media_manager.indexer.schemas import IndexerQueryResult
|
|
from media_manager.torrent.download_clients.abstractDownloadClient import (
|
|
AbstractDownloadClient,
|
|
)
|
|
from media_manager.torrent.download_clients.qbittorrent import QbittorrentDownloadClient
|
|
from media_manager.torrent.download_clients.transmission import (
|
|
TransmissionDownloadClient,
|
|
)
|
|
from media_manager.torrent.download_clients.sabnzbd import SabnzbdDownloadClient
|
|
from media_manager.torrent.schemas import Torrent, TorrentStatus
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class DownloadClientType(Enum):
|
|
"""Types of download clients supported"""
|
|
|
|
TORRENT = "torrent"
|
|
USENET = "usenet"
|
|
|
|
|
|
class DownloadManager:
|
|
"""
|
|
Manages download clients and routes downloads to the appropriate client
|
|
based on the content type (torrent vs usenet).
|
|
Only one torrent client and one usenet client are active at a time.
|
|
"""
|
|
|
|
def __init__(self):
|
|
self._torrent_client: AbstractDownloadClient | None = None
|
|
self._usenet_client: AbstractDownloadClient | None = None
|
|
self.config = AllEncompassingConfig().torrents
|
|
self._initialize_clients()
|
|
|
|
def _initialize_clients(self) -> None:
|
|
"""Initialize and register the default download clients"""
|
|
|
|
# Initialize torrent clients (prioritize qBittorrent, fallback to Transmission)
|
|
if self.config.qbittorrent.enabled:
|
|
try:
|
|
self._torrent_client = QbittorrentDownloadClient()
|
|
log.info(
|
|
"qBittorrent client initialized and set as active torrent client"
|
|
)
|
|
except Exception as e:
|
|
log.error(f"Failed to initialize qBittorrent client: {e}")
|
|
|
|
# If qBittorrent is not available or failed, try Transmission
|
|
if self._torrent_client is None and self.config.transmission.enabled:
|
|
try:
|
|
self._torrent_client = TransmissionDownloadClient()
|
|
log.info(
|
|
"Transmission client initialized and set as active torrent client"
|
|
)
|
|
except Exception as e:
|
|
log.error(f"Failed to initialize Transmission client: {e}")
|
|
|
|
# Initialize SABnzbd client for usenet
|
|
if self.config.sabnzbd.enabled:
|
|
try:
|
|
self._usenet_client = SabnzbdDownloadClient()
|
|
log.info("SABnzbd client initialized and set as active usenet client")
|
|
except Exception as e:
|
|
log.error(f"Failed to initialize SABnzbd client: {e}")
|
|
|
|
active_clients = []
|
|
if self._torrent_client:
|
|
active_clients.append(f"torrent ({self._torrent_client.name})")
|
|
if self._usenet_client:
|
|
active_clients.append(f"usenet ({self._usenet_client.name})")
|
|
|
|
log.info(
|
|
f"Download manager initialized with active download clients: {', '.join(active_clients) if active_clients else 'none'}"
|
|
)
|
|
|
|
def _get_appropriate_client(
|
|
self, indexer_result: IndexerQueryResult | Torrent
|
|
) -> AbstractDownloadClient:
|
|
"""
|
|
Select the appropriate download client based on the indexer result
|
|
|
|
:param indexer_result: The indexer query result to determine client type
|
|
:return: The appropriate download client
|
|
:raises RuntimeError: If no suitable client is available
|
|
"""
|
|
# Use the usenet flag from the indexer result to determine the client type
|
|
if indexer_result.usenet:
|
|
if not self._usenet_client:
|
|
raise RuntimeError("No usenet download client configured")
|
|
log.info(
|
|
f"Selected usenet client: {self._usenet_client.__class__.__name__}"
|
|
)
|
|
return self._usenet_client
|
|
else:
|
|
if not self._torrent_client:
|
|
raise RuntimeError("No torrent download client configured")
|
|
log.info(
|
|
f"Selected torrent client: {self._torrent_client.__class__.__name__}"
|
|
)
|
|
return self._torrent_client
|
|
|
|
def download(self, indexer_result: IndexerQueryResult) -> Torrent:
|
|
"""
|
|
Download content using the appropriate client
|
|
|
|
:param indexer_result: The indexer query result to download
|
|
:return: The torrent object representing the download
|
|
"""
|
|
log.info(f"Processing download request for: {indexer_result.title}")
|
|
|
|
client = self._get_appropriate_client(indexer_result)
|
|
return client.download_torrent(indexer_result)
|
|
|
|
def remove_torrent(self, torrent: Torrent, delete_data: bool = False) -> None:
|
|
"""
|
|
Remove a torrent using the appropriate client
|
|
|
|
:param torrent: The torrent to remove
|
|
:param delete_data: Whether to delete the downloaded data
|
|
"""
|
|
log.info(f"Removing torrent: {torrent.title}")
|
|
|
|
client = self._get_appropriate_client(torrent)
|
|
client.remove_torrent(torrent, delete_data)
|
|
|
|
def get_torrent_status(self, torrent: Torrent) -> TorrentStatus:
|
|
"""
|
|
Get the status of a torrent using the appropriate client
|
|
|
|
:param torrent: The torrent to get status for
|
|
:return: The current status of the torrent
|
|
"""
|
|
client = self._get_appropriate_client(torrent)
|
|
return client.get_torrent_status(torrent)
|
|
|
|
def pause_torrent(self, torrent: Torrent) -> None:
|
|
"""
|
|
Pause a torrent using the appropriate client
|
|
|
|
:param torrent: The torrent to pause
|
|
"""
|
|
log.info(f"Pausing torrent: {torrent.title}")
|
|
|
|
client = self._get_appropriate_client(torrent)
|
|
client.pause_torrent(torrent)
|
|
|
|
def resume_torrent(self, torrent: Torrent) -> None:
|
|
"""
|
|
Resume a torrent using the appropriate client
|
|
|
|
:param torrent: The torrent to resume
|
|
"""
|
|
log.info(f"Resuming torrent: {torrent.title}")
|
|
|
|
client = self._get_appropriate_client(torrent)
|
|
client.resume_torrent(torrent)
|