#!/usr/bin/env python3 """Share-list search/publish helpers for the musician service. Paths are environment-overridable and the share database / directory are accessed lazily, so importing this module has no side effects (the previous version ran ``SHARE_DIR.mkdir()`` and read the JSON DB at import time, which crashed on any host without the Pi's ``/var/www`` / ``/var/log`` layout — and made the service untestable). """ import json import os import uuid from pathlib import Path # CONFIGURATION (env-overridable) JSON_DB = os.getenv("CONJURER_SHARE_DB", "/var/log/share_scan.json") SHARE_DIR = Path(os.getenv("CONJURER_SHARE_DIR", "/var/www/html/share")) BASE_URL = os.getenv("CONJURER_SHARE_BASE_URL", "https://czernobog.pl/share") _entries_cache = None def _ensure_share_dir(): SHARE_DIR.mkdir(parents=True, exist_ok=True) def load_db(): """Load share entries, returning [] when the DB is missing/corrupt.""" try: with open(JSON_DB) as handle: return json.load(handle).get("entries", []) except (FileNotFoundError, json.JSONDecodeError): return [] def _entries(): global _entries_cache if _entries_cache is None: _entries_cache = load_db() return _entries_cache def relevancy(path, keywords): score = 0 low = path.lower() for kw in keywords: if kw.lower() in low: score += low.count(kw.lower()) return score def find_matches(count, keywords): scored = [] for entry in _entries(): score = relevancy(entry["path"], keywords) if score > 0: scored.append((score, entry["path"])) scored.sort(reverse=True, key=lambda x: x[0]) result = [p for _, p in scored] return result[:count] def publish(paths): _ensure_share_dir() urls = [] for path in paths: token = uuid.uuid4().hex link = SHARE_DIR / token try: os.symlink(path, link) except FileExistsError: pass urls.append(f"{BASE_URL}/{token}") return urls