From ce48d867a990fc8565f7ce5b4e0f7260d5cd18bb Mon Sep 17 00:00:00 2001 From: Johan Hjorth Date: Wed, 25 Jun 2025 13:17:58 +0200 Subject: [PATCH] started working on plex playlist integration --- plex_playlist_sync.py | 160 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 plex_playlist_sync.py diff --git a/plex_playlist_sync.py b/plex_playlist_sync.py new file mode 100644 index 0000000..37442d8 --- /dev/null +++ b/plex_playlist_sync.py @@ -0,0 +1,160 @@ +# plex_playlist_sync.py (Den fullständiga koden från mitt tidigare svar) + +# Importera konfiguration och hjälpfunktioner från dina befintliga filer +from config import ( + LASTFM_API_KEY, LASTFM_API_SECRET, LASTFM_USERNAME, + PLEX_BASEURL, PLEX_TOKEN, + MIN_PLAYS, RECENT_MONTHS, MAX_SIMILAR_PER_ART, SIMILAR_MATCH_MIN, + CACHE_TTL_HOURS, DEBUG_PRINT +) +from lastfm_helpers import lf_request, recent_artists +from musicbrainz_helpers import load_cache, save_cache # Används för cache + +import pylast +from plexapi.server import PlexServer +import datetime +import time +import logging + +logging.basicConfig(level=logging.INFO) +log = logging.getLogger("PlexPlaylistSync") + +try: + LASTFM_NETWORK = pylast.LastFMNetwork( + api_key=LASTFM_API_KEY, + api_secret=LASTFM_API_SECRET, + username=LASTFM_USERNAME + ) +except Exception as e: + log.error(f"Kunde inte initiera Last.fm-nätverket. Kontrollera nycklar/användarnamn: {e}") + LASTFM_NETWORK = None + +def get_artist_top_tracks(artist_name, limit=5): + if not LASTFM_NETWORK: + return [] + try: + artist = LASTFM_NETWORK.get_artist(artist_name) + top_tracks = artist.get_top_tracks(limit=limit) + return [{"artist": track.item.artist.name, "title": track.item.title} for track in top_tracks] + except Exception as e: + log.warning(f"Kunde inte hämta top-spår för '{artist_name}' från Last.fm: {e}") + return [] + +def create_lastfm_recommended_playlist(): + start_time = time.time() + log.info("🚀 Börjar processen för att skapa Last.fm-baserade spellistor i Plex.") + + try: + plex = PlexServer(PLEX_BASEURL, PLEX_TOKEN) + log.info(f"✅ Ansluten till Plex Media Server: {plex.baseurl}") + except Exception as e: + log.error(f"❌ Kunde inte ansluta till Plex Server: {e}") + log.error("Kontrollera PLEX_BASEURL och PLEX_TOKEN i config_local.py.") + return + + music_library = None + try: + music_library = plex.library.section('Music') + log.info(f"Använder Plex-biblioteket: '{music_library.title}'") + except Exception as e: + log.error(f"❌ Kunde inte hitta musikbiblioteket 'Music' i Plex: {e}") + log.error("Kontrollera namnet på ditt musikbibliotek i Plex.") + return + + artists_for_playlist = [] + cache = load_cache() + added_artists_mbids = cache.get("added_artists", []) + + log.info("Samlar in artister för spellistan...") + for mbid in added_artists_mbids: + try: + artist_info = LASTFM_NETWORK.get_artist_by_mbid(mbid) + artists_for_playlist.append(artist_info.name) + except Exception: + log.debug(f"Kunde inte hitta namn för MBID: {mbid} via pylast.") + pass + + recent_played_artists = recent_artists() + for name, mbid in recent_played_artists[:10]: + if name not in artists_for_playlist: + artists_for_playlist.append(name) + + if not artists_for_playlist: + log.info("Inga artister hittades för att skapa en spellista. Se till att Last.fm-synkroniseringen har kört.") + return + + log.info(f"Hittade {len(artists_for_playlist)} unika artister för att bygga spellistan.") + + all_recommended_tracks_info = [] + for artist_name in artists_for_playlist: + top_tracks = get_artist_top_tracks(artist_name, limit=3) + all_recommended_tracks_info.extend(top_tracks) + + unique_tracks_to_add = [] + seen_track_identifiers = set() + + log.info(f"Söker efter {len(all_recommended_tracks_info)} potentiella spår i Plex-biblioteket...") + for track_info in all_recommended_tracks_info: + artist_name = track_info["artist"] + track_title = track_info["title"] + identifier = f"{artist_name}-{track_title}" + + if identifier in seen_track_identifiers: + continue + + found_plex_track = None + try: + results = music_library.search(f"{artist_name} {track_title}", libtype='track') + + for item in results: + if item.artist() and item.artist().title.lower() == artist_name.lower() and item.title.lower() == track_title.lower(): + found_plex_track = item + break + + except Exception as e: + log.warning(f"Fel vid Plex-sökning efter '{track_title}' av '{artist_name}': {e}") + + if found_plex_track: + unique_tracks_to_add.append(found_plex_track) + seen_track_identifiers.add(identifier) + log.info(f" ✅ Hittade: {found_plex_track.artist().title} - {found_plex_track.title}") + else: + log.info(f" ❌ Hittade inte: '{track_title}' av '{artist_name}' i Plex.") + + if not unique_tracks_to_add: + log.info("Inga nya matchande låtar hittades i Plex för att skapa en spellista.") + return + + current_date = datetime.datetime.now().strftime("%Y-%m") + playlist_name = f"Last.fm Rekommendationer {current_date}" + + playlist = None + try: + playlist = plex.playlist(playlist_name) + log.info(f"Spellistan '{playlist_name}' finns redan.") + except Exception: + log.info(f"Skapar ny spellista: '{playlist_name}'") + + if playlist: + existing_playlist_items = playlist.items() + new_items_to_add = [track for track in unique_tracks_to_add if track not in existing_playlist_items] + + if new_items_to_add: + try: + playlist.addItems(new_items_to_add) + log.info(f"Lade till {len(new_items_to_add)} nya låtar i befintlig spellista '{playlist_name}'.") + except Exception as e: + log.error(f"Kunde inte lägga till låtar i befintlig spellista: {e}") + else: + log.info(f"Inga nya låtar att lägga till i befintlig spellista '{playlist_name}'.") + else: + try: + new_playlist = plex.createPlaylist(playlist_name, items=unique_tracks_to_add) + log.info(f"✅ Skapade ny spellista '{new_playlist.title}' med {len(unique_tracks_to_add)} låtar.") + except Exception as e: + log.error(f"❌ Kunde inte skapa spellista i Plex: {e}") + + log.info(f"🎉 Klar! Processen tog {((time.time()-start_time)/60):.1f} minuter.") + +if __name__ == "__main__": + create_lastfm_recommended_playlist() \ No newline at end of file