mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Add more HTTP endpoints and migrate playlist
This commit is contained in:
parent
922e927231
commit
70eb3f9d72
3 changed files with 85 additions and 56 deletions
|
@ -386,7 +386,7 @@ impl SpClient {
|
|||
}
|
||||
|
||||
pub async fn get_lyrics(&self, track_id: SpotifyId) -> SpClientResult {
|
||||
let endpoint = format!("/color-lyrics/v1/track/{}", track_id.to_base62()?);
|
||||
let endpoint = format!("/color-lyrics/v2/track/{}", track_id.to_base62()?);
|
||||
|
||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||
.await
|
||||
|
@ -407,6 +407,87 @@ impl SpClient {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn get_playlist(&self, playlist_id: SpotifyId) -> SpClientResult {
|
||||
let endpoint = format!("/playlist/v2/playlist/{}", playlist_id);
|
||||
|
||||
self.request(&Method::GET, &endpoint, None, None).await
|
||||
}
|
||||
|
||||
pub async fn get_user_profile(
|
||||
&self,
|
||||
username: String,
|
||||
playlist_limit: Option<u32>,
|
||||
artist_limit: Option<u32>,
|
||||
) -> SpClientResult {
|
||||
let mut endpoint = format!("/user-profile-view/v3/profile/{}", username);
|
||||
|
||||
if playlist_limit.is_some() || artist_limit.is_some() {
|
||||
let _ = write!(endpoint, "?");
|
||||
|
||||
if let Some(limit) = playlist_limit {
|
||||
let _ = write!(endpoint, "playlist_limit={}", limit);
|
||||
if artist_limit.is_some() {
|
||||
let _ = write!(endpoint, "&");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(limit) = artist_limit {
|
||||
let _ = write!(endpoint, "artist_limit={}", limit);
|
||||
}
|
||||
}
|
||||
|
||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_user_followers(&self, username: String) -> SpClientResult {
|
||||
let endpoint = format!("/user-profile-view/v3/profile/{}/followers", username);
|
||||
|
||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_user_following(&self, username: String) -> SpClientResult {
|
||||
let endpoint = format!("/user-profile-view/v3/profile/{}/following", username);
|
||||
|
||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_radio_for_track(&self, track_id: SpotifyId) -> SpClientResult {
|
||||
let endpoint = format!(
|
||||
"/inspiredby-mix/v2/seed_to_playlist/{}?response-format=json",
|
||||
track_id.to_uri()?
|
||||
);
|
||||
|
||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_apollo_station(
|
||||
&self,
|
||||
context: SpotifyId,
|
||||
count: u32,
|
||||
previous_tracks: Vec<SpotifyId>,
|
||||
autoplay: bool,
|
||||
) -> SpClientResult {
|
||||
let previous_track_str = previous_tracks
|
||||
.iter()
|
||||
.map(|track| track.to_uri())
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.join(",");
|
||||
let endpoint = format!(
|
||||
"/radio-apollo/v3/stations/{}?count={}&prev_tracks={}&autoplay={}",
|
||||
context.to_uri()?,
|
||||
count,
|
||||
previous_track_str,
|
||||
autoplay,
|
||||
);
|
||||
|
||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
// TODO: Find endpoint for newer canvas.proto and upgrade to that.
|
||||
pub async fn get_canvases(&self, request: EntityCanvazRequest) -> SpClientResult {
|
||||
let endpoint = "/canvaz-cache/v0/canvases";
|
||||
|
|
|
@ -163,7 +163,7 @@ impl SpotifyId {
|
|||
/// can be arbitrary while `{id}` is a 22-character long, base62 encoded Spotify ID.
|
||||
///
|
||||
/// Note that this should not be used for playlists, which have the form of
|
||||
/// `spotify:user:{owner_username}:playlist:{id}`.
|
||||
/// `spotify:playlist:{id}`.
|
||||
///
|
||||
/// [Spotify URI]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids
|
||||
pub fn from_uri(src: &str) -> SpotifyIdResult {
|
||||
|
|
|
@ -4,10 +4,8 @@ use std::{
|
|||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use protobuf::Message;
|
||||
|
||||
use crate::{
|
||||
request::{MercuryRequest, RequestResult},
|
||||
request::RequestResult,
|
||||
util::{impl_deref_wrapped, impl_from_repeated_copy, impl_try_from_repeated},
|
||||
Metadata,
|
||||
};
|
||||
|
@ -55,11 +53,6 @@ pub struct Playlists(pub Vec<SpotifyId>);
|
|||
|
||||
impl_deref_wrapped!(Playlists, Vec<SpotifyId>);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RootPlaylist(pub SelectedListContent);
|
||||
|
||||
impl_deref_wrapped!(RootPlaylist, SelectedListContent);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SelectedListContent {
|
||||
pub revision: Vec<u8>,
|
||||
|
@ -80,31 +73,6 @@ pub struct SelectedListContent {
|
|||
}
|
||||
|
||||
impl Playlist {
|
||||
#[allow(dead_code)]
|
||||
async fn request_for_user(
|
||||
session: &Session,
|
||||
username: &str,
|
||||
playlist_id: SpotifyId,
|
||||
) -> RequestResult {
|
||||
let uri = format!(
|
||||
"hm://playlist/user/{}/playlist/{}",
|
||||
username,
|
||||
playlist_id.to_base62()?
|
||||
);
|
||||
<Self as MercuryRequest>::request(session, &uri).await
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn get_for_user(
|
||||
session: &Session,
|
||||
username: &str,
|
||||
playlist_id: SpotifyId,
|
||||
) -> Result<Self, Error> {
|
||||
let response = Self::request_for_user(session, username, playlist_id).await?;
|
||||
let msg = <Self as Metadata>::Message::parse_from_bytes(&response)?;
|
||||
Self::parse(&msg, playlist_id)
|
||||
}
|
||||
|
||||
pub fn tracks(&self) -> impl ExactSizeIterator<Item = &SpotifyId> {
|
||||
let tracks = self.contents.items.iter().map(|item| &item.id);
|
||||
|
||||
|
@ -125,15 +93,12 @@ impl Playlist {
|
|||
}
|
||||
}
|
||||
|
||||
impl MercuryRequest for Playlist {}
|
||||
|
||||
#[async_trait]
|
||||
impl Metadata for Playlist {
|
||||
type Message = protocol::playlist4_external::SelectedListContent;
|
||||
|
||||
async fn request(session: &Session, playlist_id: SpotifyId) -> RequestResult {
|
||||
let uri = format!("hm://playlist/v2/playlist/{}", playlist_id.to_base62()?);
|
||||
<Self as MercuryRequest>::request(session, &uri).await
|
||||
session.spclient().get_playlist(playlist_id).await
|
||||
}
|
||||
|
||||
fn parse(msg: &Self::Message, id: SpotifyId) -> Result<Self, Error> {
|
||||
|
@ -161,23 +126,6 @@ impl Metadata for Playlist {
|
|||
}
|
||||
}
|
||||
|
||||
impl MercuryRequest for RootPlaylist {}
|
||||
|
||||
impl RootPlaylist {
|
||||
#[allow(dead_code)]
|
||||
async fn request_for_user(session: &Session, username: &str) -> RequestResult {
|
||||
let uri = format!("hm://playlist/user/{}/rootlist", username,);
|
||||
<Self as MercuryRequest>::request(session, &uri).await
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn get_root_for_user(session: &Session, username: &str) -> Result<Self, Error> {
|
||||
let response = Self::request_for_user(session, username).await?;
|
||||
let msg = protocol::playlist4_external::SelectedListContent::parse_from_bytes(&response)?;
|
||||
Ok(Self(SelectedListContent::try_from(&msg)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&<Playlist as Metadata>::Message> for SelectedListContent {
|
||||
type Error = librespot_core::Error;
|
||||
fn try_from(playlist: &<Playlist as Metadata>::Message) -> Result<Self, Self::Error> {
|
||||
|
|
Loading…
Reference in a new issue