Load remote playlists from Plex during sync
This commit is contained in:
@@ -3,6 +3,10 @@ from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Literal, Sequence
|
||||
|
||||
from app.utils.config import server_config
|
||||
from app.utils.logger import logger
|
||||
from app.utils.plex_client import plex_client
|
||||
|
||||
from merge3 import Merge3
|
||||
|
||||
|
||||
@@ -273,6 +277,48 @@ def _load_playlist_snapshots(playlist: str, folder: str) -> tuple[str, str, str,
|
||||
return base_text, remote_text, playlist_folder, remote_exists, base_exists
|
||||
|
||||
|
||||
def _fetch_remote_playlists() -> dict[str, str]:
|
||||
"""Retrieve remote playlists from Plex when connected.
|
||||
|
||||
Returns a mapping of playlist name to serialized playlist text. Failures to
|
||||
connect or fetch playlists are logged and result in an empty mapping to
|
||||
avoid blocking local testing.
|
||||
"""
|
||||
|
||||
server_config.load()
|
||||
if not server_config.url:
|
||||
return {}
|
||||
|
||||
try:
|
||||
plex_client.connect(
|
||||
token=server_config.token,
|
||||
scheme=server_config.scheme,
|
||||
url=server_config.url,
|
||||
port=server_config.port,
|
||||
)
|
||||
except Exception as exc: # pragma: no cover - network access
|
||||
logger.warning(f"Failed to connect to Plex for remote playlists: {exc}")
|
||||
return {}
|
||||
|
||||
playlists: dict[str, str] = {}
|
||||
try:
|
||||
for playlist in plex_client.server.playlists():
|
||||
paths: list[str] = []
|
||||
try:
|
||||
for track in playlist.items():
|
||||
locations = getattr(track, "locations", None) or []
|
||||
if locations:
|
||||
paths.append(locations[0])
|
||||
except Exception as exc: # pragma: no cover - plex runtime
|
||||
logger.warning(f"Failed to read playlist '{playlist.title}': {exc}")
|
||||
playlists[playlist.title] = save_paths(paths)
|
||||
except Exception as exc: # pragma: no cover - plex runtime
|
||||
logger.warning(f"Failed to enumerate remote playlists: {exc}")
|
||||
return {}
|
||||
|
||||
return playlists
|
||||
|
||||
|
||||
def _sync_single_playlist(
|
||||
playlist: str,
|
||||
mode: SyncMode,
|
||||
@@ -349,8 +395,11 @@ def sync_all_playlists(
|
||||
|
||||
_ensure_test_dir(test_folder)
|
||||
local_playlists = _load_local_playlists(local_dir)
|
||||
remote_playlists = _fetch_remote_playlists()
|
||||
playlist_names: set[str] = set(local_playlists.keys())
|
||||
|
||||
playlist_names.update(remote_playlists.keys())
|
||||
|
||||
for entry in os.scandir(test_folder):
|
||||
if entry.is_dir():
|
||||
playlist_names.add(entry.name)
|
||||
@@ -358,10 +407,17 @@ def sync_all_playlists(
|
||||
results: list[PlaylistSyncResult] = []
|
||||
|
||||
for playlist in sorted(playlist_names):
|
||||
base_text, remote_text, playlist_folder, remote_exists, _ = _load_playlist_snapshots(
|
||||
base_text, snapshot_remote_text, playlist_folder, remote_exists, _ = _load_playlist_snapshots(
|
||||
playlist, test_folder
|
||||
)
|
||||
local_text = local_playlists.get(playlist)
|
||||
|
||||
remote_text = remote_playlists.get(playlist)
|
||||
remote_present = False
|
||||
if remote_text:
|
||||
remote_present = True
|
||||
else:
|
||||
remote_text = snapshot_remote_text
|
||||
remote_present = bool(remote_text.strip()) or remote_exists
|
||||
|
||||
# Treat missing remote text as absent playlist.
|
||||
|
||||
Reference in New Issue
Block a user