Handle non-JSON Tidal auth responses
Detect JSON decode-like exceptions from Tidal's token endpoint and return a safer, more actionable error message. Adds a _looks_like_json_decode_error helper and special-cases that error in check_device_auth to log the non-JSON response and advise disabling VPN/proxy/network filtering and restarting SoulSync. A test was added to ensure the user-facing message does not leak the raw exception text while still returning an error status. Other errors continue to fall back to the existing behavior.
This commit is contained in:
parent
a3f0018b29
commit
3375b6c4bd
2 changed files with 42 additions and 0 deletions
|
|
@ -95,6 +95,16 @@ HLS_MAP_TAG_RE = re.compile(r'#EXT-X-MAP:.*URI="([^"]+)"')
|
||||||
from core.download_plugins.base import DownloadSourcePlugin
|
from core.download_plugins.base import DownloadSourcePlugin
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_json_decode_error(exc: Exception) -> bool:
|
||||||
|
name = exc.__class__.__name__.lower()
|
||||||
|
message = str(exc).lower()
|
||||||
|
return (
|
||||||
|
"jsondecodeerror" in name
|
||||||
|
or "expecting value" in message
|
||||||
|
or "could not decode json" in message
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TidalDownloadClient(DownloadSourcePlugin):
|
class TidalDownloadClient(DownloadSourcePlugin):
|
||||||
"""
|
"""
|
||||||
Tidal download client using tidalapi.
|
Tidal download client using tidalapi.
|
||||||
|
|
@ -230,6 +240,18 @@ class TidalDownloadClient(DownloadSourcePlugin):
|
||||||
return {'status': 'error', 'message': 'Auth completed but session invalid'}
|
return {'status': 'error', 'message': 'Auth completed but session invalid'}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
if _looks_like_json_decode_error(e):
|
||||||
|
logger.error(
|
||||||
|
"Tidal device auth check received a non-JSON response from Tidal's token endpoint: %s",
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
'status': 'error',
|
||||||
|
'message': (
|
||||||
|
"Tidal returned an invalid auth response while SoulSync was finishing login. "
|
||||||
|
"Try again after disabling VPN/proxy/network filtering, then restart SoulSync if it repeats."
|
||||||
|
),
|
||||||
|
}
|
||||||
logger.error(f"Tidal device auth check error: {e}")
|
logger.error(f"Tidal device auth check error: {e}")
|
||||||
return {'status': 'error', 'message': str(e)}
|
return {'status': 'error', 'message': str(e)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,26 @@ def test_is_authenticated_false_when_session_check_login_raises(tidal_client_wit
|
||||||
assert client.is_authenticated() is False
|
assert client.is_authenticated() is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_check_device_auth_returns_helpful_message_for_non_json_tidal_response(tidal_client_with_engine):
|
||||||
|
client, _ = tidal_client_with_engine
|
||||||
|
|
||||||
|
class FakeFuture:
|
||||||
|
def running(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def result(self, timeout=0):
|
||||||
|
raise ValueError("Expecting value: line 1 column 1 (char 0)")
|
||||||
|
|
||||||
|
client._device_auth_future = FakeFuture()
|
||||||
|
client._device_auth_link = {'verification_uri': 'https://link.tidal.com', 'user_code': 'ABCD'}
|
||||||
|
|
||||||
|
result = client.check_device_auth()
|
||||||
|
|
||||||
|
assert result['status'] == 'error'
|
||||||
|
assert 'invalid auth response' in result['message']
|
||||||
|
assert 'Expecting value' not in result['message']
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# download() — filename parsing + id contract
|
# download() — filename parsing + id contract
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue