Files
Mediatracker/generate-compose.py
snoopy 6f551ba439 Initial release — MediaTracker v1.0
Dockerized media library scanner for NAS drives.
Identifies movies and series from filenames, fetches posters
via the public IMDB suggestion API (no key required), and
exposes a dark-themed web UI with multilingual search support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:40:44 +00:00

109 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""
generate-compose.py
Reads .env and generates docker-compose.override.yml with NAS volumes.
No external dependencies required.
"""
import os
import sys
import re
from pathlib import Path
ENV_FILE = Path(".env")
OUTPUT_FILE = Path("docker-compose.override.yml")
OVERRIDE_HEADER = """\
# Auto-generated by generate-compose.py — do not edit manually.
# Re-run the script after changing NAS_* entries in .env.
services:
backend:
volumes:
"""
def load_env(path: Path) -> dict:
env = {}
if not path.exists():
print(f"[ERROR] {path} not found. Copy .env.example to .env first.")
sys.exit(1)
with path.open(encoding="utf-8") as fh:
for line in fh:
line = line.strip()
if not line or line.startswith("#"):
continue
if "=" not in line:
continue
key, _, value = line.partition("=")
key = key.strip()
# Strip inline comments
value = value.split("#")[0].strip()
env[key] = value
return env
def parse_nas_entries(env: dict) -> list[tuple[str, str, str]]:
"""Return list of (key, name, host_path) sorted by key."""
nas_pattern = re.compile(r"^NAS_(\d+)$")
entries = []
for key, value in env.items():
match = nas_pattern.match(key)
if not match:
continue
if "|" not in value:
print(f"[WARN] {key}={value!r} — expected format 'Name|/host/path', skipping.")
continue
name, _, host_path = value.partition("|")
entries.append((key, name.strip(), host_path.strip()))
entries.sort(key=lambda t: int(t[0].split("_")[1]))
return entries
def validate_paths(entries: list[tuple[str, str, str]]) -> None:
for key, name, host_path in entries:
if not Path(host_path).exists():
print(f"[WARN] {key} — host path does not exist: {host_path!r}")
else:
print(f"[OK] {key}{name!r}{host_path}")
def generate_override(entries: list[tuple[str, str, str]]) -> str:
lines = [OVERRIDE_HEADER]
for idx, (key, name, host_path) in enumerate(entries, start=1):
container_path = f"/nas/nas{idx}"
lines.append(f" - {host_path}:{container_path}:ro # {name}")
# Pass NAS_X env vars into the container so config.py can read the names
lines.append(" environment:")
for idx, (key, name, host_path) in enumerate(entries, start=1):
lines.append(f" - {key}={name}|/nas/nas{idx}")
lines.append("")
return "\n".join(lines)
def main() -> None:
print("=" * 55)
print(" MediaTracker — generate-compose.py")
print("=" * 55)
env = load_env(ENV_FILE)
entries = parse_nas_entries(env)
if not entries:
print("[ERROR] No NAS_* entries found in .env. Add at least one NAS.")
sys.exit(1)
print(f"\nFound {len(entries)} NAS source(s):\n")
validate_paths(entries)
content = generate_override(entries)
OUTPUT_FILE.write_text(content, encoding="utf-8")
print(f"\n[DONE] {OUTPUT_FILE} generated with {len(entries)} volume(s).")
print("\nNext step:")
print(" docker compose -f docker-compose.yml -f docker-compose.override.yml up -d --build\n")
if __name__ == "__main__":
main()