fix(tidal): refresh access token correctly (#1984)
authorJozef Kruszynski <60214390+jozefKruszynski@users.noreply.github.com>
Wed, 26 Feb 2025 20:20:43 +0000 (21:20 +0100)
committerGitHub <noreply@github.com>
Wed, 26 Feb 2025 20:20:43 +0000 (21:20 +0100)
music_assistant/providers/tidal/__init__.py
music_assistant/providers/tidal/helpers.py

index 20661290e85c891deb4a109f2e67bb3e5134f9ef..d2fb5de82076cf14b09379d880ddf6d4cf77cac3 100644 (file)
@@ -7,11 +7,15 @@ import base64
 import pickle
 from collections.abc import Callable
 from contextlib import suppress
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
 from enum import StrEnum
 from typing import TYPE_CHECKING, ParamSpec, TypeVar, cast
 
-from music_assistant_models.config_entries import ConfigEntry, ConfigValueOption, ConfigValueType
+from music_assistant_models.config_entries import (
+    ConfigEntry,
+    ConfigValueOption,
+    ConfigValueType,
+)
 from music_assistant_models.enums import (
     AlbumType,
     CacheCategory,
@@ -48,7 +52,10 @@ from tidalapi import exceptions as tidal_exceptions
 
 from music_assistant.helpers.auth import AuthenticationHelper
 from music_assistant.helpers.tags import AudioTags, async_parse_tags
-from music_assistant.helpers.throttle_retry import ThrottlerManager, throttle_with_retries
+from music_assistant.helpers.throttle_retry import (
+    ThrottlerManager,
+    throttle_with_retries,
+)
 from music_assistant.models.music_provider import MusicProvider
 
 from .helpers import (
@@ -74,6 +81,7 @@ from .helpers import (
     library_items_add_remove,
     remove_playlist_tracks,
     search,
+    token_refresh,
 )
 
 if TYPE_CHECKING:
@@ -658,11 +666,13 @@ class TidalProvider(MusicProvider):
 
     async def _get_tidal_session(self) -> TidalSession:
         """Ensure the current token is valid and return a tidal session."""
+        token_expiry = datetime.fromisoformat(str(self.config.get_value(CONF_EXPIRY_TIME)))
+        token_expiry_with_tz = token_expiry.replace(tzinfo=UTC)
+        utc_now_plus_one_hour = datetime.now(UTC) + timedelta(hours=1)
         if (
             self._tidal_session
             and self._tidal_session.access_token
-            and datetime.fromisoformat(str(self.config.get_value(CONF_EXPIRY_TIME)))
-            > (datetime.now() + timedelta(days=1))
+            and token_expiry_with_tz > utc_now_plus_one_hour
         ):
             return self._tidal_session
 
@@ -674,6 +684,8 @@ class TidalProvider(MusicProvider):
                 refresh_token=str(self.config.get_value(CONF_REFRESH_TOKEN)),
                 expiry_time=datetime.fromisoformat(str(self.config.get_value(CONF_EXPIRY_TIME))),
             )
+            await token_refresh(self._tidal_session)
+
         except Exception as err:
             if "401 Client Error: Unauthorized" in str(err):
                 err_msg = "Credentials expired, you need to re-setup"
@@ -773,7 +785,10 @@ class TidalProvider(MusicProvider):
 
         # Cache the mapping for future use
         await self.mass.cache.set(
-            cache_key, tracks[0].id, category=CacheCategory.DEFAULT, base_key=self.lookup_key
+            cache_key,
+            tracks[0].id,
+            category=CacheCategory.DEFAULT,
+            base_key=self.lookup_key,
         )
 
         return tracks[0]
index ec87e05bfafbeecc4bb1f2966cb15083f698af47..24e1805bf2a0b3ea295e323ff78c7785dcfdf2bf 100644 (file)
@@ -422,3 +422,12 @@ async def search(
         return results
 
     return await asyncio.to_thread(inner)
+
+
+async def token_refresh(session: TidalSession) -> None:
+    """Async wrapper around the tidalapi Session.refresh function."""
+
+    def inner() -> None:
+        session.token_refresh(session.refresh_token)
+
+    return await asyncio.to_thread(inner)