//! Module d'accès aux données utilisateur (favoris) use super::catalog::{AlbumResponse, ArtistResponse, PlaylistResponse, TrackResponse}; use super::QobuzApi; use crate::error::{QobuzError, Result}; use crate::models::*; use serde::Deserialize; use tracing::debug; /// Réponse paginée #[derive(Debug, Deserialize)] struct PaginatedResponse { items: Vec, } /// Réponse de l'endpoint /favorite/getUserFavorites #[derive(Debug, Deserialize)] struct FavoritesResponse { #[serde(default)] albums: Option>, #[serde(default)] artists: Option>, #[serde(default)] tracks: Option>, } /// Réponse de l'endpoint /playlist/getUserPlaylists #[derive(Debug, Deserialize)] struct UserPlaylistsResponse { playlists: PaginatedResponse, } impl QobuzApi { /// Vérifie que l'utilisateur est authentifié fn ensure_authenticated(&self) -> Result<&str> { self.user_id .as_deref() .ok_or_else(|| QobuzError::Unauthorized("Not authenticated".to_string())) } /// Récupère les albums favoris de l'utilisateur pub async fn get_favorite_albums(&self) -> Result> { let user_id = self.ensure_authenticated()?; debug!("Fetching favorite albums for user {}", user_id); let params = [("user_id", user_id), ("type", "albums"), ("limit", "1000")]; let response: FavoritesResponse = self.get("/favorite/getUserFavorites", ¶ms).await?; if let Some(albums) = response.albums { Ok(albums .items .into_iter() .map(QobuzApi::parse_album) .filter(|a| a.streamable) .collect()) } else { Ok(Vec::new()) } } /// Récupère les artistes favoris de l'utilisateur pub async fn get_favorite_artists(&self) -> Result> { let user_id = self.ensure_authenticated()?; debug!("Fetching favorite artists for user {}", user_id); let params = [ ("user_id", user_id), ("type", "artists"), ("limit", "1000"), ]; let response: FavoritesResponse = self.get("/favorite/getUserFavorites", ¶ms).await?; if let Some(artists) = response.artists { Ok(artists .items .into_iter() .map(QobuzApi::parse_artist) .collect()) } else { Ok(Vec::new()) } } /// Récupère les tracks favorites de l'utilisateur pub async fn get_favorite_tracks(&self) -> Result> { let user_id = self.ensure_authenticated()?; debug!("Fetching favorite tracks for user {}", user_id); let params = [("user_id", user_id), ("type", "tracks"), ("limit", "1000")]; let response: FavoritesResponse = self.get("/favorite/getUserFavorites", ¶ms).await?; if let Some(tracks) = response.tracks { Ok(tracks .items .into_iter() .map(|t| QobuzApi::parse_track(t, None)) .filter(|t| t.streamable) .collect()) } else { Ok(Vec::new()) } } /// Récupère les playlists de l'utilisateur pub async fn get_user_playlists(&self) -> Result> { let user_id = self.ensure_authenticated()?; debug!("Fetching playlists for user {}", user_id); let params = [("user_id", user_id), ("limit", "1000")]; let response: UserPlaylistsResponse = self.get("/playlist/getUserPlaylists", ¶ms).await?; Ok(response .playlists .items .into_iter() .map(QobuzApi::parse_playlist) .collect()) } }