diff --git a/journeyfm/config_store.py b/journeyfm/config_store.py index f0c42a3..fd0d790 100644 --- a/journeyfm/config_store.py +++ b/journeyfm/config_store.py @@ -23,6 +23,7 @@ DEFAULT_CONFIG = { NON_SECRET_KEYS = { "SERVER_IP", "PLAYLIST_NAME", + "PLAYLIST_NAMES", "AUTO_UPDATE", "UPDATE_INTERVAL", "UPDATE_UNIT", diff --git a/journeyfm/update_service.py b/journeyfm/update_service.py index a84864c..b1f4561 100644 --- a/journeyfm/update_service.py +++ b/journeyfm/update_service.py @@ -102,9 +102,17 @@ def run_update_job(config=None, dry_run=False, persist_history=True, write_buy_l token = config.get("PLEX_TOKEN", "").strip() server_ip = config.get("SERVER_IP", "").strip() - playlist_name = config.get("PLAYLIST_NAME", "Journey FM Recently Played").strip() selected_stations = config.get("SELECTED_STATIONS", ["journey_fm", "spirit_fm"]) + # Support PLAYLIST_NAMES (list) or fall back to single PLAYLIST_NAME + raw_names = config.get("PLAYLIST_NAMES") or config.get("PLAYLIST_NAME", "Journey FM Recently Played") + if isinstance(raw_names, list): + playlist_names = [n.strip() for n in raw_names if str(n).strip()] + else: + playlist_names = [n.strip() for n in str(raw_names).split(",") if n.strip()] + if not playlist_names: + playlist_names = ["Journey FM Recently Played"] + if not token or not server_ip: result["status"] = "error" result["error_message"] = "Missing configuration: set Plex token and server IP before running updates" @@ -117,13 +125,21 @@ def run_update_job(config=None, dry_run=False, persist_history=True, write_buy_l songs = scrape_result["songs"] result["station_breakdown"] = scrape_result["station_results"] result["scraped_count"] = len(songs) - # Keep scraped songs for history analytics (song play counts per station) result["scraped_songs"] = songs try: plex = connect_to_plex_server(token, server_ip) - playlist_result = create_or_update_playlist(plex, songs, playlist_name, dry_run=dry_run) - result.update(playlist_result) + # Sync every configured playlist; aggregate results + merged = {} + for playlist_name in playlist_names: + pr = create_or_update_playlist(plex, songs, playlist_name, dry_run=dry_run) + if not merged: + merged = pr + else: + merged["added_count"] = merged.get("added_count", 0) + pr.get("added_count", 0) + merged["added_songs"] = merged.get("added_songs", []) + pr.get("added_songs", []) + merged["duplicate_count"] = merged.get("duplicate_count", 0) + pr.get("duplicate_count", 0) + result.update(merged) result["missing_count"] = len(result.get("missing_songs", [])) result["skipped_count"] = len(result.get("skipped_songs", [])) if write_buy_list and not dry_run: diff --git a/journeyfm/web_service.py b/journeyfm/web_service.py index 170113c..684a173 100644 --- a/journeyfm/web_service.py +++ b/journeyfm/web_service.py @@ -186,21 +186,36 @@ def dedup_buy_list(buy_list_path=None): # ── Config ──────────────────────────────────────────────────── def get_web_config(): - config = load_runtime_config() - token = config.get("PLEX_TOKEN", "") - config["_has_token"] = bool(token) + from journeyfm.config_store import _read_config_file, DEFAULT_CONFIG, _normalize_selected_stations + # Read config.json directly so the form shows/saves the file values, + # not the env-var-merged runtime config (env vars still win at sync time). + file_cfg = _read_config_file() + config = dict(DEFAULT_CONFIG) + config.update({k: v for k, v in file_cfg.items() if k != "PLEX_TOKEN"}) + config["_has_token"] = bool(get_secret("PLEX_TOKEN")) config["PLEX_TOKEN"] = "" - stations = config.get("SELECTED_STATIONS", []) - if isinstance(stations, str): - stations = [s.strip() for s in stations.split(",") if s.strip()] - config["SELECTED_STATIONS"] = stations + config["SELECTED_STATIONS"] = _normalize_selected_stations(config.get("SELECTED_STATIONS", [])) + # Normalise playlist names to a list + raw = config.get("PLAYLIST_NAMES") or config.get("PLAYLIST_NAME", "") + if isinstance(raw, list): + playlists = [n.strip() for n in raw if str(n).strip()] + else: + playlists = [n.strip() for n in str(raw).split(",") if n.strip()] + config["PLAYLIST_NAMES"] = playlists return config def save_web_config(data): config = {} config["SERVER_IP"] = str(data.get("SERVER_IP", "")).strip() - config["PLAYLIST_NAME"] = str(data.get("PLAYLIST_NAME", "")).strip() + # Accept PLAYLIST_NAMES as list or comma string; store as comma string + raw = data.get("PLAYLIST_NAMES", data.get("PLAYLIST_NAME", "")) + if isinstance(raw, list): + playlists = [n.strip() for n in raw if str(n).strip()] + else: + playlists = [n.strip() for n in str(raw).split(",") if n.strip()] + config["PLAYLIST_NAMES"] = ",".join(playlists) + config["PLAYLIST_NAME"] = playlists[0] if playlists else "" stations = data.get("SELECTED_STATIONS", []) if isinstance(stations, str): stations = [s.strip() for s in stations.split(",") if s.strip()] @@ -218,11 +233,14 @@ def save_web_config(data): # ── Playlist ────────────────────────────────────────────────── -def get_playlist_tracks(): +def get_playlist_tracks(name=None): from journeyfm.plex_service import connect_to_plex_server config = load_runtime_config() plex = connect_to_plex_server(config.get("PLEX_TOKEN", ""), config.get("SERVER_IP", "")) - name = config.get("PLAYLIST_NAME", "") + if not name: + cfg = get_web_config() + names = cfg.get("PLAYLIST_NAMES") or [] + name = names[0] if names else config.get("PLAYLIST_NAME", "") playlist = plex.playlist(name) tracks = [] for item in playlist.items(): @@ -538,6 +556,7 @@ tr:last-child td{border-bottom:none}tr:hover td{background:var(--sf2)}