"""Spotify via Last.fm Scrobble - responsive.""" import os, sys, json import urllib.request, urllib.error, urllib.parse sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) from plugins.base import Widget from palette import FG, INFO, OK, WARN, measure, fit_font, centered_text, is_small, is_wide def _fetch_lastfm(api_key, user): url = (f"http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks" f"&user={urllib.parse.quote(user)}&api_key={api_key}" f"&format=json&limit=2") with urllib.request.urlopen(url, timeout=8) as r: return json.loads(r.read()) class Widget(Widget): name = "spotify" label = "Spotify (Last.fm)" description = "Zeigt aktuell gespielten Spotify-Track via Last.fm Scrobble." category = "info" config_schema = [ {"key": "api_key", "label": "Last.fm API Key", "type": "secret"}, {"key": "username", "label": "Last.fm Username", "type": "string", "default": ""}, ] default_config = {"api_key": "", "username": ""} def fetch(self): api_key = self.cfg("api_key") user = self.cfg("username") if not api_key or not user: return {"_error": "API-Key oder Username fehlt"} try: return _fetch_lastfm(api_key, user) except Exception as e: return {"_error": str(e)} def render(self, draw, fonts, x, y, w, h): pad = 8 draw.text((x + pad, y + pad), "SPOTIFY", font=fonts.get("24", fonts.get("20")), fill=INFO) d = self.fetch() if "_error" in d: font = fit_font(draw, "Konfig fehlt", fonts, w - 2 * pad, h - 80) centered_text(draw, "Konfig fehlt", x, y + 60, w, h - 60, font, WARN) return try: tracks = d.get("recenttracks", {}).get("track", []) if isinstance(tracks, dict): tracks = [tracks] if not tracks: font = fit_font(draw, "Kein Track", fonts, w - 2 * pad, h - 80) centered_text(draw, "Kein Track", x, y + 60, w, h - 60, font, FG) return current = tracks[0] is_playing = current.get("@attr", {}).get("nowplaying") == "true" artist = current.get("artist", {}).get("#text", "?") track = current.get("name", "?") color = OK if is_playing else WARN if is_small(w, h): txt = "▶" if is_playing else "⏸" font = fit_font(draw, txt, fonts, w - 2 * pad, h - 2 * pad) centered_text(draw, txt, x, y, w, h, font, color) return # Header symbol status_str = "▶ " if is_playing else "⏸" font_st = fit_font(draw, status_str, fonts, 50, h // 4) draw.text((x + pad, y + 50), status_str, font=font_st, fill=color) # Track info font_a = fit_font(draw, artist, fonts, w - 60, h // 4) font_t = fit_font(draw, track, fonts, w - 20, h // 4) draw.text((x + 60, y + 50), artist[:30], font=font_a, fill=FG) draw.text((x + 60, y + 50 + font_a.size + 8), track[:35], font=font_t, fill=FG) except Exception as e: font = fit_font(draw, f"Fehler: {e}", fonts, w - 2 * pad, h - 80) centered_text(draw, f"Fehler: {str(e)[:40]}", x, y + 60, w, h - 60, font, WARN)