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
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
Tidal download client using tidalapi.
|
||||
|
|
@ -230,6 +240,18 @@ class TidalDownloadClient(DownloadSourcePlugin):
|
|||
return {'status': 'error', 'message': 'Auth completed but session invalid'}
|
||||
|
||||
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}")
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in a new issue