1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// #![warn(missing_docs)]
//! spotify-rs is a Rust wrapper for the Spotify API. It has full API coverage
//! and supports all the authorisation flows (except for the implicit grant flow).
//!
//! # Getting Started
//! First, you'll need to
//! [create an app](https://developer.spotify.com/documentation/web-api/tutorials/getting-started#create-an-app)
//! on Spotify's [developer dashboard](https://developer.spotify.com/dashboard).
//!
//! There you will need to set a redirect URL.
//! You'll need to get the client ID, and possibly the client secret and redirect URL,
//! depending on the authorisation flow you're going to use.
//!
//! There are two concepts: authenticating - that is, "logging the app in", using your
//! client ID and secret - and authorisation - which means having a user grant your app
//! access to their account.
//!
//! Depending on your chosen auth flow, there is either one step or two required to get you
//! up and running.
//!
//! # Authorisation
//! You will need to set your scopes, redirect the user to a URL returned by spotify-rs, which will
//! redirect them *again* to your app's *redirect URL*, which will contain a code that allows
//! your app to be authorised.
//!
//! spotify-rs supports 3 of the 4 OAuth2 authorisation flows the API makes available:
//! the authorisation code flow, authorisation code with PKCE flow and the client credentials flow.
//!
//! The [implicit grant flow](https://developer.spotify.com/documentation/web-api/tutorials/implicit-flow)
//! is not supported for 2 reasons:
//! - it returns the access token in the URL, which is insecure and leaves your app vulnerable to all kinds of attacks;
//! - it doesn't support refreshing the access token.
//!
//! The auth flow you should use depends on the use case:
//! - the authorisation code flow is recommended for long-running applications
//! where you can safely store the client secret (e.g. web and mobile apps)
//! - the authorisation code with PKCE flow is recommended for long-running applications
//! where you *can't* safely store the client secret (e.g. desktop apps and single page web apps)
//! - the client credentials flow doesn't include authorisation, thus letting you only access public information
//!
//! Below is an example for each auth flow:
//! ## Authorisation Code Flow
//! ```no_run
//! use spotify_rs::{AuthCodeClient, RedirectUrl};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Your application scopes
//! let scopes = vec![
//! "user-read-private",
//! "playlist-modify-public",
//! "playlist-modify-private",
//! "playlist-read-private",
//! "playlist-read-collaborative",
//! ];
//!
//! // This should match the redirect URL you set in your app's settings
//! // (on the Spotify API dashboard)
//! let redirect_uri = RedirectUrl::new("your_redirect_url".to_owned())?;;
//!
//! // Whether or not to automatically refresh the token when it expires.
//! let auto_refresh = true;
//!
//! // You will need to redirect the user to this URL.
//! let (client, url) = AuthCodeClient::new(
//! "client_id",
//! "client_secret",
//! scopes,
//! redirect_uri,
//! auto_refresh,
//! );
//!
//! // After the user was redirected to `url`, they will be redirected *again*, to
//! // your `redirect_uri`, with the "auth_code" and "csrf_state" parameters in the URL.
//! // You will need to get those parameters from the URL.
//!
//! // Finally, you will be able to authenticate the client.
//! let spotify = client.authenticate("auth_code", "csrf_state").await?;
//!
//! // Get an album with the specified ID.
//! let album = spotify_rs::album("album_id").get(&spotify).await?;
//! println!("The name of the album is: {}", album.name);
//!
//! // The `album` method returns a builder with optional parameters you can set
//! // For example, this sets the market to "GB".
//! let album_gb = spotify_rs::album("album_id")
//! .market("GB")
//! .get(&spotify)
//! .await?;
//! println!("The popularity of the album is {}", album_gb.popularity);
//!
//! // This gets 5 playlists of the user that authorised the app
//! // (it requires the playlist-read-private scope).
//! let user_playlists = spotify_rs::current_user_playlists()
//! .limit(5)
//! .get(&spotify)
//! .await?;
//! let result_count = user_playlists.items.len();
//! println!("The API returned {} playlists.", result_count);
//!
//! Ok(())
//! }
//! ```
//! The Authorisation Code Flow with PKCE is the same, except you would need to use
//! [`AuthCodePkceClient`] instead of [`AuthCodeClient`].
//!
//! A of available scopes can be found [here](https://developer.spotify.com/documentation/web-api/concepts/scopes).
//!
//! The auth code and CSRF token can be obtained by parsing the URL the user was
//! redirected to (the redirect URL, as set in the API dashboard and when creating the client).
//!
//! Please note that the redirect URL you pass to [`authenticate`] *must* match
//! the redirect URL you set in the Spotify API developer dashboard.
//!
//! That could be achieved by simply having the user copy and paste the URL into
//! your app, or, for example, by having a server listening at your `redirect_url`
//! and sending the auth code and CSRF token to the main app when the user is
//! redirected to said URL.
//!
//! For examples, check out the examples directory.
//!
//! ## Client Credentials Flow
//! ```no_run
//! use spotify_rs::{ClientCredsClient, RedirectUrl};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let spotify = ClientCredsClient::authenticate("client_id", "client_secret").await?;
//!
//! // Get an album with the specified ID.
//! let album = spotify_rs::album("album_id").get(&spotify).await?;
//! println!("The name of the album is: {}", album.name);
//!
//! // The `album` method returns a builder with optional parameters you can set
//! // For example, this sets the market to "GB".
//! let album_gb = spotify_rs::album("album_id")
//! .market("GB")
//! .get(&spotify)
//! .await?;
//! println!("The popularity of the album is {}", album_gb.popularity);
//!
//! Ok(())
//! }
//! ```
//! This flow doesn't require anything besides the client credentials,
//! but you cannot access any user information.
//!
//! # Automatic Token Refreshing
//! If `auto_refresh` is set to `true` when creating the client, on every request
//! the client will check if the token is about to expire. If the token is close
//! to expiring, it will refresh the token for you.
//!
//! *Note: this means that if the token has expired, the `RwLock` holding the [`Token`]*
//! *will be acquired in order to change the token.*
//!
//! If you disable this feature, you'll have to refresh the token yourself using [`request_refresh_token`].
//!
//! [`Token`]: auth::Token
//! [`AuthCodeFlow`]: auth::AuthCodeFlow
//! [`AuthCodePkceFlow`]: auth::AuthCodePkceFlow
//! [`request_refresh_token`]: client::Client::request_refresh_token()
//! [`authenticate`]: client::Client::authenticate()
/// Struct and methods for constructing and authenticating [`Clients`](crate::client::Client).
/// Functions and builders for all the Spotify endpoints.
/// Mappings of objects received from the Spotify API.
use Body;
use ;
pub use ;
pub use ;
pub use ;
pub use RedirectUrl;
pub use ;
// Function meant to create a URL query list from &[T].
pub
// Function meant to create a request body list from &[T].
pub
/// Represents an empty API response.
;
// Used to deserialize an empty API response.
// This is also necessary for when Spotify API endpoints that should
// normally return empty responses, instead return (useless) non-JSON responses.