138 lines
3.9 KiB
Python
138 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class QBittorrentConfig:
|
|
host: str
|
|
port: int
|
|
username: str
|
|
password: str
|
|
use_https: bool
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class SchedulerConfig:
|
|
poll_seconds: int
|
|
safe_margin_gb: int
|
|
anchors_per_batch: int
|
|
filler_limit: int
|
|
cold_start_small_limit: int
|
|
stall_percent: float
|
|
stall_minutes: int
|
|
stall_resume_minutes: int
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class UploaderConfig:
|
|
remote: str
|
|
root_template: str
|
|
threads: int
|
|
rclone_path: str
|
|
rclone_config: Optional[Path]
|
|
transfers: int
|
|
checkers: int
|
|
bwlimit_up: Optional[str]
|
|
drive_chunk_size: Optional[str]
|
|
retries: int
|
|
low_level_retries: int
|
|
ionice_class: Optional[str]
|
|
ionice_level: Optional[str]
|
|
nice_level: Optional[str]
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class AppPaths:
|
|
download_dir: Path
|
|
database_path: Path
|
|
log_dir: Path
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class AppConfig:
|
|
qbittorrent: QBittorrentConfig
|
|
scheduler: SchedulerConfig
|
|
uploader: UploaderConfig
|
|
paths: AppPaths
|
|
|
|
|
|
def _env(key: str, default: Optional[str] = None) -> Optional[str]:
|
|
return os.environ.get(key, default)
|
|
|
|
|
|
def _env_int(key: str, default: int) -> int:
|
|
try:
|
|
return int(_env(key, str(default)))
|
|
except (TypeError, ValueError):
|
|
return default
|
|
|
|
|
|
def _env_float(key: str, default: float) -> float:
|
|
try:
|
|
return float(_env(key, str(default)))
|
|
except (TypeError, ValueError):
|
|
return default
|
|
|
|
|
|
def _env_path(key: str, default: Path) -> Path:
|
|
raw = _env(key)
|
|
return Path(raw).expanduser() if raw else default
|
|
|
|
|
|
def load_config() -> AppConfig:
|
|
state_dir = _env_path("QFLOW_STATE_DIR", Path("./state"))
|
|
log_dir = _env_path("QFLOW_LOG_DIR", state_dir / "logs")
|
|
db_path = _env_path("QFLOW_DB_PATH", state_dir / "qflow.db")
|
|
download_dir = _env_path("QFLOW_DOWNLOAD_DIR", Path("/downloads"))
|
|
|
|
qb = QBittorrentConfig(
|
|
host=_env("QFLOW_QBIT_HOST", "http://qbittorrent:8080"),
|
|
port=_env_int("QFLOW_QBIT_PORT", 8080),
|
|
username=_env("QFLOW_QBIT_USER", "admin"),
|
|
password=_env("QFLOW_QBIT_PASS", "adminadmin"),
|
|
use_https=_env("QFLOW_QBIT_HTTPS", "false").lower() == "true",
|
|
)
|
|
|
|
scheduler = SchedulerConfig(
|
|
poll_seconds=_env_int("QFLOW_SCHED_POLL", 15),
|
|
safe_margin_gb=_env_int("QFLOW_SAFE_MARGIN_GB", 20),
|
|
anchors_per_batch=_env_int("QFLOW_ANCHORS", 1),
|
|
filler_limit=_env_int("QFLOW_FILLERS", 4),
|
|
cold_start_small_limit=_env_int("QFLOW_COLD_SMALL", 3),
|
|
stall_percent=_env_float("QFLOW_STALL_PCT", 85.0),
|
|
stall_minutes=_env_int("QFLOW_STALL_MIN", 5),
|
|
stall_resume_minutes=_env_int("QFLOW_STALL_RESUME_MIN", 2),
|
|
)
|
|
|
|
uploader = UploaderConfig(
|
|
remote=_env("QFLOW_REMOTE", "gcrypt:"),
|
|
root_template=_env("QFLOW_REMOTE_TEMPLATE", "{year}/{month:02d}"),
|
|
threads=_env_int("QFLOW_UPLOAD_THREADS", 2),
|
|
rclone_path=_env("QFLOW_RCLONE_BIN", "rclone"),
|
|
rclone_config=_env_path("QFLOW_RCLONE_CONFIG", Path("/config/rclone/rclone.conf")),
|
|
transfers=_env_int("QFLOW_RCLONE_TRANSFERS", 8),
|
|
checkers=_env_int("QFLOW_RCLONE_CHECKERS", 16),
|
|
bwlimit_up=_env("QFLOW_RCLONE_BWLIMIT", None),
|
|
drive_chunk_size=_env("QFLOW_DRIVE_CHUNK", "128M"),
|
|
retries=_env_int("QFLOW_RCLONE_RETRIES", 3),
|
|
low_level_retries=_env_int("QFLOW_RCLONE_LL_RETRIES", 10),
|
|
ionice_class=_env("QFLOW_IONICE_CLASS", "2"),
|
|
ionice_level=_env("QFLOW_IONICE_LEVEL", "7"),
|
|
nice_level=_env("QFLOW_NICE_LEVEL", "10"),
|
|
)
|
|
|
|
return AppConfig(
|
|
qbittorrent=qb,
|
|
scheduler=scheduler,
|
|
uploader=uploader,
|
|
paths=AppPaths(
|
|
download_dir=download_dir,
|
|
database_path=db_path,
|
|
log_dir=log_dir,
|
|
),
|
|
)
|