From cb1e13b0fcc19d584aa9440874828cf438165e77 Mon Sep 17 00:00:00 2001 From: fojadrachi Date: Fri, 11 Sep 2026 19:46:32 +0200 Subject: [PATCH] Fix: Discord RPC hat nie Daten empfangen (runJavaScript-Bug) Wurzelursache gefunden: page().runJavaScript() liefert bei einem direkt zurueckgegebenen JS-Objekt in dieser PySide6/QtWebEngine-Version zuverlaessig nur einen leeren String statt das Objekt (Zahlen/Strings funktionieren, Objekte nicht). Dadurch schlug 'isinstance(result, dict)' in BrowserTab._on_media_probe_result IMMER fehl, mediaInfoChanged wurde nie emittiert, MainWindow._on_media_info nie aufgerufen und der DiscordRPCWorker damit nie mit echten Daten gefuettert (Warteschlange blieb fuer immer leer, der Worker hat sich nie mal mit Discord verbunden). Fix: media_probe.py gibt jetzt JSON.stringify(...) zurueck, browser.py parst den String mit json.loads(). Per isoliertem Test verifiziert (Songtitel erscheint jetzt korrekt im Fenstertitel, Discord-Update wird erfolgreich gesendet). Ausserdem: PLAYTUBE_DEBUG=1 Env-Var fuer Debug-Logging in browser.py/discord_rpc.py, Exceptions in discord_rpc.py werden jetzt sichtbar geloggt statt verschluckt, neue Discord Client-ID. Co-Authored-By: Claude Sonnet 5 --- playtube/browser.py | 21 +++++++++++++++++++-- playtube/config.py | 2 +- playtube/discord_rpc.py | 20 ++++++++++++++++---- playtube/media_probe.py | 9 +++++++-- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/playtube/browser.py b/playtube/browser.py index 37e2281..88bbec0 100644 --- a/playtube/browser.py +++ b/playtube/browser.py @@ -3,6 +3,8 @@ Profil (eigener Datenordner, kein System-Browser-Profil) und periodischem Ausles der aktuellen Wiedergabe fuer Discord Rich Presence.""" from __future__ import annotations +import json +import os import sys from PySide6.QtCore import QTimer, Signal, QUrl @@ -162,5 +164,20 @@ class BrowserTab(QWebEngineView): self.page().runJavaScript(MEDIA_PROBE_JS, self._on_media_probe_result) def _on_media_probe_result(self, result) -> None: - if isinstance(result, dict): - self.mediaInfoChanged.emit(result) + # runJavaScript() liefert JS-Objekte ueber diese Bruecke nicht zuverlaessig + # als dict (siehe media_probe.py) - das Probe-Skript gibt daher einen + # JSON-String zurueck, der hier geparst wird. + info = None + if isinstance(result, str) and result: + try: + info = json.loads(result) + except json.JSONDecodeError: + info = None + elif isinstance(result, dict): + info = result + + if os.environ.get("PLAYTUBE_DEBUG"): + print(f"[media-probe:{self._home_url}] roh={result!r} geparst={info!r}", flush=True) + + if isinstance(info, dict): + self.mediaInfoChanged.emit(info) diff --git a/playtube/config.py b/playtube/config.py index c40a459..77d5465 100644 --- a/playtube/config.py +++ b/playtube/config.py @@ -15,7 +15,7 @@ DEFAULT_CONFIG: dict[str, Any] = { "discord": { "enabled": True, # Deine Discord Application Client-ID (discord.com/developers/applications). - "client_id": "1544058029190938774", + "client_id": "1548023494976086127", "update_interval_seconds": 15, # Wenn nichts laeuft: Idle-Status anzeigen statt Presence komplett zu leeren. "show_idle_presence": True, diff --git a/playtube/discord_rpc.py b/playtube/discord_rpc.py index 9b5a624..1d61e19 100644 --- a/playtube/discord_rpc.py +++ b/playtube/discord_rpc.py @@ -7,6 +7,7 @@ versucht, ohne die App zu beeintraechtigen. """ from __future__ import annotations +import os import queue import time from typing import Any @@ -156,8 +157,12 @@ class DiscordRPCWorker(QThread): self._presence = Presence(self._client_id) self._presence.connect() self._connected = True - except Exception: + if os.environ.get("PLAYTUBE_DEBUG"): + print("[discord-rpc] verbunden", flush=True) + except Exception as exc: self._connected = False + if os.environ.get("PLAYTUBE_DEBUG"): + print(f"[discord-rpc] Verbindung fehlgeschlagen: {exc!r}", flush=True) def _send(self, item) -> None: if self._presence is None: @@ -165,14 +170,21 @@ class DiscordRPCWorker(QThread): try: if item is _IDLE_SENTINEL: if self._show_idle: - self._presence.update(**build_idle_payload(self._session_start)) + payload = build_idle_payload(self._session_start) + self._presence.update(**payload) else: + payload = None self._presence.clear() else: - self._presence.update(**build_presence_payload(item, self._session_start)) - except Exception: + payload = build_presence_payload(item, self._session_start) + self._presence.update(**payload) + if os.environ.get("PLAYTUBE_DEBUG"): + print(f"[discord-rpc] gesendet: {payload!r}", flush=True) + except Exception as exc: # Discord evtl. geschlossen worden -> beim naechsten Mal neu verbinden. self._connected = False + if os.environ.get("PLAYTUBE_DEBUG"): + print(f"[discord-rpc] Senden fehlgeschlagen: {exc!r}", flush=True) def _cleanup(self) -> None: if self._presence is not None: diff --git a/playtube/media_probe.py b/playtube/media_probe.py index bce2d99..68fd53c 100644 --- a/playtube/media_probe.py +++ b/playtube/media_probe.py @@ -27,7 +27,12 @@ MEDIA_PROBE_JS = r""" thumbnail = imgY ? imgY.href : null; } - return { + // WICHTIG: QtWebEngine's runJavaScript()-Bruecke liefert bei einem direkt + // zurueckgegebenen JS-Objekt zuverlaessig nur einen leeren String statt des + // Objekts (Zahlen/Strings funktionieren, Objekte nicht) - deshalb hier als + // JSON-String zurueckgeben und in Python mit json.loads() wieder parsen + // (siehe BrowserTab._on_media_probe_result in browser.py). + return JSON.stringify({ isMusic: isMusic, title: title, subtitle: subtitle, @@ -37,7 +42,7 @@ MEDIA_PROBE_JS = r""" currentTime: video ? video.currentTime : 0, duration: (video && isFinite(video.duration)) ? video.duration : 0, hasVideo: !!video - }; + }); })(); """