Skip to content

Commit

Permalink
Merge pull request #157 from ramsayleung/ramsay_refactor_model
Browse files Browse the repository at this point in the history
  • Loading branch information
ramsayleung authored Dec 15, 2020
2 parents f264eaa + 1bf32cf commit b47bf6f
Show file tree
Hide file tree
Showing 16 changed files with 744 additions and 113 deletions.
24 changes: 22 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ If we missed any change or there's something you'd like to discuss about this ve
+ `FullAlbum`
+ `SimplifiedArtist`
+ `FullArtist`
+ `FullArtists`
+ `CursorPageFullArtists`
+ `AudioFeatures`
+ `AudioFeaturesPayload`
Expand Down Expand Up @@ -73,7 +72,6 @@ If we missed any change or there's something you'd like to discuss about this ve
+ `ResumePoint`
+ `FullTrack`
+ `TrackLink`
+ `FullTracks`
+ `SimplifiedTrack`
+ `TrackRestriction`
+ `SavedTrack`
Expand Down Expand Up @@ -159,6 +157,28 @@ If we missed any change or there's something you'd like to discuss about this ve
+ Change `{FullArtist, FullPlaylist, PublicUser, PrivateUser}::followers` from `HashMap<String, Option<Value>>` to struct `Followers`
+ Replace `Actions::disallows` with a `Vec<DisallowKey>` by removing all entires whose value is false, which will result in a simpler API
+ Replace `{FullAlbum, SimplifiedEpisode, FullEpisode}::release_date_precision` from `String` to `DatePrecision` enum, makes it easier to use.
- ([#157](https://github.com/ramsayleung/rspotify/pull/157))Keep polishing models to make it easier to use:
+ Constrain visibility of `FullArtists` struct with `pub (in crate)`, make `artists` and `artist_related_artists` endpoints return a `Vec<FullArtist>` instead.
+ Constrain visibility of `FullTracks` struct with `pub (in crate)`, make `tracks` and `artist_top_tracks` endpoints return a `Vec<FullTrack>` instead.
+ Constrain visibility of `AudioFeaturesPayload` struct with `pub (in crate)`, make `tracks_features` endpoints return a `Vec<AudioFeatures>` instead.
+ Constrain visibility of `FullAlbums` struct with `pub (in crate)`, make `albums` endpoints return a `Vec<FullAlbum>` instead.
+ Constrain visibility of `PageSimpliedAlbums` struct with `pub (in crate)`, make `new_releases` endpoints return a `Page<SimplifiedAlbum>` instead.
+ Constrain visibility of `CursorPageFullArtists` struct with `pub (in crate)`, make `current_user_followed_artists` endpoints return a `CursorBasedPage<FullArtist>` instead.
+ Constrain visibility of `PageCategory` struct with `pub (in crate)`, make `categories` endpoints return a `Page<Category>` instead.
+ Constrain visibility of `DevicePayload` struct with `pub (in crate)`, make `device` endpoints return a `Vec<Device>` instead.
+ Constrain visibility of `SeversalSimplifiedShows` struct with `pub (in crate)`, make `get_several_shows` endpoints return a `Vec<SimplifiedShow>` instead.
+ Rename `AudioFeatures.duration_ms` to `duration`, and change its type from `u32` to `std::time::Duration`.
+ Rename `FullEpisode.duration_ms` to `duration`, and change its type from `u32` to `std::time::Duration`.
+ Rename `SimplifiedEpisode.duration_ms` to `duration`, and change its type from `u32` to `std::time::Duration`.
+ Rename `FullTrack.duration_ms` to `duration`, and change its type from `u32` to `std::time::Duration`.
+ Rename `SimplifiedTrack.duration_ms` to `duration`, and change its type from `u32` to `std::time::Duration`.
+ Rename `ResumePoint.resume_position_ms` to `resume_position`, and change its type from `u32` to `std::time::Duration`.
+ Rename `CurrentlyPlayingContext.progress_ms` to `progress`, and change its type from `Option<u32>` to `Option<std::time::Duration>`.
+ Rename `CurrentPlaybackContext.progress_ms` to `progress`, and change its type from `Option<u32>` to `Option<std::time::Duration>`.
+ Change `CurrentlyPlayingContext.timestamp`'s type from `u64` to `chrono::DateTime<Utc>`.
+ Change `CurrentPlaybackContext.timestamp`'s type from `u64` to `chrono::DateTime<Utc>`.
+ Change `Offset.position`'s type from `Option<u32>` to `Option<std::time::Duration>`
+ Remove `SimplifiedPlayingContext`, since it's useless.

## 0.10 (2020/07/01)

Expand Down
2 changes: 1 addition & 1 deletion examples/with_refresh_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async fn do_things(spotify: Spotify) {
.expect("couldn't get user followed artists");
println!(
"User currently follows at least {} artists.",
followed.artists.items.len()
followed.items.len()
);

spotify
Expand Down
53 changes: 31 additions & 22 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl Spotify {
&self,
track_ids: impl IntoIterator<Item = &'a str>,
market: Option<Country>,
) -> ClientResult<FullTracks> {
) -> ClientResult<Vec<FullTrack>> {
// TODO: this can be improved
let mut ids: Vec<String> = vec![];
for track_id in track_ids {
Expand All @@ -234,7 +234,7 @@ impl Spotify {

let url = format!("tracks/?ids={}", ids.join(","));
let result = self.get(&url, None, &params).await?;
self.convert_result(&result)
self.convert_result::<FullTracks>(&result).map(|x| x.tracks)
}

/// Returns a single artist given the artist's ID, URI or URL.
Expand All @@ -261,14 +261,16 @@ impl Spotify {
pub async fn artists<'a>(
&self,
artist_ids: impl IntoIterator<Item = &'a str>,
) -> ClientResult<FullArtists> {
) -> ClientResult<Vec<FullArtist>> {
let mut ids: Vec<String> = vec![];
for artist_id in artist_ids {
ids.push(self.get_id(Type::Artist, artist_id));
}
let url = format!("artists/?ids={}", ids.join(","));
let result = self.get(&url, None, &Query::new()).await?;
self.convert_result(&result)

self.convert_result::<FullArtists>(&result)
.map(|x| x.artists)
}

/// Get Spotify catalog information about an artist's albums.
Expand Down Expand Up @@ -322,7 +324,7 @@ impl Spotify {
&self,
artist_id: &str,
country: T,
) -> ClientResult<FullTracks> {
) -> ClientResult<Vec<FullTrack>> {
let mut params = Query::with_capacity(1);
params.insert(
"country".to_owned(),
Expand All @@ -332,7 +334,7 @@ impl Spotify {
let trid = self.get_id(Type::Artist, artist_id);
let url = format!("artists/{}/top-tracks", trid);
let result = self.get(&url, None, &params).await?;
self.convert_result(&result)
self.convert_result::<FullTracks>(&result).map(|x| x.tracks)
}

/// Get Spotify catalog information about artists similar to an identified
Expand All @@ -344,11 +346,12 @@ impl Spotify {
///
/// [Reference](https://developer.spotify.com/web-api/get-related-artists/)
#[maybe_async]
pub async fn artist_related_artists(&self, artist_id: &str) -> ClientResult<FullArtists> {
pub async fn artist_related_artists(&self, artist_id: &str) -> ClientResult<Vec<FullArtist>> {
let trid = self.get_id(Type::Artist, artist_id);
let url = format!("artists/{}/related-artists", trid);
let result = self.get(&url, None, &Query::new()).await?;
self.convert_result(&result)
self.convert_result::<FullArtists>(&result)
.map(|x| x.artists)
}

/// Returns a single album given the album's ID, URIs or URL.
Expand Down Expand Up @@ -376,14 +379,14 @@ impl Spotify {
pub async fn albums<'a>(
&self,
album_ids: impl IntoIterator<Item = &'a str>,
) -> ClientResult<FullAlbums> {
) -> ClientResult<Vec<FullAlbum>> {
let mut ids: Vec<String> = vec![];
for album_id in album_ids {
ids.push(self.get_id(Type::Album, album_id));
}
let url = format!("albums/?ids={}", ids.join(","));
let result = self.get(&url, None, &Query::new()).await?;
self.convert_result(&result)
self.convert_result::<FullAlbums>(&result).map(|x| x.albums)
}

/// Search for an Item. Get Spotify catalog information about artists,
Expand Down Expand Up @@ -1018,7 +1021,7 @@ impl Spotify {
&self,
limit: L,
after: Option<String>,
) -> ClientResult<CursorPageFullArtists> {
) -> ClientResult<CursorBasedPage<FullArtist>> {
let mut params = Query::with_capacity(2);
params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string());
params.insert("type".to_owned(), Type::Artist.to_string());
Expand All @@ -1027,7 +1030,8 @@ impl Spotify {
}

let result = self.get("me/following", None, &params).await?;
self.convert_result(&result)
self.convert_result::<CursorPageFullArtists>(&result)
.map(|x| x.artists)
}

/// Remove one or more tracks from the current user's "Your Music" library.
Expand Down Expand Up @@ -1397,7 +1401,7 @@ impl Spotify {
country: Option<Country>,
limit: L,
offset: O,
) -> ClientResult<PageSimpliedAlbums> {
) -> ClientResult<Page<SimplifiedAlbum>> {
let mut params = Query::with_capacity(2);
params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string());
params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string());
Expand All @@ -1406,7 +1410,8 @@ impl Spotify {
}

let result = self.get("browse/new-releases", None, &params).await?;
self.convert_result(&result)
self.convert_result::<PageSimpliedAlbums>(&result)
.map(|x| x.albums)
}

/// Get a list of new album releases featured in Spotify
Expand All @@ -1428,7 +1433,7 @@ impl Spotify {
country: Option<Country>,
limit: L,
offset: O,
) -> ClientResult<PageCategory> {
) -> ClientResult<Page<Category>> {
let mut params = Query::with_capacity(2);
params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string());
params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string());
Expand All @@ -1439,7 +1444,8 @@ impl Spotify {
params.insert("country".to_owned(), country.to_string());
}
let result = self.get("browse/categories", None, &params).await?;
self.convert_result(&result)
self.convert_result::<PageCategory>(&result)
.map(|x| x.categories)
}

/// Get a list of playlists in a category in Spotify
Expand Down Expand Up @@ -1578,7 +1584,7 @@ impl Spotify {
pub async fn tracks_features<'a>(
&self,
tracks: impl IntoIterator<Item = &'a str>,
) -> ClientResult<Option<AudioFeaturesPayload>> {
) -> ClientResult<Option<Vec<AudioFeatures>>> {
let ids: Vec<String> = tracks
.into_iter()
.map(|track| self.get_id(Type::Track, track))
Expand All @@ -1589,7 +1595,8 @@ impl Spotify {
if result.is_empty() {
Ok(None)
} else {
self.convert_result(&result)
self.convert_result::<Option<AudioFeaturesPayload>>(&result)
.map(|option_payload| option_payload.map(|x| x.audio_features))
}
}

Expand All @@ -1611,9 +1618,10 @@ impl Spotify {
///
/// [Reference](https://developer.spotify.com/web-api/get-a-users-available-devices/)
#[maybe_async]
pub async fn device(&self) -> ClientResult<DevicePayload> {
pub async fn device(&self) -> ClientResult<Vec<Device>> {
let result = self.get("me/player/devices", None, &Query::new()).await?;
self.convert_result(&result)
self.convert_result::<DevicePayload>(&result)
.map(|x| x.devices)
}

/// Get Information About The User’s Current Playback
Expand Down Expand Up @@ -1981,7 +1989,7 @@ impl Spotify {
&self,
ids: impl IntoIterator<Item = &'a str>,
market: Option<Country>,
) -> ClientResult<SeversalSimplifiedShows> {
) -> ClientResult<Vec<SimplifiedShow>> {
// TODO: This can probably be better
let mut params = Query::with_capacity(1);
params.insert(
Expand All @@ -1992,7 +2000,8 @@ impl Spotify {
params.insert("country".to_owned(), market.to_string());
}
let result = self.get("shows", None, &params).await?;
self.convert_result(&result)
self.convert_result::<SeversalSimplifiedShows>(&result)
.map(|x| x.shows)
}

/// Get Spotify catalog information about an show’s episodes. Optional
Expand Down
10 changes: 4 additions & 6 deletions src/model/album.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,16 @@ pub struct FullAlbum {
/// Full Albums wrapped by Vec object
///
/// [Reference](https://developer.spotify.com/documentation/web-api/reference/albums/get-several-albums/)
// TODO: Reduce this wrapper object to `Vec<FullAlbum>`
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct FullAlbums {
#[derive(Deserialize)]
pub(in crate) struct FullAlbums {
pub albums: Vec<FullAlbum>,
}

/// Simplified Albums wrapped by Page object
///
/// [Reference](https://developer.spotify.com/web-api/get-list-new-releases/)
// TODO: Reduce this wrapper object to `Page<SimplifiedAlbum>`
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct PageSimpliedAlbums {
#[derive(Deserialize)]
pub(in crate) struct PageSimpliedAlbums {
pub albums: Page<SimplifiedAlbum>,
}

Expand Down
10 changes: 4 additions & 6 deletions src/model/artist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,15 @@ pub struct FullArtist {
/// Full artist object wrapped by `Vec`
///
/// [Reference](https://developer.spotify.com/documentation/web-api/reference/artists/get-several-artists/)
// TODO: Reduce this wrapper object to `Vec<FullArtist>`
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct FullArtists {
#[derive(Deserialize)]
pub(in crate) struct FullArtists {
pub artists: Vec<FullArtist>,
}

/// Full Artists vector wrapped by cursor-based-page object
///
/// [Reference](https://developer.spotify.com/documentation/web-api/reference/follow/get-followed/)
// TODO: Reduce this wrapper object to `CursorBasedPage<FullArtist>`
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct CursorPageFullArtists {
#[derive(Deserialize)]
pub(in crate) struct CursorPageFullArtists {
pub artists: CursorBasedPage<FullArtist>,
}
14 changes: 10 additions & 4 deletions src/model/audio.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! All objects related to artist defined by Spotify API
use crate::model::{from_duration_ms, to_duration_ms};
use serde::{Deserialize, Serialize};
use std::time::Duration;

/// Audio Feature Object
///
Expand All @@ -9,7 +11,12 @@ pub struct AudioFeatures {
pub acousticness: f32,
pub analysis_url: String,
pub danceability: f32,
pub duration_ms: u32,
#[serde(
deserialize_with = "from_duration_ms",
serialize_with = "to_duration_ms",
rename = "duration_ms"
)]
pub duration: Duration,
pub energy: f32,
pub id: String,
pub instrumentalness: f32,
Expand All @@ -30,9 +37,8 @@ pub struct AudioFeatures {
/// Audio feature object wrapped by `Vec`
///
/// [Reference](https://developer.spotify.com/documentation/web-api/reference/tracks/get-several-audio-features/)
// TODO: Reduce this wrapper object to `Vec<AudioFeatures>`
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct AudioFeaturesPayload {
#[derive(Deserialize)]
pub(in crate) struct AudioFeaturesPayload {
pub audio_features: Vec<AudioFeatures>,
}

Expand Down
5 changes: 2 additions & 3 deletions src/model/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ pub struct Category {
/// Categories wrapped by page object
///
/// [Reference](https://developer.spotify.com/web-api/get-list-categories/)
// TODO: Reduce this wrapper object to `Page<Category>`
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct PageCategory {
#[derive(Deserialize)]
pub(in crate) struct PageCategory {
pub categories: Page<Category>,
}
Loading

0 comments on commit b47bf6f

Please sign in to comment.