feat: add Qobuz playlist follow/unfollow (#172)
Discovered undocumented Qobuz API endpoints from bundle analysis:
- POST /playlist/subscribe { playlist_id }
- POST /playlist/unsubscribe { playlist_id }
This is the native "follow playlist" feature that syncs across all
Qobuz clients, separate from QBZ's existing "Copy to Library" (local
copy) and "Favorite" (local flag) features.
Added:
- subscribe_playlist/unsubscribe_playlist in both qbz-qobuz and legacy client
- v2_qobuz_subscribe_playlist / v2_qobuz_unsubscribe_playlist commands
- Bookmark toggle button in PlaylistDetailView (next to Copy button)
- i18n keys in all 5 locales
cc
This commit is contained in:
12 files changed
+163
-2
No files matched your search
@@ -1622,6 +1622,54 @@ impl QobuzClient {
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// Subscribe to a Qobuz playlist (follow it in the user's library)
|
||||
pub async fn subscribe_playlist(&self, playlist_id: u64) -> Result<()> {
|
||||
let url = endpoints::build_url(paths::PLAYLIST_SUBSCRIBE);
|
||||
|
||||
let response = self
|
||||
.http
|
||||
.get(&url)
|
||||
.headers(self.authenticated_headers().await?)
|
||||
.query(&[("playlist_id", playlist_id.to_string())])
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
let body = response.text().await.unwrap_or_default();
|
||||
return Err(ApiError::ApiResponse(format!(
|
||||
"playlist/subscribe failed ({}): {}",
|
||||
status, body
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unsubscribe from a Qobuz playlist
|
||||
pub async fn unsubscribe_playlist(&self, playlist_id: u64) -> Result<()> {
|
||||
let url = endpoints::build_url(paths::PLAYLIST_UNSUBSCRIBE);
|
||||
|
||||
let response = self
|
||||
.http
|
||||
.get(&url)
|
||||
.headers(self.authenticated_headers().await?)
|
||||
.query(&[("playlist_id", playlist_id.to_string())])
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
let body = response.text().await.unwrap_or_default();
|
||||
return Err(ApiError::ApiResponse(format!(
|
||||
"playlist/unsubscribe failed ({}): {}",
|
||||
status, body
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add item to favorites
|
||||
pub async fn add_favorite(&self, fav_type: &str, item_id: &str) -> Result<()> {
|
||||
let url = endpoints::build_url(paths::FAVORITE_CREATE);
|
||||
|
||||
@@ -39,6 +39,8 @@ pub mod paths {
|
||||
pub const PLAYLIST_DELETE_TRACKS: &str = "/playlist/deleteTracks";
|
||||
pub const PLAYLIST_UPDATE: &str = "/playlist/update";
|
||||
pub const PLAYLIST_GET_TAGS: &str = "/playlist/getTags";
|
||||
pub const PLAYLIST_SUBSCRIBE: &str = "/playlist/subscribe";
|
||||
pub const PLAYLIST_UNSUBSCRIBE: &str = "/playlist/unsubscribe";
|
||||
|
||||
// Favorites
|
||||
pub const FAVORITE_GET_USER_FAVORITES: &str = "/favorite/getUserFavorites";
|
||||
|
||||
Reference in new issue
Block a user