From 88a3228a3bdc7c92de6867ac2529ae646e37b558 Mon Sep 17 00:00:00 2001 From: Jozef Kruszynski <60214390+jozefKruszynski@users.noreply.github.com> Date: Sun, 9 Mar 2025 00:50:39 +0100 Subject: [PATCH] Tidal provider maintenance: add tidaluser class (#2010) --- music_assistant/providers/tidal/__init__.py | 19 ++++++++-- .../providers/tidal/auth_manager.py | 36 +++++++++++++------ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/music_assistant/providers/tidal/__init__.py b/music_assistant/providers/tidal/__init__.py index be577803..fb03c7b9 100644 --- a/music_assistant/providers/tidal/__init__.py +++ b/music_assistant/providers/tidal/__init__.py @@ -377,7 +377,8 @@ class TidalProvider(MusicProvider): # Get user information from sessions API api_result = await self._get_data("sessions") user_info = self._extract_data(api_result) - await self.auth.update_user_info(user_info) + logged_in_user = await self.get_user(str(user_info.get("userId"))) + await self.auth.update_user_info(logged_in_user, str(user_info.get("sessionId"))) @property def supported_features(self) -> set[ProviderFeature]: @@ -614,6 +615,11 @@ class TidalProvider(MusicProvider): # SEARCH & DISCOVERY # + async def get_user(self, prov_user_id: str) -> dict[str, Any]: + """Get user information.""" + api_result = await self._get_data(f"users/{prov_user_id}") + return self._extract_data(api_result) + async def search( self, search_query: str, @@ -1313,11 +1319,20 @@ class TidalProvider(MusicProvider): if playlist_obj["creator"]: creator_id = playlist_obj["creator"]["id"] is_editable = bool(creator_id and str(creator_id) == str(self.auth.user_id)) + + owner_name = "Tidal" + if is_editable: + if self.auth.user.profile_name: + owner_name = self.auth.user.profile_name + elif self.auth.user.user_name: + owner_name = self.auth.user.user_name + else: + owner_name = str(self.auth.user_id or "Unknown") playlist = Playlist( item_id=playlist_id, provider=self.instance_id if is_editable else self.lookup_key, name=playlist_obj["title"], - owner=creator_id or "Tidal", + owner=owner_name, provider_mappings={ ProviderMapping( item_id=playlist_id, diff --git a/music_assistant/providers/tidal/auth_manager.py b/music_assistant/providers/tidal/auth_manager.py index b6b63634..e55f0099 100644 --- a/music_assistant/providers/tidal/auth_manager.py +++ b/music_assistant/providers/tidal/auth_manager.py @@ -5,6 +5,7 @@ import random import time import urllib from collections.abc import Callable +from dataclasses import dataclass from types import TracebackType from typing import TYPE_CHECKING, Any @@ -24,6 +25,18 @@ AUTH_URL = "https://auth.tidal.com/v1/oauth2" REDIRECT_URI = "https://tidal.com/android/login/auth" +@dataclass +class TidalUser: + """Represent a Tidal user with their associated account information.""" + + user_id: str | None = None + country_code: str | None = None + session_id: str | None = None + profile_name: str | None = None + user_name: str | None = None + email: str | None = None + + class ManualAuthenticationHelper: """Helper for authentication flows that require manual user intervention. @@ -68,9 +81,7 @@ class TidalAuthManager: self.update_config = config_updater self.logger = logger self._auth_info = None - self._user_id = None - self._country_code = None - self._session_id = None + self.user = TidalUser() async def initialize(self, auth_data: str) -> bool: """Initialize the auth manager with stored auth data.""" @@ -86,17 +97,17 @@ class TidalAuthManager: @property def user_id(self) -> str | None: """Return the current user ID.""" - return self._user_id + return self.user.user_id @property def country_code(self) -> str | None: """Return the current country code.""" - return self._country_code + return self.user.country_code @property def session_id(self) -> str | None: """Return the current session ID.""" - return self._session_id + return self.user.session_id @property def access_token(self) -> str | None: @@ -159,11 +170,16 @@ class TidalAuthManager: return True - async def update_user_info(self, user_info: dict[str, Any]) -> None: + async def update_user_info(self, user_info: dict[str, Any], session_id: str) -> None: """Update user info from API response.""" - self._user_id = user_info.get("userId") - self._country_code = user_info.get("countryCode") - self._session_id = user_info.get("sessionId") + # Update the TidalUser dataclass with values from API response + self.user = TidalUser( + user_id=user_info.get("id"), + country_code=user_info.get("countryCode"), + session_id=session_id, + profile_name=user_info.get("profileName"), + user_name=user_info.get("username"), + ) @staticmethod async def generate_auth_url(auth_helper: ManualAuthenticationHelper, quality: str) -> str: -- 2.34.1