working on plex_playlists based on gemini

This commit is contained in:
Johan Hjorth 2025-06-25 13:53:24 +02:00
parent ce48d867a9
commit 88d1f94748
3 changed files with 142 additions and 96 deletions

View file

@ -1,47 +1,89 @@
from config import *
import requests, time, urllib.parse
from collections import defaultdict
from datetime import datetime, timedelta
# lastfm_helpers.py
def lf_request(method, **params):
# Fixa 'from_' → 'from' och 'to_' → 'to' (Last.fm accepterar inte Python-säkra namn)
for alt, real in (("from_", "from"), ("to_", "to")):
if alt in params:
params[real] = params.pop(alt)
url = "https://ws.audioscrobbler.com/2.0/"
params.update({
"method": method,
"api_key": LASTFM_API_KEY,
"format": "json"
})
try:
r = requests.get(url, params=params)
r.raise_for_status()
return r.json()
except Exception as e:
print(f"[LFM ERR] {e}")
return None
import pylast
from config import (
LASTFM_API_KEY, LASTFM_API_SECRET, LASTFM_USERNAME,
MIN_PLAYS, RECENT_MONTHS
)
import logging
from datetime import datetime, timedelta
from collections import defaultdict
log = logging.getLogger("LastFmHelpers")
LASTFM_NETWORK = None
try:
LASTFM_NETWORK = pylast.LastFMNetwork(
api_key=LASTFM_API_KEY,
api_secret=LASTFM_API_SECRET,
username=LASTFM_USERNAME
)
log.info("✅ Connected to Last.fm API.")
except Exception as e:
log.error(f"❌ Failed to initialize Last.fm network. Check API keys and username: {e}")
def recent_artists():
since = int((datetime.utcnow() - timedelta(days=30 * RECENT_MONTHS)).timestamp())
"""Fetches recently played artists from Last.fm, filtered by play count and recency."""
if not LASTFM_NETWORK:
log.error("Last.fm network not initialized. Cannot fetch recent artists.")
return []
user = LASTFM_NETWORK.get_user(LASTFM_USERNAME)
since_timestamp = int((datetime.utcnow() - timedelta(days=30 * RECENT_MONTHS)).timestamp())
counts = defaultdict(int)
page = 1
while True:
js = lf_request(
"user.getRecentTracks", user=LASTFM_USERNAME,
limit=200, page=page, from_=since
)
if not js:
break
log.info(f"Fetching recent tracks for {LASTFM_USERNAME} since {datetime.fromtimestamp(since_timestamp).strftime('%Y-%m-%d %H:%M:%S')}")
try:
for track in user.get_recent_tracks(time_from=since_timestamp, limit=None):
artist = track.artist
counts[(artist.name, artist.mbid)] += 1
except pylast.NetworkError as ne:
log.error(f"Network error fetching recent tracks: {ne}")
return []
except pylast.WSError as wse:
log.error(f"Last.fm API error fetching recent tracks: {wse}")
return []
except Exception as e:
log.error(f"Unexpected error fetching recent tracks: {e}")
return []
for t in js.get("recenttracks", {}).get("track", []):
a = t["artist"]
counts[(a["#text"], a.get("mbid", ""))] += 1
return [(name, mbid) for (name, mbid), count in counts.items() if count >= MIN_PLAYS]
attr = js.get("recenttracks", {}).get("@attr", {})
if page >= int(attr.get("totalPages", 1)):
break
page += 1
def get_similar_artists_pylast(artist_mbid, limit):
"""Fetches artists similar to a given artist from Last.fm."""
if not LASTFM_NETWORK:
log.error("Last.fm network not initialized. Cannot fetch similar artists.")
return []
try:
artist = LASTFM_NETWORK.get_artist_by_mbid(artist_mbid)
similar_artists_tuples = artist.get_similar(limit=limit)
return similar_artists_tuples
except pylast.WSError as wse:
log.warning(f"Last.fm API error fetching similar artists for MBID {artist_mbid}: {wse}. Check MBID.")
return []
except pylast.NetworkError as ne:
log.warning(f"Network error fetching similar artists for MBID {artist_mbid}: {ne}")
return []
except Exception as e:
log.warning(f"Could not fetch similar artists for MBID {artist_mbid}: {e}")
return []
return [(n, m) for (n, m), c in counts.items() if c >= MIN_PLAYS]
def get_artist_top_tracks(artist_name, limit=5):
"""Fetches top tracks for a specific artist from Last.fm."""
if not LASTFM_NETWORK:
log.error("Last.fm network not initialized. Cannot fetch top tracks.")
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 pylast.WSError as wse:
log.warning(f"Last.fm API error fetching top tracks for '{artist_name}': {wse}. Check artist name.")
return []
except pylast.NetworkError as ne:
log.warning(f"Network error fetching top tracks for '{artist_name}': {ne}")
return []
except Exception as e:
log.warning(f"Unexpected error fetching top tracks for '{artist_name}': {e}")
return []