Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce core dependencies #110

Merged
merged 25 commits into from
Aug 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
22e9ec8
Replace rand with getrandom.
Aug 14, 2020
c98a577
replacing rand with getrandom to reduce binary size and compilation t…
ramsayleung Aug 14, 2020
88c97ba
Merge branch 'reduce-core-dependencies' of github.com:samrayleung/rsp…
ramsayleung Aug 14, 2020
08ded2b
Merge branch 'master' into reduce-core-dependencies
ramsayleung Aug 15, 2020
d36adb0
Change alphanum from global variable to a local variable, update desc…
ramsayleung Aug 15, 2020
f6caa06
Change rand dependency into getrandom
marioortizmanero Aug 15, 2020
09ee436
Moved static variable inside function
marioortizmanero Aug 15, 2020
be15092
Optional webbrowser feature
marioortizmanero Aug 15, 2020
2841d99
Optional dotenv feature
marioortizmanero Aug 15, 2020
6d6cbdf
Initial documentation work
marioortizmanero Aug 15, 2020
6b81aca
Merge branch 'reduce-core-dependencies' of github.com:samrayleung/rsp…
ramsayleung Aug 16, 2020
c8cc068
Merge branch 'master' of https://github.com/ramsayleung/rspotify into…
marioortizmanero Aug 16, 2020
cfd4aa6
Merge with master, clean up docs
marioortizmanero Aug 27, 2020
392a751
Documentation polishing
marioortizmanero Aug 27, 2020
918db60
Update changelog
marioortizmanero Aug 27, 2020
0cb81ae
Documentation for the blocking module on release
marioortizmanero Aug 27, 2020
dc43420
Improved changelog wording
marioortizmanero Aug 27, 2020
dd60983
Unnecessary return
marioortizmanero Aug 27, 2020
9ee378b
Use env-file feature for tests
marioortizmanero Aug 27, 2020
087aaf1
Fix 'user_playlist_remove_specific_occurrenes_of_tracks' typo
marioortizmanero Aug 27, 2020
e7d7828
Note typo in the changelog as well
marioortizmanero Aug 27, 2020
a818b0c
Fix cargo check and test
marioortizmanero Aug 27, 2020
7a376f1
Include env-file dependency for examples
marioortizmanero Aug 27, 2020
ad0eece
Revert Vec::new() change
marioortizmanero Aug 27, 2020
170c279
Fix webapp 'rspotify' dependency and upper imports
marioortizmanero Aug 27, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --features env-file

lints:
name: Lints
Expand Down
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
## 0.11 (unreleased)

- Rewritten documentation in hopes that it's easier to get started with Rspotify.
- Reduced the number of examples. Instead of having an example for each endpoint, which is repetitive and unhelpful for newcomers, some real-life examples are now included. If you'd like to add your own example, please do!
- Add `add_item_to_queue` endpoint.
- Fix typo in `transfer_playback`: `device_id` to `device_ids`.
- Fix race condition when using a single client from multiple threads (see [#114](https://github.com/ramsayleung/rspotify/pull/114) for more information).
- Rspotify should now be considerably lighter and less bloated:
+ Remove unused dependencies: `base64`, `env_logger`, `derive_builder`, `random`, `url`. <!-- NOTE: derive_builder might not be removed after all -->
+ Remove `itertools` dependency by using the standard library.
+ Remove `rand` in place of `getrandom` to [reduce total dependencies and compile times](https://github.com/ramsayleung/rspotify/issues/108#issuecomment-673587185).
+ `webbrowser` and access to functions that use it (`util::get_token`, `util::get_token_without_cache` and `util::request_token`) can be disabled for the non-CLI applications with the `browser` feature. It's still enabled by default due to [its frequent usage](https://github.com/ramsayleung/rspotify/pull/110#issuecomment-674410604).
+ Reduced repetitive code and boilerplate internally in several places.
- Updated dependencies to the latest versions, integrated Dependabot to keep track of them.

**Breaking changes:**
- `dotenv` support is now optional. You can enable it with the `env-file` feature to have the same behavior as before.
- Fix typo in `user_playlist_remove_specific_occurrenes_of_tracks`, now it's `user_playlist_remove_specific_occurrences_of_tracks`.

## 0.10 (2020/07/01)

- Add `get_access_token_without_cache` and `refresh_access_token_without_cache` to get and refresh access token without caching it.
Expand Down Expand Up @@ -39,7 +58,7 @@
- Code optimize, remove a unnecessary mut and add a missing reference
- Fix reqwest breaking change
- Add missing devices type
- Add `position_ms` to `start_playback
- Add `position_ms` to `start_playback`

## 0.6 (2019/07/22)

Expand Down
55 changes: 43 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,34 @@ name = "rspotify"
version = "0.10.0"
license = "MIT"
readme = "README.md"
description="Spotify API wrapper"
homepage="https://github.com/samrayleung/rspotify"
repository="https://github.com/samrayleung/rspotify"
keywords=["spotify","api"]
description = "Spotify API wrapper"
homepage = "https://github.com/ramsayleung/rspotify"
repository = "https://github.com/ramsayleung/rspotify"
keywords = ["spotify","api"]
edition = "2018"

[dependencies]
chrono = { version = "0.4.13", features = ["serde", "rustc-serialize"] }
dotenv = "0.15.0"
dotenv = { version = "0.15.0", optional = true }
failure = "0.1.8"
lazy_static = "1.4.0"
log = "0.4.11"
percent-encoding = "2.1.0"
rand = "0.7.3"
getrandom = "0.1.14"
reqwest = { version = "0.10.7", features = ["json", "socks"], default-features = false }
serde = { version = "1.0.115", features = ["derive"] }
serde_json = "1.0.57"
webbrowser = "0.5.5"
webbrowser = { version = "0.5.5", optional = true }

[dev-dependencies]
async_once = { version = "0.1.0", features = ["tokio"] }
tokio = { version = "0.2.22", features = ["full"] }
futures = "0.3.5"

[features]
default = ["reqwest/default-tls"]
default = ["reqwest/default-tls", "browser"]
env-file = ["dotenv"]
browser = ["webbrowser"]
blocking = ["reqwest/default-tls", "reqwest/blocking"]
# Passing the TLS features to reqwest.
native-tls = ["reqwest/native-tls"]
Expand All @@ -39,22 +41,51 @@ native-tls-vendored-blocking = ["reqwest/native-tls-vendored", "reqwest/blocking
rustls-tls = ["reqwest/rustls-tls"]
rustls-tls-blocking = ["reqwest/rustls-tls", "reqwest/blocking"]

[package.metadata.docs.rs]
# Also documenting the blocking module
features = ["blocking"]

[[example]]
name = "album"
required-features = ["env-file"]
path = "examples/album.rs"

[[example]]
name = "current_user_recently_played"
required-features = ["env-file"]
path = "examples/current_user_recently_played.rs"

[[example]]
name = "track"
required-features = ["env-file"]
path = "examples/track.rs"

[[example]]
name = "tracks"
required-features = ["env-file"]
path = "examples/tracks.rs"

[[example]]
name = "with_refresh_token"
required-features = ["env-file"]
path = "examples/with_refresh_token.rs"

[[example]]
name = "device"
required-features = ["blocking"]
required-features = ["env-file", "blocking"]
path = "examples/blocking/device.rs"

[[example]]
name = "me"
required-features = ["blocking"]
required-features = ["env-file", "blocking"]
path = "examples/blocking/me.rs"

[[example]]
name = "blocking_search"
required-features = ["blocking"]
required-features = ["env-file", "blocking"]
path = "examples/blocking/search.rs"

[[example]]
name = "seek_track"
required-features = ["blocking"]
required-features = ["env-file", "blocking"]
path = "examples/blocking/seek_track.rs"
6 changes: 2 additions & 4 deletions examples/webapp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ version = "0.1.0"
authors = ["Ramsay <ramsayleung@gmail.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rocket = "0.4.5"
rocket_contrib = {version = "0.4.5", features= ["tera_templates"]}
rspotify = {version = "0.10.0", features = ["blocking"]}
rocket_contrib = { version = "0.4.5", features = ["tera_templates"] }
rspotify = { path = "../..", features = ["blocking"] }
23 changes: 11 additions & 12 deletions examples/webapp/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
//! In this example, the token is saved into a cache file. If you are building a real-world web
//! app, it's easy to save token into database, by calling the function
//! `util::get_token_without_cache()`, instead of `util::get_token()`, which saves token by
//! default.

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate rocket;

use rocket::http::Cookie;
use rocket::http::Cookies;
use rocket::http::{Cookie, Cookies};
use rocket::response::Redirect;
use rocket_contrib::json;
use rocket_contrib::json::JsonValue;
use rocket_contrib::templates::Template;
use rspotify::blocking::client::Spotify;
use std::fs;
use std::path::Path;
use std::path::PathBuf;

use rspotify::blocking::oauth2::SpotifyClientCredentials;
use rspotify::blocking::oauth2::SpotifyOAuth;
use rspotify::blocking::oauth2::{SpotifyClientCredentials, SpotifyOAuth};
use rspotify::blocking::util;
use std::env;

use std::env;
use std::collections::HashMap;
/// In this example, the token is saved into a cache file. If you are building a real-world web
/// app, it's easy to save token into database, by calling the function
/// `util::get_token_without_cache()`, instead of `util::get_token()`, which saves token by
/// default.
use std::fs;
use std::path::{Path, PathBuf};

#[derive(Debug, Responder)]
pub enum AppResponse {
Expand Down
3 changes: 0 additions & 3 deletions examples/with_refresh_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
//! tokens](https://github.com/felix-hilden/tekore/issues/86),
//! so in the case of Spotify it doesn't seem to revoke them at all.

use dotenv::dotenv;

use rspotify::client::Spotify;
use rspotify::oauth2::{SpotifyClientCredentials, SpotifyOAuth};
use rspotify::util::get_token_without_cache;
Expand Down Expand Up @@ -81,7 +79,6 @@ async fn do_things(spotify: Spotify) {
#[tokio::main]
async fn main() {
// The default credentials from the `.env` file will be used by default.
dotenv().ok();
let mut oauth = SpotifyOAuth::default()
.scope("user-follow-read user-follow-modify")
.build();
Expand Down
41 changes: 31 additions & 10 deletions src/blocking/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,16 +823,37 @@ impl Spotify {
self.convert_result::<CUDResult>(&result)
}

/// [remove tracks playlist](https://developer.spotify.com/web-api/remove-tracks-playlist/)
/// Removes all occurrences of the given tracks from the given playlist
/// Parameters:
/// - user_id - the id of the user
/// - playlist_id - the id of the playlist
/// - tracks - an array of map containing Spotify URIs of the tracks
/// to remove with their current positions in the playlist. For example:
/// { "tracks": [{ "uri": "spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "positions": [0,3] },{
/// "uri": "spotify:track:1301WleyT98MSxVHPZCA6M", "positions": [7] }] }
/// - snapshot_id - optional id of the playlist snapshot
/// [remove tracks playlist
/// ](https://developer.spotify.com/web-api/remove-tracks-playlist/).
///
/// Removes specfic occurrences of the given tracks from the given
/// playlist. Parameters:
///
/// - user_id: the id of the user
/// - playlist_id: the id of the playlist
/// - tracks: an array of map containing Spotify URIs of the tracks to remove
/// with their current positions in the playlist. For example:
///
/// ```json
/// {
/// "tracks":[
/// {
/// "uri":"spotify:track:4iV5W9uYEdYUVa79Axb7Rh",
/// "positions":[
/// 0,
/// 3
/// ]
/// },
/// {
/// "uri":"spotify:track:1301WleyT98MSxVHPZCA6M",
/// "positions":[
/// 7
/// ]
/// }
/// ]
/// }
/// ```
/// - snapshot_id: optional id of the playlist snapshot
pub fn user_playlist_remove_specific_occurrenes_of_tracks(
&self,
user_id: &str,
Expand Down
11 changes: 8 additions & 3 deletions src/blocking/oauth2.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! The module contains function about authorization and client-credential
// use 3rd party library
use chrono::prelude::*;
use dotenv::dotenv;
use log::{debug, error, trace};
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
use reqwest::blocking::Client;
Expand Down Expand Up @@ -98,7 +97,10 @@ impl TokenInfo {
impl SpotifyClientCredentials {
/// Build default SpotifyClientCredentials
pub fn default() -> SpotifyClientCredentials {
dotenv().ok();
#[cfg(feature = "env-file")]
{
dotenv::dotenv().ok();
}
let client_id = env::var("CLIENT_ID").unwrap_or_default();
let client_secret = env::var("CLIENT_SECRET").unwrap_or_default();
trace!(
Expand Down Expand Up @@ -207,7 +209,10 @@ impl SpotifyOAuth {
// }

pub fn default() -> SpotifyOAuth {
dotenv().ok();
#[cfg(feature = "env-file")]
{
dotenv::dotenv().ok();
}
let client_id = env::var("CLIENT_ID").unwrap_or_default();
let client_secret = env::var("CLIENT_SECRET").unwrap_or_default();
let redirect_uri = env::var("REDIRECT_URI").unwrap_or_default();
Expand Down
21 changes: 14 additions & 7 deletions src/blocking/util.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
//! Utils function
use chrono::prelude::*;
use rand::distributions::Alphanumeric;
use rand::{self, Rng};
use webbrowser;
use getrandom::getrandom;

use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::io;
use std::string::ToString;

use super::oauth2::{SpotifyOAuth, TokenInfo};
Expand All @@ -19,9 +16,14 @@ pub fn datetime_to_timestamp(elapsed: u32) -> i64 {
}
/// Generate `length` random chars
pub fn generate_random_string(length: usize) -> String {
rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(length)
let alphanum: &[u8] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".as_bytes();
let mut buf = vec![0u8; length];
getrandom(&mut buf).unwrap();
let range = alphanum.len();

buf.iter()
.map(|byte| alphanum[*byte as usize % range] as char)
.collect()
}

Expand Down Expand Up @@ -71,6 +73,7 @@ pub fn convert_str_to_map(query_str: &mut str) -> HashMap<&str, &str> {
map
}

#[cfg(feature = "browser")]
pub fn request_token(spotify_oauth: &mut SpotifyOAuth) {
let state = generate_random_string(16);
let auth_url = spotify_oauth.get_authorize_url(Some(&state), None);
Expand Down Expand Up @@ -98,7 +101,9 @@ pub fn process_token_without_cache(
}

/// Get tokenInfo by Authorization
#[cfg(feature = "browser")]
pub fn get_token(spotify_oauth: &mut SpotifyOAuth) -> Option<TokenInfo> {
use std::io;
match spotify_oauth.get_cached_token() {
Some(token_info) => Some(token_info),
None => {
Expand All @@ -114,7 +119,9 @@ pub fn get_token(spotify_oauth: &mut SpotifyOAuth) -> Option<TokenInfo> {
}

/// Get tokenInfo by Authorization without cache.
#[cfg(feature = "browser")]
pub fn get_token_without_cache(spotify_oauth: &mut SpotifyOAuth) -> Option<TokenInfo> {
use std::io;
request_token(spotify_oauth);
println!("Enter the URL you were redirected to: ");
let mut input = String::new();
Expand Down
34 changes: 26 additions & 8 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,14 +808,32 @@ impl Spotify {
/// [remove tracks playlist](https://developer.spotify.com/web-api/remove-tracks-playlist/)
/// Removes specfic occurrences of the given tracks from the given playlist
/// Parameters:
/// - user_id - the id of the user
/// - playlist_id - the id of the playlist
/// - tracks - an array of map containing Spotify URIs of the tracks
/// to remove with their current positions in the playlist. For example:
/// { "tracks": [{ "uri": "spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "positions": [0,3] },{
/// "uri": "spotify:track:1301WleyT98MSxVHPZCA6M", "positions": [7] }] }
/// - snapshot_id - optional id of the playlist snapshot
pub async fn user_playlist_remove_specific_occurrenes_of_tracks(
/// - user_id: the id of the user
/// - playlist_id: the id of the playlist
/// - tracks: an array of map containing Spotify URIs of the tracks to remove
/// with their current positions in the playlist. For example:
///
/// ```json
/// {
/// "tracks":[
/// {
/// "uri":"spotify:track:4iV5W9uYEdYUVa79Axb7Rh",
/// "positions":[
/// 0,
/// 3
/// ]
/// },
/// {
/// "uri":"spotify:track:1301WleyT98MSxVHPZCA6M",
/// "positions":[
/// 7
/// ]
/// }
/// ]
/// }
/// ```
/// - snapshot_id: optional id of the playlist snapshot
pub async fn user_playlist_remove_specific_occurrences_of_tracks(
&self,
user_id: &str,
playlist_id: &str,
Expand Down
Loading