From 56e1061325a622239f1ebc2c7e9b32f7fbffe9d3 Mon Sep 17 00:00:00 2001 From: Johan Hjorth Date: Wed, 25 Jun 2025 15:03:26 +0200 Subject: [PATCH] New plex implementation --- create_monthly_playlist.py | 29 +++++++++++++++ discovery_sync.py | 1 + lastfm_helpers.py | 6 ++++ lidarr_helpers.py | 1 + musicbrainz_helpers.py | 17 +++++---- plex_helpers.py | 73 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 create_monthly_playlist.py create mode 100644 plex_helpers.py diff --git a/create_monthly_playlist.py b/create_monthly_playlist.py new file mode 100644 index 0000000..1fa2d0c --- /dev/null +++ b/create_monthly_playlist.py @@ -0,0 +1,29 @@ +#create_monthly_playlist.py +from plex_helpers import create_or_update_playlist +from musicbrainz_helpers import load_cache +import time + +def main(): + cache = load_cache() + added_artists = cache.get("added_artists", []) + added_tracks = cache.get("added_tracks", []) + + if not added_artists: + print("[PLEX] Ingen artist har lagts till ännu.") + return + + print(f"[PLEX] Skapar spellista för {len(added_artists)} artister...") + timestamp = time.strftime("%Y-%m") + playlist_name = f"DiscoveryLidarr {timestamp}" + + success, new_tracks = create_or_update_playlist( + playlist_name, added_artists, top_n=3, already_added=added_tracks + ) + + if success: + cache["added_tracks"] = list(set(added_tracks + new_tracks)) + print(f"[PLEX] 🎵 Spellistan '{playlist_name}' skapad med {len(new_tracks)} nya spår.") + from musicbrainz_helpers import save_cache + save_cache(cache) + else: + print(f"[PLEX] ❌ Spellistan '{playlist_name}' kunde inte skapas.") diff --git a/discovery_sync.py b/discovery_sync.py index 600aff5..f412357 100644 --- a/discovery_sync.py +++ b/discovery_sync.py @@ -1,3 +1,4 @@ +## discovery_sync.py from config import * from lastfm_helpers import lf_request, recent_artists from lidarr_helpers import lidarr_api_add_artist diff --git a/lastfm_helpers.py b/lastfm_helpers.py index e177ca5..0ad0bfb 100644 --- a/lastfm_helpers.py +++ b/lastfm_helpers.py @@ -45,3 +45,9 @@ def recent_artists(): page += 1 return [(n, m) for (n, m), c in counts.items() if c >= MIN_PLAYS] + +def get_top_tracks(artist_name, limit=3): + res = lf_request("artist.getTopTracks", artist=artist_name, limit=limit) + if not res: + return [] + return [t["name"] for t in res.get("toptracks", {}).get("track", [])] diff --git a/lidarr_helpers.py b/lidarr_helpers.py index 28c1036..93b347a 100644 --- a/lidarr_helpers.py +++ b/lidarr_helpers.py @@ -1,3 +1,4 @@ +#lidarr_helpers.py from config import ( LIDARR_URL, LIDARR_API_KEY, diff --git a/musicbrainz_helpers.py b/musicbrainz_helpers.py index 650d752..1ea39c8 100644 --- a/musicbrainz_helpers.py +++ b/musicbrainz_helpers.py @@ -1,3 +1,4 @@ +#musicbrainz_helpers.py import json from pathlib import Path @@ -7,12 +8,16 @@ def load_cache(): try: if not CACHE_FILE.exists(): with open(CACHE_FILE, "w") as f: - json.dump({"added_artists": [], "similar_cache": {}}, f) + json.dump({ + "added_artists": [], + "similar_cache": {}, + "added_tracks": [] + }, f) with open(CACHE_FILE, "r") as f: return json.load(f) except Exception: - return {"added_artists": [], "similar_cache": {}} - -def save_cache(cache): - with open(CACHE_FILE, "w") as f: - json.dump(cache, f, indent=2) + return { + "added_artists": [], + "similar_cache": {}, + "added_tracks": [] + } diff --git a/plex_helpers.py b/plex_helpers.py new file mode 100644 index 0000000..d1128fb --- /dev/null +++ b/plex_helpers.py @@ -0,0 +1,73 @@ +# plex_helpers.py +import requests +from config import PLEX_URL, PLEX_TOKEN +from lastfm_helpers import get_top_tracks, lf_request + +HEADERS = { + "X-Plex-Token": PLEX_TOKEN +} + +def get_artist_name_from_mbid(mbid): + js = lf_request("artist.getInfo", mbid=mbid) + if js and "artist" in js: + return js["artist"]["name"] + return None + +def search_track(artist, track): + query = f"{artist} {track}" + params = { + "type": "10", # track + "query": query + } + res = requests.get(f"{PLEX_URL}/search", params=params, headers=HEADERS) + res.raise_for_status() + return res.json() + +def get_top_tracks_keys(artist_names, top_n=3, already_added=None): + if already_added is None: + already_added = [] + + keys = [] + for artist in artist_names: + top_tracks = get_top_tracks(artist, limit=top_n) + for track in top_tracks: + try: + result = search_track(artist, track) + items = result.get("MediaContainer", {}).get("Metadata", []) + for item in items: + key = item.get("ratingKey") + if key and key not in already_added: + keys.append(key) + except Exception: + continue + return keys + +def create_or_update_playlist(name, mbid_list, top_n=3, already_added=None): + artist_names = [] + for mbid in mbid_list: + name = get_artist_name_from_mbid(mbid) + if name: + artist_names.append(name) + + track_keys = get_top_tracks_keys(artist_names, top_n=top_n, already_added=already_added) + + if not track_keys: + print("[PLEX] Inga nya spår hittades för de angivna artisterna.") + return False, [] + + keys_csv = ",".join(track_keys) + url = f"{PLEX_URL}/playlists" + payload = { + "type": "audio", + "title": name, + "smart": "0", + "uri": f"server://{PLEX_TOKEN}/com.plexapp.plugins.library/library/metadata/{keys_csv}" + } + r = requests.post(url, headers=HEADERS, params=payload) + if r.status_code == 201: + print(f"[PLEX] ✅ Spellistan '{name}' skapades med {len(track_keys)} spår.") + return True, track_keys + else: + print(f"[PLEX] ❌ Misslyckades med att skapa spellista: {r.text}") + return False, [] +