From 77c175e1bfa81d0f91cbba3cd000c6b98d7bbd2d Mon Sep 17 00:00:00 2001 From: TroyHernandez Date: Sat, 6 Jun 2026 22:15:36 -0500 Subject: [PATCH 1/5] Migrate auth + tracks.R to tinyoauth (pattern proof) - authenticate.R: client-credentials + user flow via tinyoauth, with oauth_import_httr() carrying over an existing .httr-oauth (no re-login) - tracks.R: endpoints use tinyoauth::oauth_request (no httr RETRY/content) - DESCRIPTION: Imports tinyoauth + Remotes; Depends R (>= 4.0); httr/jsonlite kept until the remaining endpoint files are migrated - Verified live: get_spotify_access_token() + get_track() --- DESCRIPTION | 6 +- R/authenticate.R | 80 +++++++++++++++------------ R/tracks.R | 60 ++++---------------- man/dot-spotify_client.Rd | 20 +++++++ man/get_spotify_access_token.Rd | 8 +-- man/get_spotify_authorization_code.Rd | 12 ++-- 6 files changed, 91 insertions(+), 95 deletions(-) create mode 100644 man/dot-spotify_client.Rd diff --git a/DESCRIPTION b/DESCRIPTION index ba4bebb..009f82f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,10 +5,12 @@ Date: 2026-06-06 Authors@R: c(person("Troy", "Hernandez", email = "troy@cornball.ai", role = c("aut", "cre", "cph"), comment = c(ORCID = "0009-0005-4248-604X")), person("Charlie", "Thompson", email = "chuck@rcharlie.com", role = c("aut", "cph")), person("Josiah", "Parry", email = "josiah.parry@yahoo.com", role = "aut"), person("Donal", "Phipps", email = "donal.phipps@gmail.com", role = "aut"), person("Tom", "Wolff", email = "tom.wolff@duke.edu", role = "aut")) Description: An R wrapper for the 'Spotify' Web API . -Depends: R (>= 3.2) +Depends: R (>= 4.0) Imports: httr, - jsonlite + jsonlite, + tinyoauth +Remotes: cornball-ai/tinyoauth License: MIT + file LICENSE Encoding: UTF-8 LazyData: true diff --git a/R/authenticate.R b/R/authenticate.R index 4573f95..ce9a3a2 100644 --- a/R/authenticate.R +++ b/R/authenticate.R @@ -1,54 +1,64 @@ +# authenticate.R +# Spotify OAuth via tinyoauth. Client-credentials and user (authorization-code) +# tokens, with a back-compat path that carries over an existing httr .httr-oauth +# cache so prior authorizations keep working without a fresh login. + +#' Spotify OAuth client +#' @param client_id Spotify client id (default env SPOTIFY_CLIENT_ID). +#' @param client_secret Spotify client secret (default env SPOTIFY_CLIENT_SECRET). +#' @return A tinyoauth client. +#' @keywords internal +.spotify_client <- function(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), + client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET")) { + tinyoauth::oauth_client( + id = client_id, secret = client_secret, + token_url = "https://accounts.spotify.com/api/token", + auth_url = "https://accounts.spotify.com/authorize") +} + #' Get Spotify Access Token #' -#' This function creates a Spotify access token. -#' @param client_id Defaults to System Environment variable "SPOTIFY_CLIENT_ID" -#' @param client_secret Defaults to System Environment variable "SPOTIFY_CLIENT_SECRET" +#' Creates a Spotify access token via the client-credentials grant (app-only). +#' @param client_id Defaults to system environment variable "SPOTIFY_CLIENT_ID" +#' @param client_secret Defaults to system environment variable "SPOTIFY_CLIENT_SECRET" #' @keywords auth -#' @return -#' Returns an environment with access token data. +#' @return An access token string. #' @export #' @examples #' \dontrun{ #' get_spotify_access_token() #' } - -get_spotify_access_token <- function(client_id = Sys.getenv('SPOTIFY_CLIENT_ID'), client_secret = Sys.getenv('SPOTIFY_CLIENT_SECRET')) { - - post0 <- RETRY('POST', 'https://accounts.spotify.com/api/token', - accept_json(), httr::authenticate(client_id, client_secret), - body = list(grant_type = 'client_credentials'), - encode = 'form', httr::config(http_version = 2)) - - post <- httr::content(post0) - - if (!is.null(post$error)) { - stop(paste0("Could not authenticate with given Spotify credentials:\n\t", - post$error_description)) - } - - access_token <- post$access_token - - return(access_token) +get_spotify_access_token <- function(client_id = Sys.getenv('SPOTIFY_CLIENT_ID'), + client_secret = Sys.getenv('SPOTIFY_CLIENT_SECRET')) { + tok <- tinyoauth::oauth_token_client(.spotify_client(client_id, client_secret)) + tok$access_token } #' Get Spotify authorization Code #' -#' This function creates a Spotify access token. -#' @param client_id Defaults to System Envioronment variable "SPOTIFY_CLIENT_ID" -#' @param client_secret Defaults to System Envioronment variable "SPOTIFY_CLIENT_SECRET" -#' @param scope Space delimited string of spotify scopes, found here: https://developer.spotify.com/documentation/general/guides/scopes/. All scopes are selected by default +#' Obtains a user-authorized token via the authorization-code grant, with +#' caching and refresh. If a legacy httr \code{.httr-oauth} file is present, its +#' authorization is carried over (refreshed) so no new browser login is needed. +#' @param client_id Defaults to system environment variable "SPOTIFY_CLIENT_ID" +#' @param client_secret Defaults to system environment variable "SPOTIFY_CLIENT_SECRET" +#' @param scope Spotify scopes; all are requested by default. #' @keywords auth -#' @return -#' Returns an environment with access token data. +#' @return A tinyoauth token (carries the access and refresh tokens). #' @export #' @examples #' \dontrun{ #' get_spotify_authorization_code() #' } - -get_spotify_authorization_code <- function(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET"), scope = tinyspotifyr::scopes) { - endpoint <- httr::oauth_endpoint(authorize = 'https://accounts.spotify.com/authorize', - access = 'https://accounts.spotify.com/api/token') - app <- httr::oauth_app('spotifyr', client_id, client_secret) - httr::oauth2.0_token(endpoint = endpoint, app = app, scope = scope) +get_spotify_authorization_code <- function(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), + client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET"), + scope = tinyspotifyr::scopes) { + client <- .spotify_client(client_id, client_secret) + legacy <- ".httr-oauth" + if (file.exists(legacy)) { + imp <- tryCatch(tinyoauth::oauth_import_httr(legacy), error = function(e) NULL) + if (!is.null(imp)) { + return(tinyoauth::oauth_refresh(imp$client, imp$token)) + } + } + tinyoauth::oauth_token(client, scope = paste(scope, collapse = " ")) } diff --git a/R/tracks.R b/R/tracks.R index e7641b6..edea81d 100644 --- a/R/tracks.R +++ b/R/tracks.R @@ -7,19 +7,9 @@ #' @export get_track_audio_analysis <- function(id, authorization = get_spotify_access_token()) { - base_url <- 'https://api.spotify.com/v1/audio-analysis' - - params <- list( - access_token = authorization - ) url <- paste0(base_url, "/", id) - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) - - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - - return(res) + tinyoauth::oauth_request(authorization, url, "GET", flatten = TRUE) } #' Get audio feature information for a single track identified by its unique Spotify ID. @@ -39,16 +29,10 @@ get_track_audio_features <- function(ids, authorization = get_spotify_access_tok "returns data for apps without prior access.")) stopifnot(length(ids) <= 100) base_url <- 'https://api.spotify.com/v1/audio-features' - params <- list( - access_token = authorization, - ids = paste0(ids, collapse = ',') - ) - res <- RETRY('GET', base_url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - res <- res$audio_features - - return(res) + params <- list(ids = paste0(ids, collapse = ',')) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) + res$audio_features } #' Get Spotify catalog information for a single track identified by its unique Spotify ID. @@ -62,26 +46,15 @@ get_track_audio_features <- function(ids, authorization = get_spotify_access_tok #' @export get_track <- function(id, market = NULL, authorization = get_spotify_access_token()) { - base_url <- 'https://api.spotify.com/v1/tracks' - if (!is.null(market)) { if (!grepl('^[[:alpha:]]{2}$', market)) { stop('"market" must be an ISO 3166-1 alpha-2 country code') } } - - params <- list( - market = market, - access_token = authorization - ) url <- paste0(base_url, "/", id) - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) - - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - - return(res) + tinyoauth::oauth_request(authorization, url, "GET", + query = list(market = market), flatten = TRUE) } #' Get Spotify catalog information for a single track identified by its unique Spotify ID. @@ -96,28 +69,17 @@ get_track <- function(id, market = NULL, authorization = get_spotify_access_toke #' @export get_tracks <- function(ids, market = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - base_url <- 'https://api.spotify.com/v1/tracks' - if (!is.null(market)) { if (!grepl('^[[:alpha:]]{2}$', market)) { stop('"market" must be an ISO 3166-1 alpha-2 country code') } } - - params <- list( - ids = paste(ids, collapse = ','), - market = market, - access_token = authorization - ) - res <- RETRY('GET', base_url, query = params, encode = 'json') - stop_for_status(res) - - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - + params <- list(ids = paste(ids, collapse = ','), market = market) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$tracks } - - return(res) + res } diff --git a/man/dot-spotify_client.Rd b/man/dot-spotify_client.Rd new file mode 100644 index 0000000..a930662 --- /dev/null +++ b/man/dot-spotify_client.Rd @@ -0,0 +1,20 @@ +% tinyrox says don't edit this manually, but it can't stop you! +\name{.spotify_client} +\alias{.spotify_client} +\title{Spotify OAuth client} +\usage{ +.spotify_client(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), + client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET")) +} +\arguments{ +\item{client_id}{Spotify client id (default env SPOTIFY_CLIENT_ID).} + +\item{client_secret}{Spotify client secret (default env SPOTIFY_CLIENT_SECRET).} +} +\value{ +A tinyoauth client. +} +\description{ +Spotify OAuth client +} +\keyword{internal} diff --git a/man/get_spotify_access_token.Rd b/man/get_spotify_access_token.Rd index 5010208..d81acc0 100644 --- a/man/get_spotify_access_token.Rd +++ b/man/get_spotify_access_token.Rd @@ -7,15 +7,15 @@ get_spotify_access_token(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET")) } \arguments{ -\item{client_id}{Defaults to System Environment variable "SPOTIFY_CLIENT_ID"} +\item{client_id}{Defaults to system environment variable "SPOTIFY_CLIENT_ID"} -\item{client_secret}{Defaults to System Environment variable "SPOTIFY_CLIENT_SECRET"} +\item{client_secret}{Defaults to system environment variable "SPOTIFY_CLIENT_SECRET"} } \value{ -Returns an environment with access token data. +An access token string. } \description{ -This function creates a Spotify access token. +Creates a Spotify access token via the client-credentials grant (app-only). } \examples{ \dontrun{ diff --git a/man/get_spotify_authorization_code.Rd b/man/get_spotify_authorization_code.Rd index 0733b81..1eaf223 100644 --- a/man/get_spotify_authorization_code.Rd +++ b/man/get_spotify_authorization_code.Rd @@ -8,17 +8,19 @@ get_spotify_authorization_code(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), scope = tinyspotifyr::scopes) } \arguments{ -\item{client_id}{Defaults to System Envioronment variable "SPOTIFY_CLIENT_ID"} +\item{client_id}{Defaults to system environment variable "SPOTIFY_CLIENT_ID"} -\item{client_secret}{Defaults to System Envioronment variable "SPOTIFY_CLIENT_SECRET"} +\item{client_secret}{Defaults to system environment variable "SPOTIFY_CLIENT_SECRET"} -\item{scope}{Space delimited string of spotify scopes, found here: https://developer.spotify.com/documentation/general/guides/scopes/. All scopes are selected by default} +\item{scope}{Spotify scopes; all are requested by default.} } \value{ -Returns an environment with access token data. +A tinyoauth token (carries the access and refresh tokens). } \description{ -This function creates a Spotify access token. +Obtains a user-authorized token via the authorization-code grant, with +caching and refresh. If a legacy httr \code{.httr-oauth} file is present, its +authorization is carried over (refreshed) so no new browser login is needed. } \examples{ \dontrun{ From ee4b48aa9cadf2696401f31fe8eb6eff9393fd7f Mon Sep 17 00:00:00 2001 From: TroyHernandez Date: Sat, 6 Jun 2026 22:57:50 -0500 Subject: [PATCH 2/5] Migrate all endpoints to tinyoauth::oauth_request; drop httr - All endpoint files use tinyoauth::oauth_request (Bearer header, retry, JSON parse); removed httr RETRY/GET/content/config/stop_for_status everywhere - authenticate.R on tinyoauth with oauth_import_httr() .httr-oauth carry-over - DESCRIPTION: Imports trimmed to tinyoauth only (dropped httr + jsonlite), Remotes: cornball-ai/tinyoauth; package doc imports dropped - Fixed two pre-existing latent bugs surfaced by live testing: get_artist() 'id=' typo and get_album() stray undefined playlist_id line - Verified live across ~15 endpoints (catalog, user, search, browse, paginated) --- DESCRIPTION | 2 - NAMESPACE | 13 ------ R/albums.R | 23 +++------- R/artists.R | 39 +++++----------- R/browse.R | 46 ++++++------------- R/follow.R | 21 +++------ R/library.R | 8 +--- R/personalization.R | 4 +- R/player.R | 43 ++++++------------ R/playlists.R | 105 ++++++++++---------------------------------- R/search.R | 7 +-- R/shows.R | 21 +++------ R/tinyspotifyr.R | 2 - R/users_profile.R | 11 ++--- 14 files changed, 87 insertions(+), 258 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 009f82f..cfb2491 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -7,8 +7,6 @@ Description: An R wrapper for the 'Spotify' Web API . Depends: R (>= 4.0) Imports: - httr, - jsonlite, tinyoauth Remotes: cornball-ai/tinyoauth License: MIT + file LICENSE diff --git a/NAMESPACE b/NAMESPACE index a648972..7cf83a8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -66,16 +66,3 @@ export(toggle_my_shuffle) export(transfer_my_playback) export(unfollow_playlist) export(verify_result) - -importFrom(httr,accept_json) -importFrom(httr,authenticate) -importFrom(httr,config) -importFrom(httr,content) -importFrom(httr,GET) -importFrom(httr,oauth_app) -importFrom(httr,oauth_endpoint) -importFrom(httr,oauth2.0_token) -importFrom(httr,RETRY) -importFrom(httr,stop_for_status) -importFrom(jsonlite,fromJSON) -importFrom(jsonlite,toJSON) diff --git a/R/albums.R b/R/albums.R index 7015979..435af61 100644 --- a/R/albums.R +++ b/R/albums.R @@ -19,17 +19,12 @@ get_album <- function(id, market = NULL, authorization = get_spotify_access_toke } params <- list( - market = market, - access_token = authorization + market = market ) - url <- paste0(base_url, "/", playlist_id, "/tracks?market=", market) url <- paste0(base_url, "/", id) - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- jsonlite::fromJSON(content(res, as = 'text', encoding = 'UTF-8'), - flatten = TRUE) return(res) } @@ -57,13 +52,10 @@ get_albums <- function(ids, market = NULL, authorization = get_spotify_access_to params <- list( ids = paste(ids, collapse = ','), - market = market, - access_token = authorization + market = market ) - res <- RETRY('GET', base_url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) if (!include_meta_info) { res <- res$albums @@ -108,14 +100,11 @@ get_album_tracks <- function(id, limit = 20, offset = 0, market = NULL, authoriz params <- list( market = market, offset = offset, - limit = limit, - access_token = authorization + limit = limit ) url <- paste0(base_url, "/", id, "/tracks") - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) if (!include_meta_info) { res <- res$items diff --git a/R/artists.R b/R/artists.R index d68e4a0..5e17ae7 100644 --- a/R/artists.R +++ b/R/artists.R @@ -10,14 +10,10 @@ get_artist <- function(id, authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/artists' - params <- list( - access_token = authorization - ) - url <- paste0(base_url, "/", id=) - res <- GET(url, query = params, encode = 'json') - stop_for_status(res) + params <- list() + url <- paste0(base_url, "/", id) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) return(res) } @@ -36,13 +32,10 @@ get_artists <- function(ids, authorization = get_spotify_access_token(), include base_url <- 'https://api.spotify.com/v1/artists' params <- list( - ids = paste(ids, collapse = ','), - access_token = authorization + ids = paste(ids, collapse = ',') ) - res <- GET(base_url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) if (!include_meta_info) { res <- res$artists @@ -93,14 +86,11 @@ get_artist_albums <- function(id, include_groups = c('album', 'single', 'appears include_groups = paste(include_groups, collapse = ','), market = market, limit = limit, - offset = offset, - access_token = authorization + offset = offset ) url <- paste0(base_url, "/", id, "/albums") - res <- GET(url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) if (!include_meta_info) { res <- res$items @@ -131,14 +121,11 @@ get_artist_top_tracks <- function(id, market = 'US', authorization = get_spotify } params <- list( - market = market, - access_token = authorization + market = market ) url <- paste0(base_url, "/", id, "/top-tracks") - res <- GET(url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) if (!include_meta_info) { res <- res$tracks @@ -160,14 +147,10 @@ get_related_artists <- function(id, authorization = get_spotify_access_token(), base_url <- 'https://api.spotify.com/v1/artists' - params <- list( - access_token = authorization - ) + params <- list() url <- paste0(base_url, "/", id, "/related-artists") - res <- GET(url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) if (!include_meta_info) { res <- res$artists diff --git a/R/browse.R b/R/browse.R index 2b508e5..662485b 100644 --- a/R/browse.R +++ b/R/browse.R @@ -11,15 +11,10 @@ get_categories <- function(authorization = get_spotify_access_token(), df = TRUE url <- 'https://api.spotify.com/v1/browse/categories' - params <- list( - access_token = authorization - ) + params <- list() - res <- httr::GET(url, query = params, encode = 'json') - httr::stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- jsonlite::fromJSON(httr::content(res, as = 'text', encoding = 'UTF-8'), - flatten = TRUE) if(df){ res <- res$categories$items @@ -44,15 +39,11 @@ get_category <- function(category_id, country = NULL, locale = NULL, authorizati params <- list( country = country, - locale = locale, - access_token = authorization + locale = locale ) - res <- httr::RETRY('GET', url, query = params, encode = 'json') - httr::stop_for_status(res) - res0 <- jsonlite::fromJSON(httr::content(res, as = 'text', - encoding = 'UTF-8'), - flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + res0 <- res res <- as.data.frame(res0, stringsAsFactors = FALSE) return(res) } @@ -81,12 +72,10 @@ get_category_playlists <- function(category_id, market = NULL, limit = 20, offse url <- paste0(base_url, "/", category_id, "/playlists") params <- list(market = market, limit = limit, - offset = offset, access_token = authorization) + offset = offset) - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) res <- res$playlists if(!include_meta_info){ @@ -117,12 +106,9 @@ get_new_releases <- function(country = NULL, limit = 20, offset = 0, authorizati params <- list( country = country, limit = limit, - offset = offset, - access_token = authorization + offset = offset ) - res <- RETRY('GET', base_url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) res <- res$albums if(!include_meta_info){ @@ -157,12 +143,9 @@ get_featured_playlists <- function(locale = NULL, country = NULL, timestamp = NU country = country, timestamp = timestamp, limit = limit, - offset = offset, - access_token = authorization + offset = offset ) - res <- RETRY('GET', base_url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) res$playlists$message <- res$message res <- res$playlists if (!include_meta_info) { @@ -340,13 +323,10 @@ get_recommendations <- function(limit = 20, target_speechiness = target_speechiness, target_tempo = target_tempo, target_time_signature = target_time_signature, - target_valence = target_valence, - access_token = authorization + target_valence = target_valence ) - res <- RETRY('GET', base_url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) if (!include_seeds_in_response) { res <- res$tracks } diff --git a/R/follow.R b/R/follow.R index c1c14e0..b14b711 100644 --- a/R/follow.R +++ b/R/follow.R @@ -13,8 +13,7 @@ follow_artists_or_users <- function(type, ids, authorization = get_spotify_autho type = type, ids = paste0(ids, collapse = ',') ) - res <- RETRY('PUT', base_url, config(token = authorization), query = query_params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = query_params, flatten = TRUE) return(res) } @@ -35,8 +34,7 @@ follow_playlist <- function(playlist_id, public = FALSE, authorization = get_spo params <- list( public = public ) - res <- RETRY('PUT', url, config(token = authorization), body = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "PUT", body = params, flatten = TRUE) return(res) } @@ -53,8 +51,7 @@ follow_playlist <- function(playlist_id, public = FALSE, authorization = get_spo unfollow_playlist <- function(playlist_id, authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/followers") - res <- RETRY('DELETE', url, config(token = authorization), encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "DELETE", flatten = TRUE) return(res) } @@ -75,9 +72,7 @@ get_my_followed_artists <- function(limit = 20, after = NULL, authorization = ge limit = limit, after = after ) - res <- RETRY('GET', base_url, query = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) res <- res$artists if (!include_meta_info) { res <- res$items @@ -101,9 +96,7 @@ check_me_following <- function(type, ids, authorization = get_spotify_authorizat type = type, ids = paste0(ids, collapse = ',') ) - res <- RETRY('GET', base_url, query = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) data.frame(type = type, id = ids, @@ -130,9 +123,7 @@ check_users_following <- function(playlist_id, ids, authorization = get_spotify_ ids = paste0(ids, collapse = ',') ) url <- paste0(base_url, "/", playlist_id, "/followers/contains") - res <- RETRY('GET', url, query = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) data.frame(user_id = ids, playlist_id = playlist_id, diff --git a/R/library.R b/R/library.R index 5b330a7..a00e0ae 100644 --- a/R/library.R +++ b/R/library.R @@ -30,9 +30,7 @@ get_my_saved_albums <- function(limit = 20, offset = 0, market = NULL, authoriza offset = offset, market = market ) - res <- RETRY('GET', base_url, query = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items @@ -72,9 +70,7 @@ get_my_saved_tracks <- function(limit = 20, offset = 0, market = NULL, authoriza offset = offset, market = market ) - res <- RETRY('GET', base_url, query = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items diff --git a/R/personalization.R b/R/personalization.R index a19a950..ea9ea12 100644 --- a/R/personalization.R +++ b/R/personalization.R @@ -43,10 +43,8 @@ get_my_top_artists_or_tracks <- function(type = NULL, limit = 20, offset = 0, ti time_range = time_range ) url <- paste0(base_url, "/", type) - res <- RETRY('GET', url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) if (!include_meta_info) { res <- res$items diff --git a/R/player.R b/R/player.R index 22cd134..71265c4 100644 --- a/R/player.R +++ b/R/player.R @@ -10,9 +10,7 @@ get_my_currently_playing <- function(market = NULL, authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/currently-playing' params <- list(market = market) - res <- RETRY('GET', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) return(res) } @@ -36,9 +34,7 @@ get_my_recently_played <- function(limit = 20, after = NULL, before = NULL, auth after = after, before = before ) - res <- RETRY('GET', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items } @@ -55,9 +51,7 @@ get_my_recently_played <- function(limit = 20, after = NULL, before = NULL, auth get_my_devices <- function(authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/devices' - res <- RETRY('GET', base_url, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", flatten = TRUE) return(res$devices) } @@ -73,9 +67,7 @@ get_my_devices <- function(authorization = get_spotify_authorization_code()) { get_my_current_playback <- function(market = NULL, authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player' params <- list(market = market) - res <- RETRY('GET', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) return(res) } @@ -91,8 +83,7 @@ get_my_current_playback <- function(market = NULL, authorization = get_spotify_a pause_my_playback <- function(device_id = NULL, authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/pause' params <- list(device_id = device_id) - res <- RETRY('PUT', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) return(res) } @@ -115,8 +106,7 @@ toggle_my_shuffle <- function(state, device_id = NULL, authorization = get_spoti state = state, device_id = device_id ) - res <- RETRY('PUT', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) return(res) } @@ -142,8 +132,7 @@ set_my_repeat_mode <- function(state, device_id = NULL, authorization = get_spot state = state, device_id = device_id ) - res <- RETRY('PUT', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) return(res) } @@ -166,8 +155,7 @@ set_my_volume <- function(volume_percent, device_id = NULL, authorization = get_ volume_percent = volume_percent, device_id = device_id ) - res <- RETRY('PUT', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) return(res) } @@ -185,8 +173,7 @@ skip_my_playback <- function(device_id = NULL, authorization = get_spotify_autho params <- list( device_id = device_id ) - res <- RETRY('POST', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "POST", query = params, flatten = TRUE) return(res) } @@ -204,8 +191,7 @@ skip_my_playback_previous <- function(device_id = NULL, authorization = get_spot params <- list( device_id = device_id ) - res <- RETRY('POST', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "POST", query = params, flatten = TRUE) return(res) } @@ -235,8 +221,7 @@ start_my_playback <- function(device_id = NULL, context_uri = NULL, uris = NULL, offset = offset, position_ms = position_ms ) - res <- RETRY('PUT', base_url, query = query_params, config(token = authorization), body = body_params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = query_params, body = body_params, flatten = TRUE) return(res) } @@ -259,8 +244,7 @@ transfer_my_playback <- function(device_ids, play = FALSE, authorization = get_s device_ids = list(device_ids), play = play ) - res <- RETRY('PUT', base_url, config(token = authorization), body = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", body = params, flatten = TRUE) return(res) } @@ -285,7 +269,6 @@ seek_to_position <- function(position_ms, device_id = NULL, authorization = get_ position_ms = position_ms, device_id = device_id ) - res <- RETRY('PUT', base_url, config(token = authorization), query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) return(res) } diff --git a/R/playlists.R b/R/playlists.R index de1e91b..fa0eb9d 100644 --- a/R/playlists.R +++ b/R/playlists.R @@ -16,17 +16,14 @@ add_items_to_playlist <- function(playlist_id, uris, position = NULL, market = "US", authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' - + if(is.null(position)){ - url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ","), "&market=", market) + url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ","), "&market=", market) } else { - url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ","), "&market=", market, "&position=", position) + url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ","), "&market=", market, "&position=", position) } - - res <- RETRY('POST', url, config(token = authorization), encode = 'json') #, body = params) - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - return(res) + + tinyoauth::oauth_request(authorization, url, "POST", flatten = TRUE) } #' Add one or more tracks to a user’s playlist. @@ -51,10 +48,7 @@ add_tracks_to_playlist <- function(playlist_id, uris, position = NULL, market = market = market, position = position ) - res <- RETRY('POST', url, body = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - return(res) + tinyoauth::oauth_request(authorization, url, "POST", body = params, flatten = TRUE) } @@ -80,9 +74,7 @@ change_playlist_details <- function(playlist_id, name = NULL, public = NULL, col collaborative = collaborative, description = description ) - res <- RETRY('PUT', url, body = params, config(token = authorization), encode = 'json') - stop_for_status(res) - return(res) + tinyoauth::oauth_request(authorization, url, "PUT", body = params, flatten = TRUE) } #' Create a playlist for a Spotify user. (The playlist will be empty until you add tracks.) @@ -107,10 +99,7 @@ create_playlist <- function(user_id, name, public = TRUE, collaborative = FALSE, collaborative = collaborative, description = description ) - res <- RETRY('POST', url, body = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - return(res) + tinyoauth::oauth_request(authorization, url, "POST", body = params, flatten = TRUE) } #' Get a list of the playlists owned or followed by the current Spotify user. @@ -137,10 +126,8 @@ get_my_playlists <- function(limit = 20, offset = 0, authorization = get_spotify limit = limit, offset = offset ) - res <- RETRY('GET', base_url, query = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + if (!include_meta_info) { res <- res$items } @@ -172,9 +159,7 @@ get_user_playlists <- function(user_id, limit = 20, offset = 0, authorization = limit = limit, offset = offset ) - res <- RETRY('GET', url, query = params, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items } @@ -193,10 +178,7 @@ get_user_playlists <- function(user_id, limit = 20, offset = 0, authorization = get_playlist_cover_image <- function(playlist_id, authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/images") - res <- RETRY('GET', url, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - return(res) + tinyoauth::oauth_request(authorization, url, "GET", flatten = TRUE) } #' Get a playlist owned by a Spotify user. @@ -220,15 +202,9 @@ get_playlist <- function(playlist_id, fields = NULL, market = NULL, authorizatio url <- paste0(base_url, "/", playlist_id) params <- list( fields = paste(fields, collapse = ','), - market = market, - access_token = authorization + market = market ) - - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), - flatten = TRUE) - return(res) + tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) } #' Get full details of the items of a playlist owned by a Spotify user. @@ -255,20 +231,17 @@ get_playlist <- function(playlist_id, fields = NULL, market = NULL, authorizatio #' @export get_playlist_items <- function(playlist_id, fields = NULL, limit = 100, offset = 0, market = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - + base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/tracks") params <- list( fields = ifelse(!is.null(fields), paste0('items(', paste0(fields, collapse = ','), ')'), ''), limit = limit, offset = offset, - market = market, - access_token = authorization + market = market ) - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + if (!include_meta_info) { res <- res$items } @@ -306,12 +279,9 @@ get_playlist_tracks <- function(playlist_id, fields = NULL, limit = 100, offset fields = ifelse(!is.null(fields), paste0('items(', paste0(fields, collapse = ','), ')'), ''), limit = limit, offset = offset, - market = market, - access_token = authorization + market = market ) - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items @@ -334,36 +304,13 @@ remove_tracks_from_playlist <- function(playlist_id, uris, authorization = get_s base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/tracks/") - # For DELETE request params URIs should be put in body + # For DELETE the URIs go in the body, as an R list; oauth_request JSON-encodes it. uris_list <- lapply(uris, function(x) list(uri = x)) - params <- jsonlite::toJSON(list(tracks = uris_list), auto_unbox = TRUE) + params <- list(tracks = uris_list) - res <- httr::RETRY('DELETE', url, body = params, httr::config(token = authorization), encode = 'json') - stop_for_status(res) - res <- jsonlite::fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - return(res) + tinyoauth::oauth_request(authorization, url, "DELETE", body = params, flatten = TRUE) } -# remove_tracks_from_playlist <- function(playlist_id, uris, positions, market = "US", authorization = get_spotify_authorization_code()) { -# base_url <- 'https://api.spotify.com/v1/playlists' -# url <- paste0(base_url, "/", playlist_id, "/tracks") -# if(!is.null(market)){ -# url <- paste0(url, "?market=", market) -# } -# -# # For DELETE request params URIs should be put in body -# uris_list <- lapply(uris, function(x) list(uri = x)) -# for(i in 1:length(positions)){ -# uris_list[[i]]$positions <- list(positions[i]) -# } -# params <- jsonlite::toJSON(list(tracks = uris_list), auto_unbox = TRUE) -# -# res <- httr::RETRY('DELETE', url, body = params, httr::config(token = authorization), encode = 'json') -# stop_for_status(res) -# res <- jsonlite::fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) -# return(res) -# } - #' Add the latest episode of a podcast to a user’s playlist. #' #' @param playlist_id Required. The \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify ID} for the playlist. @@ -402,9 +349,5 @@ reorder_replace_playlist_items <- function(playlist_id, uris, authorization = ge base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ",")) - res <- httr::RETRY('PUT', url, #body = params, - httr::config(token = authorization), encode = 'json') - httr::stop_for_status(res) - res <- jsonlite::fromJSON(httr::content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - return(res) + tinyoauth::oauth_request(authorization, url, "PUT", flatten = TRUE) } diff --git a/R/search.R b/R/search.R index 7207f15..9b8a740 100644 --- a/R/search.R +++ b/R/search.R @@ -74,13 +74,10 @@ search_spotify <- function(q, type = c('album', 'artist', 'playlist', 'track'), market = market, limit = limit, offset = offset, - include_external = include_external, - access_token = authorization + include_external = include_external ) - res <- RETRY('GET', base_url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) return(res) } diff --git a/R/shows.R b/R/shows.R index 5a4a859..a82df3b 100644 --- a/R/shows.R +++ b/R/shows.R @@ -14,14 +14,11 @@ get_show <- function(id, market = "US", authorization = get_spotify_access_token base_url <- 'https://api.spotify.com/v1/shows' params <- list( - market = market, - access_token = authorization + market = market ) url <- paste0(base_url, "/", id) - res <- httr::GET(url, query = params, encode = 'json') - httr::stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- jsonlite::fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) return(res) } @@ -43,14 +40,11 @@ get_shows <- function(ids, market = "US", authorization = get_spotify_access_tok params <- list( ids = paste(ids, collapse = ','), - market = market, - access_token = authorization + market = market ) url <- paste0(base_url) - res <- httr::GET(url, query = params, encode = 'json') - httr::stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- jsonlite::fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) return(res) } @@ -72,14 +66,11 @@ get_shows_episodes <- function(id, market = "US", authorization = get_spotify_ac base_url <- 'https://api.spotify.com/v1/shows' params <- list( - market = market, - access_token = authorization + market = market ) url <- paste0(base_url, "/", id, "/episodes?market=", market) - res <- GET(url, query = params, encode = 'json') - stop_for_status(res) + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - res <- jsonlite::fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) return(res) } diff --git a/R/tinyspotifyr.R b/R/tinyspotifyr.R index 770ef16..66c0c1f 100644 --- a/R/tinyspotifyr.R +++ b/R/tinyspotifyr.R @@ -3,8 +3,6 @@ #' See the README on #' \href{https://github.com/troyhernandez/tinyspotifyr#readme}{GitHub} #' -#' @importFrom httr RETRY GET accept_json authenticate config content oauth2.0_token oauth_app oauth_endpoint stop_for_status -#' @importFrom jsonlite fromJSON toJSON #' @keywords internal "_PACKAGE" diff --git a/R/users_profile.R b/R/users_profile.R index 9df0218..fa2c366 100644 --- a/R/users_profile.R +++ b/R/users_profile.R @@ -8,9 +8,7 @@ get_my_profile <- function(authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/' - res <- RETRY('GET', base_url, config(token = authorization), encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", flatten = TRUE) res <- t(unlist(res)) return(res) @@ -27,11 +25,8 @@ get_my_profile <- function(authorization = get_spotify_authorization_code()) { get_user_profile <- function(user_id, authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/users' url <- paste0(base_url, "/", user_id) - params = list(access_token = authorization) - res <- RETRY('GET', url, query = params, encode = 'json') - stop_for_status(res) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) - res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE) + params = list() + res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) res <- t(unlist(res)) return(res) From 48f38e25db9614f4b5b32468e179958113a1d2b4 Mon Sep 17 00:00:00 2001 From: TroyHernandez Date: Sat, 6 Jun 2026 22:58:33 -0500 Subject: [PATCH 3/5] rformat + document --- R/albums.R | 42 ++++----- R/artists.R | 56 ++++++------ R/authenticate.R | 35 ++++---- R/browse.R | 205 +++++++++++++++++++------------------------- R/follow.R | 73 +++++++--------- R/library.R | 27 +++--- R/personalization.R | 17 ++-- R/player.R | 127 ++++++++++++++------------- R/playlists.R | 137 +++++++++++++++-------------- R/search.R | 21 +++-- R/shows.R | 71 ++++++++------- R/tinyspotifyr.R | 86 +++++-------------- R/tracks.R | 18 ++-- R/users_profile.R | 14 +-- R/utils.R | 35 ++++---- 15 files changed, 447 insertions(+), 517 deletions(-) diff --git a/R/albums.R b/R/albums.R index 435af61..c5e533e 100644 --- a/R/albums.R +++ b/R/albums.R @@ -8,8 +8,8 @@ #' Returns a data frame of results containing album data. See the \href{https://developer.spotify.com/documentation/web-api}{official documentation} for more information. #' @export -get_album <- function(id, market = NULL, authorization = get_spotify_access_token()) { - +get_album <- function(id, market = NULL, + authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/albums' if (!is.null(market)) { @@ -18,13 +18,11 @@ get_album <- function(id, market = NULL, authorization = get_spotify_access_toke } } - params <- list( - market = market - ) + params <- list(market = market) url <- paste0(base_url, "/", id) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) return(res) } @@ -40,8 +38,9 @@ get_album <- function(id, market = NULL, authorization = get_spotify_access_toke #' Returns a data frame of results containing album data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_albums <- function(ids, market = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_albums <- function(ids, market = NULL, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/albums' if (!is.null(market)) { @@ -50,12 +49,9 @@ get_albums <- function(ids, market = NULL, authorization = get_spotify_access_to } } - params <- list( - ids = paste(ids, collapse = ','), - market = market - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) - + params <- list(ids = paste(ids, collapse = ','), market = market) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$albums @@ -87,8 +83,9 @@ get_albums <- function(ids, market = NULL, authorization = get_spotify_access_to #' Returns a data frame of results containing album data. See the official API \href{https://developer.spotify.com/documentation/web-api}{documentation} for more information. #' @export -get_album_tracks <- function(id, limit = 20, offset = 0, market = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_album_tracks <- function(id, limit = 20, offset = 0, market = NULL, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/albums' if (!is.null(market)) { @@ -97,14 +94,10 @@ get_album_tracks <- function(id, limit = 20, offset = 0, market = NULL, authoriz } } - params <- list( - market = market, - offset = offset, - limit = limit - ) + params <- list(market = market, offset = offset, limit = limit) url <- paste0(base_url, "/", id, "/tracks") - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items @@ -112,3 +105,4 @@ get_album_tracks <- function(id, limit = 20, offset = 0, market = NULL, authoriz return(res) } + diff --git a/R/artists.R b/R/artists.R index 5e17ae7..85bdef7 100644 --- a/R/artists.R +++ b/R/artists.R @@ -7,13 +7,12 @@ #' @export get_artist <- function(id, authorization = get_spotify_access_token()) { - base_url <- 'https://api.spotify.com/v1/artists' params <- list() url <- paste0(base_url, "/", id) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) return(res) } @@ -27,15 +26,13 @@ get_artist <- function(id, authorization = get_spotify_access_token()) { #' Returns a data frame of results containing artist data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_artists <- function(ids, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_artists <- function(ids, authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/artists' - params <- list( - ids = paste(ids, collapse = ',') - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) - + params <- list(ids = paste(ids, collapse = ',')) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$artists @@ -72,8 +69,11 @@ get_artists <- function(ids, authorization = get_spotify_access_token(), include #' Returns a data frame of results containing artist data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_artist_albums <- function(id, include_groups = c('album', 'single', 'appears_on', 'compilation'), market = NULL, limit = 20, offset = 0, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_artist_albums <- function(id, + include_groups = c('album', 'single', 'appears_on', 'compilation'), + market = NULL, limit = 20, offset = 0, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/artists' if (!is.null(market)) { @@ -82,16 +82,11 @@ get_artist_albums <- function(id, include_groups = c('album', 'single', 'appears } } - params <- list( - include_groups = paste(include_groups, collapse = ','), - market = market, - limit = limit, - offset = offset - ) + params <- list(include_groups = paste(include_groups, collapse = ','), + market = market, limit = limit, offset = offset) url <- paste0(base_url, "/", id, "/albums") res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - if (!include_meta_info) { res <- res$items } @@ -110,8 +105,9 @@ get_artist_albums <- function(id, include_groups = c('album', 'single', 'appears #' Returns a data frame of results containing artist data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_artist_top_tracks <- function(id, market = 'US', authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_artist_top_tracks <- function(id, market = 'US', + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/artists' if (!is.null(market)) { @@ -120,12 +116,10 @@ get_artist_top_tracks <- function(id, market = 'US', authorization = get_spotify } } - params <- list( - market = market - ) + params <- list(market = market) url <- paste0(base_url, "/", id, "/top-tracks") - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$tracks @@ -143,14 +137,15 @@ get_artist_top_tracks <- function(id, market = 'US', authorization = get_spotify #' Returns a data frame of results containing artist data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_related_artists <- function(id, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_related_artists <- function(id, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/artists' params <- list() url <- paste0(base_url, "/", id, "/related-artists") - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$artists @@ -158,3 +153,4 @@ get_related_artists <- function(id, authorization = get_spotify_access_token(), return(res) } + diff --git a/R/authenticate.R b/R/authenticate.R index ce9a3a2..57a7b01 100644 --- a/R/authenticate.R +++ b/R/authenticate.R @@ -10,10 +10,10 @@ #' @keywords internal .spotify_client <- function(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET")) { - tinyoauth::oauth_client( - id = client_id, secret = client_secret, - token_url = "https://accounts.spotify.com/api/token", - auth_url = "https://accounts.spotify.com/authorize") + tinyoauth::oauth_client( + id = client_id, secret = client_secret, + token_url = "https://accounts.spotify.com/api/token", + auth_url = "https://accounts.spotify.com/authorize") } #' Get Spotify Access Token @@ -30,8 +30,9 @@ #' } get_spotify_access_token <- function(client_id = Sys.getenv('SPOTIFY_CLIENT_ID'), client_secret = Sys.getenv('SPOTIFY_CLIENT_SECRET')) { - tok <- tinyoauth::oauth_token_client(.spotify_client(client_id, client_secret)) - tok$access_token + tok <- tinyoauth::oauth_token_client(.spotify_client(client_id, + client_secret)) + tok$access_token } #' Get Spotify authorization Code @@ -50,15 +51,17 @@ get_spotify_access_token <- function(client_id = Sys.getenv('SPOTIFY_CLIENT_ID') #' get_spotify_authorization_code() #' } get_spotify_authorization_code <- function(client_id = Sys.getenv("SPOTIFY_CLIENT_ID"), - client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET"), - scope = tinyspotifyr::scopes) { - client <- .spotify_client(client_id, client_secret) - legacy <- ".httr-oauth" - if (file.exists(legacy)) { - imp <- tryCatch(tinyoauth::oauth_import_httr(legacy), error = function(e) NULL) - if (!is.null(imp)) { - return(tinyoauth::oauth_refresh(imp$client, imp$token)) + client_secret = Sys.getenv("SPOTIFY_CLIENT_SECRET"), + scope = tinyspotifyr::scopes) { + client <- .spotify_client(client_id, client_secret) + legacy <- ".httr-oauth" + if (file.exists(legacy)) { + imp <- tryCatch(tinyoauth::oauth_import_httr(legacy), + error = function(e) NULL) + if (!is.null(imp)) { + return(tinyoauth::oauth_refresh(imp$client, imp$token)) + } } - } - tinyoauth::oauth_token(client, scope = paste(scope, collapse = " ")) + tinyoauth::oauth_token(client, scope = paste(scope, collapse = " ")) } + diff --git a/R/browse.R b/R/browse.R index 662485b..022af3e 100644 --- a/R/browse.R +++ b/R/browse.R @@ -7,22 +7,21 @@ #' Returns a data frame of results containing album data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_categories <- function(authorization = get_spotify_access_token(), df = TRUE) { - +get_categories <- function(authorization = get_spotify_access_token(), + df = TRUE) { url <- 'https://api.spotify.com/v1/browse/categories' params <- list() - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) - if(df){ + if (df) { res <- res$categories$items } return(res) } - #' Get a single category used to tag items in Spotify (on, for example, the Spotify player’s “Browse” tab). #' #' @param category_id Required. The \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify ID} for the category. @@ -33,22 +32,20 @@ get_categories <- function(authorization = get_spotify_access_token(), df = TRUE #' Returns a list of results containing category information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_category <- function(category_id, country = NULL, locale = NULL, authorization = get_spotify_access_token()) { +get_category <- function(category_id, country = NULL, locale = NULL, + authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/browse/categories' url <- paste0(base_url, "/", category_id) - params <- list( - country = country, - locale = locale - ) + params <- list(country = country, locale = locale) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) res0 <- res res <- as.data.frame(res0, stringsAsFactors = FALSE) return(res) } - #' Get a list of Spotify playlists tagged with a particular category. #' #' @param category_id Required. The \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify ID} for the category. @@ -67,18 +64,21 @@ get_category <- function(category_id, country = NULL, locale = NULL, authorizati #' get_category_playlists('party', country = 'BR') #' } -get_category_playlists <- function(category_id, market = NULL, limit = 20, offset = 0, authorization = get_spotify_access_token(), include_meta_info = FALSE) { +get_category_playlists <- function(category_id, market = NULL, limit = 20, + offset = 0, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/browse/categories' url <- paste0(base_url, "/", category_id, "/playlists") - params <- list(market = market, limit = limit, - offset = offset) + params <- list(market = market, limit = limit, offset = offset) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) res <- res$playlists - if(!include_meta_info){ + if (!include_meta_info) { res <- res$items } return(res) @@ -101,17 +101,16 @@ get_category_playlists <- function(category_id, market = NULL, limit = 20, offse #' get_new_releases(country = 'SE') #' } -get_new_releases <- function(country = NULL, limit = 20, offset = 0, authorization = get_spotify_access_token(), include_meta_info = FALSE) { +get_new_releases <- function(country = NULL, limit = 20, offset = 0, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/browse/new-releases' - params <- list( - country = country, - limit = limit, - offset = offset - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + params <- list(country = country, limit = limit, offset = offset) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) res <- res$albums - if(!include_meta_info){ + if (!include_meta_info) { res <- res$items } return(res) @@ -136,15 +135,13 @@ get_new_releases <- function(country = NULL, limit = 20, offset = 0, authorizati #' get_featured_playlists(country = 'SE') #' } -get_featured_playlists <- function(locale = NULL, country = NULL, timestamp = NULL, limit = 20, offset = 0, authorization = get_spotify_access_token(), include_meta_info = FALSE) { +get_featured_playlists <- function(locale = NULL, country = NULL, + timestamp = NULL, limit = 20, offset = 0, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/browse/featured-playlists' - params <- list( - locale = locale, - country = country, - timestamp = timestamp, - limit = limit, - offset = offset - ) + params <- list(locale = locale, country = country, timestamp = timestamp, + limit = limit, offset = offset) res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) res$playlists$message <- res$message res <- res$playlists @@ -217,37 +214,23 @@ get_featured_playlists <- function(locale = NULL, country = NULL, timestamp = NU #' get_recommendations(country = 'SE') #' } -get_recommendations <- function(limit = 20, - market = NULL, - seed_artists = NULL, - seed_genres = NULL, - seed_tracks = NULL, - max_acousticness = NULL, +get_recommendations <- function(limit = 20, market = NULL, + seed_artists = NULL, seed_genres = NULL, + seed_tracks = NULL, max_acousticness = NULL, max_danceability = NULL, - max_duration_ms = NULL, - max_energy = NULL, - max_instrumentalness = NULL, - max_key = NULL, - max_liveness = NULL, - max_loudness = NULL, - max_mode = NULL, - max_popularity = NULL, - max_speechiness = NULL, - max_tempo = NULL, + max_duration_ms = NULL, max_energy = NULL, + max_instrumentalness = NULL, max_key = NULL, + max_liveness = NULL, max_loudness = NULL, + max_mode = NULL, max_popularity = NULL, + max_speechiness = NULL, max_tempo = NULL, max_time_signature = NULL, - max_valence = NULL, - min_acousticness = NULL, + max_valence = NULL, min_acousticness = NULL, min_danceability = NULL, - min_duration_ms = NULL, - min_energy = NULL, - min_instrumentalness = NULL, - min_key = NULL, - min_liveness = NULL, - min_loudness = NULL, - min_mode = NULL, - min_popularity = NULL, - min_speechiness = NULL, - min_tempo = NULL, + min_duration_ms = NULL, min_energy = NULL, + min_instrumentalness = NULL, min_key = NULL, + min_liveness = NULL, min_loudness = NULL, + min_mode = NULL, min_popularity = NULL, + min_speechiness = NULL, min_tempo = NULL, min_time_signature = NULL, min_valence = NULL, target_acousticness = NULL, @@ -255,10 +238,8 @@ get_recommendations <- function(limit = 20, target_duration_ms = NULL, target_energy = NULL, target_instrumentalness = NULL, - target_key = NULL, - target_liveness = NULL, - target_loudness = NULL, - target_mode = NULL, + target_key = NULL, target_liveness = NULL, + target_loudness = NULL, target_mode = NULL, target_popularity = NULL, target_speechiness = NULL, target_tempo = NULL, @@ -266,65 +247,52 @@ get_recommendations <- function(limit = 20, target_valence = NULL, authorization = get_spotify_access_token(), include_seeds_in_response = FALSE) { - .Deprecated(msg = paste("get_recommendations(): Spotify removed", - "GET /v1/recommendations (HTTP 404) in November 2024;", - "the endpoint no longer exists.")) + "GET /v1/recommendations (HTTP 404) in November 2024;", + "the endpoint no longer exists.")) if (length(seed_artists) + length(seed_tracks) + length(seed_genres) > 5) { stop("Too many seed values. Up to 5 seed values may be provided in any combination of seed_artists, seed_tracks and seed_genres") } base_url <- 'https://api.spotify.com/v1/recommendations' - params <- list( - limit = limit, - market = market, - seed_artists = paste(seed_artists, collapse = ','), - seed_genres = paste(seed_genres, collapse = ','), - seed_tracks = paste(seed_tracks, collapse = ','), - max_acousticness = max_acousticness, - max_danceability = max_danceability, - max_duration_ms = max_duration_ms, - max_energy = max_energy, - max_instrumentalness = max_instrumentalness, - max_key = max_key, - max_liveness = max_liveness, - max_loudness = max_loudness, - max_mode = max_mode, - max_popularity = max_popularity, - max_speechiness = max_speechiness, - max_tempo = max_tempo, - max_time_signature = max_time_signature, - max_valence = max_valence, - min_acousticness = min_acousticness, - min_danceability = min_danceability, - min_duration_ms = min_duration_ms, - min_energy = min_energy, - min_instrumentalness = min_instrumentalness, - min_key = min_key, - min_liveness = min_liveness, - min_loudness = min_loudness, - min_mode = min_mode, - min_popularity = min_popularity, - min_speechiness = min_speechiness, - min_tempo = min_tempo, - min_time_signature = min_time_signature, - min_valence = min_valence, - target_acousticness = target_acousticness, - target_danceability = target_danceability, - target_duration_ms = target_duration_ms, - target_energy = target_energy, - target_instrumentalness = target_instrumentalness, - target_key = target_key, - target_liveness = target_liveness, - target_loudness = target_loudness, - target_mode = target_mode, - target_popularity = target_popularity, - target_speechiness = target_speechiness, - target_tempo = target_tempo, - target_time_signature = target_time_signature, - target_valence = target_valence - ) + params <- list(limit = limit, market = market, + seed_artists = paste(seed_artists, collapse = ','), + seed_genres = paste(seed_genres, collapse = ','), + seed_tracks = paste(seed_tracks, collapse = ','), + max_acousticness = max_acousticness, + max_danceability = max_danceability, + max_duration_ms = max_duration_ms, max_energy = max_energy, + max_instrumentalness = max_instrumentalness, + max_key = max_key, max_liveness = max_liveness, + max_loudness = max_loudness, max_mode = max_mode, + max_popularity = max_popularity, + max_speechiness = max_speechiness, max_tempo = max_tempo, + max_time_signature = max_time_signature, + max_valence = max_valence, + min_acousticness = min_acousticness, + min_danceability = min_danceability, + min_duration_ms = min_duration_ms, min_energy = min_energy, + min_instrumentalness = min_instrumentalness, + min_key = min_key, min_liveness = min_liveness, + min_loudness = min_loudness, min_mode = min_mode, + min_popularity = min_popularity, + min_speechiness = min_speechiness, min_tempo = min_tempo, + min_time_signature = min_time_signature, + min_valence = min_valence, + target_acousticness = target_acousticness, + target_danceability = target_danceability, + target_duration_ms = target_duration_ms, + target_energy = target_energy, + target_instrumentalness = target_instrumentalness, + target_key = target_key, target_liveness = target_liveness, + target_loudness = target_loudness, + target_mode = target_mode, + target_popularity = target_popularity, + target_speechiness = target_speechiness, + target_tempo = target_tempo, + target_time_signature = target_time_signature, + target_valence = target_valence) res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) if (!include_seeds_in_response) { @@ -332,3 +300,4 @@ get_recommendations <- function(limit = 20, } return(res) } + diff --git a/R/follow.R b/R/follow.R index b14b711..d258347 100644 --- a/R/follow.R +++ b/R/follow.R @@ -7,13 +7,12 @@ #' No return value. User's account follows another on Spotify. #' @export -follow_artists_or_users <- function(type, ids, authorization = get_spotify_authorization_code()) { +follow_artists_or_users <- function(type, ids, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/following' - query_params <- list( - type = type, - ids = paste0(ids, collapse = ',') - ) - res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = query_params, flatten = TRUE) + query_params <- list(type = type, ids = paste0(ids, collapse = ',')) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", + query = query_params, flatten = TRUE) return(res) } @@ -28,13 +27,13 @@ follow_artists_or_users <- function(type, ids, authorization = get_spotify_autho #' No return value. #' @export -follow_playlist <- function(playlist_id, public = FALSE, authorization = get_spotify_authorization_code()) { +follow_playlist <- function(playlist_id, public = FALSE, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/followers") - params <- list( - public = public - ) - res <- tinyoauth::oauth_request(authorization, url, "PUT", body = params, flatten = TRUE) + params <- list(public = public) + res <- tinyoauth::oauth_request(authorization, url, "PUT", + body = params, flatten = TRUE) return(res) } @@ -48,10 +47,12 @@ follow_playlist <- function(playlist_id, public = FALSE, authorization = get_spo #' No return value. #' @export -unfollow_playlist <- function(playlist_id, authorization = get_spotify_authorization_code()) { +unfollow_playlist <- function(playlist_id, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/followers") - res <- tinyoauth::oauth_request(authorization, url, "DELETE", flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "DELETE", + flatten = TRUE) return(res) } @@ -65,14 +66,13 @@ unfollow_playlist <- function(playlist_id, authorization = get_spotify_authoriza #' Returns a data frame of results containing user's followed artists. #' @export -get_my_followed_artists <- function(limit = 20, after = NULL, authorization = get_spotify_authorization_code(), include_meta_info = FALSE) { +get_my_followed_artists <- function(limit = 20, after = NULL, + authorization = get_spotify_authorization_code(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/me/following' - params <- list( - type = 'artist', - limit = limit, - after = after - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + params <- list(type = 'artist', limit = limit, after = after) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) res <- res$artists if (!include_meta_info) { res <- res$items @@ -89,18 +89,14 @@ get_my_followed_artists <- function(limit = 20, after = NULL, authorization = ge #' Returns a list of results containing user following status. #' @export -check_me_following <- function(type, ids, authorization = get_spotify_authorization_code()) { - +check_me_following <- function(type, ids, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/following/contains' - params <- list( - type = type, - ids = paste0(ids, collapse = ',') - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + params <- list(type = type, ids = paste0(ids, collapse = ',')) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) - data.frame(type = type, - id = ids, - is_following = res) + data.frame(type = type, id = ids, is_following = res) } @@ -115,18 +111,15 @@ check_me_following <- function(type, ids, authorization = get_spotify_authorizat #' Returns a list of results containing user following status. #' @export -check_users_following <- function(playlist_id, ids, authorization = get_spotify_authorization_code()) { - +check_users_following <- function(playlist_id, ids, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' - params <- list( - playlist_id = playlist_id, - ids = paste0(ids, collapse = ',') - ) + params <- list(playlist_id = playlist_id, ids = paste0(ids, collapse = ',')) url <- paste0(base_url, "/", playlist_id, "/followers/contains") - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) - data.frame(user_id = ids, - playlist_id = playlist_id, - is_following = res) + data.frame(user_id = ids, playlist_id = playlist_id, is_following = res) } + diff --git a/R/library.R b/R/library.R index a00e0ae..8dc98af 100644 --- a/R/library.R +++ b/R/library.R @@ -18,19 +18,18 @@ #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_my_saved_albums <- function(limit = 20, offset = 0, market = NULL, authorization = get_spotify_authorization_code(), include_meta_info = FALSE) { +get_my_saved_albums <- function(limit = 20, offset = 0, market = NULL, + authorization = get_spotify_authorization_code(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/me/albums' if (!is.null(market)) { if (grepl('^[[:alpha:]]{2}$', market)) { stop('"market" must be an ISO 3166-1 alpha-2 country code') } } - params <- list( - limit = limit, - offset = offset, - market = market - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + params <- list(limit = limit, offset = offset, market = market) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items @@ -58,22 +57,22 @@ get_my_saved_albums <- function(limit = 20, offset = 0, market = NULL, authoriza #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_my_saved_tracks <- function(limit = 20, offset = 0, market = NULL, authorization = get_spotify_authorization_code(), include_meta_info = FALSE) { +get_my_saved_tracks <- function(limit = 20, offset = 0, market = NULL, + authorization = get_spotify_authorization_code(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/me/tracks' if (!is.null(market)) { if (grepl('^[[:alpha:]]{2}$', market)) { stop('"market" must be an ISO 3166-1 alpha-2 country code') } } - params <- list( - limit = limit, - offset = offset, - market = market - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + params <- list(limit = limit, offset = offset, market = market) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items } return(res) } + diff --git a/R/personalization.R b/R/personalization.R index ea9ea12..0fdfd17 100644 --- a/R/personalization.R +++ b/R/personalization.R @@ -17,8 +17,10 @@ #' Returns a data frame of results containing track or album data. See the official API \href{https://developer.spotify.com/documentation/web-api}{documentation} for more information. #' @export -get_my_top_artists_or_tracks <- function(type = NULL, limit = 20, offset = 0, time_range = 'medium_term', authorization = get_spotify_authorization_code(), include_meta_info = FALSE) { - +get_my_top_artists_or_tracks <- function(type = NULL, limit = 20, offset = 0, + time_range = 'medium_term', + authorization = get_spotify_authorization_code(), + include_meta_info = FALSE) { if (!type %in% c('artists', 'tracks')) { stop('"type" must be one of "artists" or "tracks"') } @@ -37,14 +39,10 @@ get_my_top_artists_or_tracks <- function(type = NULL, limit = 20, offset = 0, ti base_url <- 'https://api.spotify.com/v1/me/top' - params <- list( - limit = limit, - offset = offset, - time_range = time_range - ) + params <- list(limit = limit, offset = offset, time_range = time_range) url <- paste0(base_url, "/", type) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items @@ -52,3 +50,4 @@ get_my_top_artists_or_tracks <- function(type = NULL, limit = 20, offset = 0, ti return(res) } + diff --git a/R/player.R b/R/player.R index 71265c4..6a4acc5 100644 --- a/R/player.R +++ b/R/player.R @@ -7,10 +7,12 @@ #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_my_currently_playing <- function(market = NULL, authorization = get_spotify_authorization_code()) { +get_my_currently_playing <- function(market = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/currently-playing' params <- list(market = market) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) return(res) } @@ -26,15 +28,14 @@ get_my_currently_playing <- function(market = NULL, authorization = get_spotify_ #' Returns a list or data frame of results containing the most recently played tracks for the current user. #' @export -get_my_recently_played <- function(limit = 20, after = NULL, before = NULL, authorization = get_spotify_authorization_code(), include_meta_info = FALSE) { +get_my_recently_played <- function(limit = 20, after = NULL, before = NULL, + authorization = get_spotify_authorization_code(), + include_meta_info = FALSE) { stopifnot(is.null(after) | is.null(before)) base_url <- 'https://api.spotify.com/v1/me/player/recently-played' - params <- list( - limit = limit, - after = after, - before = before - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + params <- list(limit = limit, after = after, before = before) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items } @@ -51,7 +52,8 @@ get_my_recently_played <- function(limit = 20, after = NULL, before = NULL, auth get_my_devices <- function(authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/devices' - res <- tinyoauth::oauth_request(authorization, base_url, "GET", flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + flatten = TRUE) return(res$devices) } @@ -64,10 +66,12 @@ get_my_devices <- function(authorization = get_spotify_authorization_code()) { #' Returns a list containing user playback information. See the official Spotify Web API \href{https://developer.spotify.com/documentation/web-api}{documentation} for more information. #' @export -get_my_current_playback <- function(market = NULL, authorization = get_spotify_authorization_code()) { +get_my_current_playback <- function(market = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player' params <- list(market = market) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) return(res) } @@ -80,10 +84,12 @@ get_my_current_playback <- function(market = NULL, authorization = get_spotify_a #' No return value. #' @export -pause_my_playback <- function(device_id = NULL, authorization = get_spotify_authorization_code()) { +pause_my_playback <- function(device_id = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/pause' params <- list(device_id = device_id) - res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", + query = params, flatten = TRUE) return(res) } @@ -99,14 +105,13 @@ pause_my_playback <- function(device_id = NULL, authorization = get_spotify_auth #' No return value. #' @export -toggle_my_shuffle <- function(state, device_id = NULL, authorization = get_spotify_authorization_code()) { +toggle_my_shuffle <- function(state, device_id = NULL, + authorization = get_spotify_authorization_code()) { stopifnot(is.logical(state)) base_url <- 'https://api.spotify.com/v1/me/player/shuffle' - params <- list( - state = state, - device_id = device_id - ) - res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) + params <- list(state = state, device_id = device_id) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", + query = params, flatten = TRUE) return(res) } @@ -124,15 +129,14 @@ toggle_my_shuffle <- function(state, device_id = NULL, authorization = get_spoti #' No return value. #' @export -set_my_repeat_mode <- function(state, device_id = NULL, authorization = get_spotify_authorization_code()) { +set_my_repeat_mode <- function(state, device_id = NULL, + authorization = get_spotify_authorization_code()) { stopifnot(state %in% c('track', 'context', 'off')) stopifnot(length(state) == 1) base_url <- 'https://api.spotify.com/v1/me/player/repeat' - params <- list( - state = state, - device_id = device_id - ) - res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) + params <- list(state = state, device_id = device_id) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", + query = params, flatten = TRUE) return(res) } @@ -146,16 +150,15 @@ set_my_repeat_mode <- function(state, device_id = NULL, authorization = get_spot #' No return value. #' @export -set_my_volume <- function(volume_percent, device_id = NULL, authorization = get_spotify_authorization_code()) { +set_my_volume <- function(volume_percent, device_id = NULL, + authorization = get_spotify_authorization_code()) { stopifnot(is.numeric(volume_percent)) stopifnot(volume %in% seq(0, 100)) stopifnot(length(volume) == 1) base_url <- 'https://api.spotify.com/v1/me/player/volume' - params <- list( - volume_percent = volume_percent, - device_id = device_id - ) - res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) + params <- list(volume_percent = volume_percent, device_id = device_id) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", + query = params, flatten = TRUE) return(res) } @@ -168,12 +171,12 @@ set_my_volume <- function(volume_percent, device_id = NULL, authorization = get_ #' No return value. #' @export -skip_my_playback <- function(device_id = NULL, authorization = get_spotify_authorization_code()) { +skip_my_playback <- function(device_id = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/next' - params <- list( - device_id = device_id - ) - res <- tinyoauth::oauth_request(authorization, base_url, "POST", query = params, flatten = TRUE) + params <- list(device_id = device_id) + res <- tinyoauth::oauth_request(authorization, base_url, "POST", + query = params, flatten = TRUE) return(res) } @@ -186,12 +189,12 @@ skip_my_playback <- function(device_id = NULL, authorization = get_spotify_autho #' No return value. #' @export -skip_my_playback_previous <- function(device_id = NULL, authorization = get_spotify_authorization_code()) { +skip_my_playback_previous <- function(device_id = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/previous' - params <- list( - device_id = device_id - ) - res <- tinyoauth::oauth_request(authorization, base_url, "POST", query = params, flatten = TRUE) + params <- list(device_id = device_id) + res <- tinyoauth::oauth_request(authorization, base_url, "POST", + query = params, flatten = TRUE) return(res) } @@ -210,17 +213,13 @@ skip_my_playback_previous <- function(device_id = NULL, authorization = get_spot #' No return value. #' @export -start_my_playback <- function(device_id = NULL, context_uri = NULL, uris = NULL, offset = NULL, position_ms = NULL, authorization = get_spotify_authorization_code()) { +start_my_playback <- function(device_id = NULL, context_uri = NULL, + uris = NULL, offset = NULL, position_ms = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/play' - query_params = list( - device_id = device_id - ) - body_params <- list( - context_uri = context_uri, - uris = uris, - offset = offset, - position_ms = position_ms - ) + query_params <- list(device_id = device_id) + body_params <- list(context_uri = context_uri, uris = uris, + offset = offset, position_ms = position_ms) res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = query_params, body = body_params, flatten = TRUE) return(res) } @@ -238,13 +237,12 @@ start_my_playback <- function(device_id = NULL, context_uri = NULL, uris = NULL, #' No return value. #' @export -transfer_my_playback <- function(device_ids, play = FALSE, authorization = get_spotify_authorization_code()) { +transfer_my_playback <- function(device_ids, play = FALSE, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/player/' - params <- list( - device_ids = list(device_ids), - play = play - ) - res <- tinyoauth::oauth_request(authorization, base_url, "PUT", body = params, flatten = TRUE) + params <- list(device_ids = list(device_ids), play = play) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", + body = params, flatten = TRUE) return(res) } @@ -258,17 +256,16 @@ transfer_my_playback <- function(device_ids, play = FALSE, authorization = get_s #' No return value. #' @export -seek_to_position <- function(position_ms, device_id = NULL, authorization = get_spotify_authorization_code()) { - +seek_to_position <- function(position_ms, device_id = NULL, + authorization = get_spotify_authorization_code()) { stopifnot(is.numeric(position_ms)) stopifnot(position_ms > 0) stopifnot(round(position_ms) == position_ms) base_url <- 'https://api.spotify.com/v1/me/player/seek' - params <- list( - position_ms = position_ms, - device_id = device_id - ) - res <- tinyoauth::oauth_request(authorization, base_url, "PUT", query = params, flatten = TRUE) + params <- list(position_ms = position_ms, device_id = device_id) + res <- tinyoauth::oauth_request(authorization, base_url, "PUT", + query = params, flatten = TRUE) return(res) } + diff --git a/R/playlists.R b/R/playlists.R index fa0eb9d..149ad04 100644 --- a/R/playlists.R +++ b/R/playlists.R @@ -13,12 +13,14 @@ #' No return value. Items added to playlist. #' @export -add_items_to_playlist <- function(playlist_id, uris, position = NULL, market = "US", authorization = get_spotify_authorization_code()) { - +add_items_to_playlist <- function(playlist_id, uris, position = NULL, + market = "US", + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' - if(is.null(position)){ - url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ","), "&market=", market) + if (is.null(position)) { + url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", + paste0(uris, collapse = ","), "&market=", market) } else { url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ","), "&market=", market, "&position=", position) } @@ -41,17 +43,16 @@ add_items_to_playlist <- function(playlist_id, uris, position = NULL, market = " #' No return value. Tracks added to playlist. #' @export -add_tracks_to_playlist <- function(playlist_id, uris, position = NULL, market = NULL, authorization = get_spotify_authorization_code()) { +add_tracks_to_playlist <- function(playlist_id, uris, position = NULL, + market = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' - url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ",")) - params <- list( - market = market, - position = position - ) + url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", + paste0(uris, collapse = ",")) + params <- list(market = market, position = position) tinyoauth::oauth_request(authorization, url, "POST", body = params, flatten = TRUE) } - #' Change a playlist’s name and public/private state. (The user must, of course, own the playlist.) #' #' @param playlist_id Required. The \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify ID} for the playlist. @@ -65,15 +66,13 @@ add_tracks_to_playlist <- function(playlist_id, uris, position = NULL, market = #' No return value. Playlist details changed. #' @export -change_playlist_details <- function(playlist_id, name = NULL, public = NULL, collaborative = NULL, description = NULL, authorization = get_spotify_authorization_code()) { +change_playlist_details <- function(playlist_id, name = NULL, public = NULL, + collaborative = NULL, description = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id) - params <- list( - name = name, - public = public, - collaborative = collaborative, - description = description - ) + params <- list(name = name, public = public, + collaborative = collaborative, description = description) tinyoauth::oauth_request(authorization, url, "PUT", body = params, flatten = TRUE) } @@ -90,15 +89,13 @@ change_playlist_details <- function(playlist_id, name = NULL, public = NULL, col #' Returns a list containing playlist information. #' @export -create_playlist <- function(user_id, name, public = TRUE, collaborative = FALSE, description = NULL, authorization = get_spotify_authorization_code()) { +create_playlist <- function(user_id, name, public = TRUE, + collaborative = FALSE, description = NULL, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/users' url <- paste0(base_url, "/", user_id, "/playlists") - params <- list( - name = name, - public = public, - collaborative = collaborative, - description = description - ) + params <- list(name = name, public = public, + collaborative = collaborative, description = description) tinyoauth::oauth_request(authorization, url, "POST", body = params, flatten = TRUE) } @@ -120,13 +117,13 @@ create_playlist <- function(user_id, name, public = TRUE, collaborative = FALSE, #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_my_playlists <- function(limit = 20, offset = 0, authorization = get_spotify_authorization_code(), include_meta_info = FALSE) { +get_my_playlists <- function(limit = 20, offset = 0, + authorization = get_spotify_authorization_code(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/me/playlists' - params <- list( - limit = limit, - offset = offset - ) - res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) + params <- list(limit = limit, offset = offset) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items @@ -152,14 +149,14 @@ get_my_playlists <- function(limit = 20, offset = 0, authorization = get_spotify #' @return #' Returns a data frame of results containing user playlist information. See the official \href{https://developer.spotify.com/documentation/web-api}{Spotify Web API documentation} for more information. #' @export -get_user_playlists <- function(user_id, limit = 20, offset = 0, authorization = get_spotify_authorization_code(), include_meta_info = FALSE) { +get_user_playlists <- function(user_id, limit = 20, offset = 0, + authorization = get_spotify_authorization_code(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/users' url <- paste0(base_url, "/", user_id, "/playlists") - params <- list( - limit = limit, - offset = offset - ) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + params <- list(limit = limit, offset = offset) + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) if (!include_meta_info) { res <- res$items } @@ -175,7 +172,8 @@ get_user_playlists <- function(user_id, limit = 20, offset = 0, authorization = #' Returns a data frame of results containing playlist cover image information. See the official \href{https://developer.spotify.com/documentation/web-api}{Spotify Web API Documentation} for more information. #' @export -get_playlist_cover_image <- function(playlist_id, authorization = get_spotify_authorization_code()) { +get_playlist_cover_image <- function(playlist_id, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/images") tinyoauth::oauth_request(authorization, url, "GET", flatten = TRUE) @@ -197,14 +195,13 @@ get_playlist_cover_image <- function(playlist_id, authorization = get_spotify_au #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_playlist <- function(playlist_id, fields = NULL, market = NULL, authorization = get_spotify_access_token()) { +get_playlist <- function(playlist_id, fields = NULL, market = NULL, + authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id) - params <- list( - fields = paste(fields, collapse = ','), - market = market - ) - tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + params <- list(fields = paste(fields, collapse = ','), market = market) + tinyoauth::oauth_request(authorization, url, "GET", query = params, + flatten = TRUE) } #' Get full details of the items of a playlist owned by a Spotify user. @@ -230,15 +227,19 @@ get_playlist <- function(playlist_id, fields = NULL, market = NULL, authorizatio #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_playlist_items <- function(playlist_id, fields = NULL, limit = 100, offset = 0, market = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_playlist_items <- function(playlist_id, fields = NULL, limit = 100, + offset = 0, market = NULL, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/tracks") params <- list( - fields = ifelse(!is.null(fields), paste0('items(', paste0(fields, collapse = ','), ')'), ''), - limit = limit, - offset = offset, - market = market + fields = ifelse(!is.null(fields), + paste0('items(', paste0(fields, collapse = ','), ')'), + ''), + limit = limit, + offset = offset, + market = market ) res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) @@ -271,15 +272,19 @@ get_playlist_items <- function(playlist_id, fields = NULL, limit = 100, offset = #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_playlist_tracks <- function(playlist_id, fields = NULL, limit = 100, offset = 0, market = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +get_playlist_tracks <- function(playlist_id, fields = NULL, limit = 100, + offset = 0, market = NULL, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/tracks") params <- list( - fields = ifelse(!is.null(fields), paste0('items(', paste0(fields, collapse = ','), ')'), ''), - limit = limit, - offset = offset, - market = market + fields = ifelse(!is.null(fields), + paste0('items(', paste0(fields, collapse = ','), ')'), + ''), + limit = limit, + offset = offset, + market = market ) res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) @@ -300,7 +305,8 @@ get_playlist_tracks <- function(playlist_id, fields = NULL, limit = 100, offset #' @return #' No return value. Tracks are removed from playlist. #' @export -remove_tracks_from_playlist <- function(playlist_id, uris, authorization = get_spotify_authorization_code()) { +remove_tracks_from_playlist <- function(playlist_id, uris, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/tracks/") @@ -308,7 +314,8 @@ remove_tracks_from_playlist <- function(playlist_id, uris, authorization = get_s uris_list <- lapply(uris, function(x) list(uri = x)) params <- list(tracks = uris_list) - tinyoauth::oauth_request(authorization, url, "DELETE", body = params, flatten = TRUE) + tinyoauth::oauth_request(authorization, url, "DELETE", body = params, + flatten = TRUE) } #' Add the latest episode of a podcast to a user’s playlist. @@ -324,12 +331,16 @@ remove_tracks_from_playlist <- function(playlist_id, uris, authorization = get_s #' @return #' No return value. Tracks are added to playlist. #' @export -add_latest_to_playlist <- function(playlist_id, uri, position = NULL, market = "US", authorization = get_spotify_authorization_code()) { +add_latest_to_playlist <- function(playlist_id, uri, position = NULL, + market = "US", + authorization = get_spotify_authorization_code()) { id <- strsplit(uri, ":")[[1]][3] episodes <- get_shows_episodes(id = id) uris <- episodes$items$uri[1] - if(length(uris) > 0){ - add_items_to_playlist(playlist_id = playlist_id, uris = uris, position = position, market = market, authorization = authorization) + if (length(uris) > 0) { + add_items_to_playlist(playlist_id = playlist_id, uris = uris, + position = position, market = market, + authorization = authorization) } } @@ -345,9 +356,11 @@ add_latest_to_playlist <- function(playlist_id, uri, position = NULL, market = " #' No return value. Tracks are added or reordered on playlist. #' @export -reorder_replace_playlist_items <- function(playlist_id, uris, authorization = get_spotify_authorization_code()) { +reorder_replace_playlist_items <- function(playlist_id, uris, + authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/playlists' url <- paste0(base_url, "/", playlist_id, "/tracks?uris=", paste0(uris, collapse = ",")) tinyoauth::oauth_request(authorization, url, "PUT", flatten = TRUE) } + diff --git a/R/search.R b/R/search.R index 9b8a740..25ca14f 100644 --- a/R/search.R +++ b/R/search.R @@ -40,8 +40,12 @@ #' \dontrun{ #' search_spotify('radiohead', 'artist') #' } -search_spotify <- function(q, type = c('album', 'artist', 'playlist', 'track'), market = NULL, limit = 20, offset = 0, include_external = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { - +search_spotify <- function(q, + type = c('album', 'artist', 'playlist', 'track'), + market = NULL, limit = 20, offset = 0, + include_external = NULL, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/search' if (!is.character(q)) { @@ -68,16 +72,11 @@ search_spotify <- function(q, type = c('album', 'artist', 'playlist', 'track'), } } - params <- list( - q = q, - type = paste(type, collapse = ','), - market = market, - limit = limit, - offset = offset, - include_external = include_external - ) + params <- list(q = q, type = paste(type, collapse = ','), + market = market, limit = limit, offset = offset, + include_external = include_external) res <- tinyoauth::oauth_request(authorization, base_url, "GET", query = params, flatten = TRUE) - return(res) } + diff --git a/R/shows.R b/R/shows.R index a82df3b..1c1dbda 100644 --- a/R/shows.R +++ b/R/shows.R @@ -10,17 +10,16 @@ #' Returns a data frame of results containing show data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_show <- function(id, market = "US", authorization = get_spotify_access_token()){ - base_url <- 'https://api.spotify.com/v1/shows' - - params <- list( - market = market - ) - url <- paste0(base_url, "/", id) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - - - return(res) +get_show <- function(id, market = "US", + authorization = get_spotify_access_token()) { + base_url <- 'https://api.spotify.com/v1/shows' + + params <- list(market = market) + url <- paste0(base_url, "/", id) + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) + + return(res) } #' Get Spotify catalog information for a single show identified by their unique Spotify ID. @@ -35,18 +34,16 @@ get_show <- function(id, market = "US", authorization = get_spotify_access_token #' Returns a data frame of results containing show data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_shows <- function(ids, market = "US", authorization = get_spotify_access_token()){ - base_url <- 'https://api.spotify.com/v1/shows' - - params <- list( - ids = paste(ids, collapse = ','), - market = market - ) - url <- paste0(base_url) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - - - return(res) +get_shows <- function(ids, market = "US", + authorization = get_spotify_access_token()) { + base_url <- 'https://api.spotify.com/v1/shows' + + params <- list(ids = paste(ids, collapse = ','), market = market) + url <- paste0(base_url) + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) + + return(res) } #' Get Spotify catalog information for a show's episodes identified by their unique Spotify ID. @@ -61,18 +58,16 @@ get_shows <- function(ids, market = "US", authorization = get_spotify_access_tok #' Returns a data frame of results containing the episode data for a show. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_shows_episodes <- function(id, market = "US", authorization = get_spotify_access_token()) { +get_shows_episodes <- function(id, market = "US", + authorization = get_spotify_access_token()) { + base_url <- 'https://api.spotify.com/v1/shows' - base_url <- 'https://api.spotify.com/v1/shows' + params <- list(market = market) + url <- paste0(base_url, "/", id, "/episodes?market=", market) + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) - params <- list( - market = market - ) - url <- paste0(base_url, "/", id, "/episodes?market=", market) - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) - - - return(res) + return(res) } #' Get Spotify uri information for a show's latest episodes identified by their unique Spotify ID. @@ -87,8 +82,10 @@ get_shows_episodes <- function(id, market = "US", authorization = get_spotify_ac #' Returns a string containing the latest episode data for a show. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_latest_episode <- function(id, market = "US", authorization = get_spotify_authorization_code()){ - episodes <- get_shows_episodes(id = id) - uri <- episodes$items$uri[1] - uri +get_latest_episode <- function(id, market = "US", + authorization = get_spotify_authorization_code()) { + episodes <- get_shows_episodes(id = id) + uri <- episodes$items$uri[1] + uri } + diff --git a/R/tinyspotifyr.R b/R/tinyspotifyr.R index 66c0c1f..ee288a6 100644 --- a/R/tinyspotifyr.R +++ b/R/tinyspotifyr.R @@ -6,69 +6,27 @@ #' @keywords internal "_PACKAGE" -globalVars <- c( -"album_name", -"album_name_", -"album_release_year_", -"album_rank", -"album_release_date", -"album_release_year", -"album_uri", -"analysis_url", -"base_album", -"base_album_name", -"key", -"name", -"num_albums", -"num_base_albums", -"playlist_img", -"playlist_name", -"playlist_uri", -"preview_url", -"href", -"album_id", -"images", -"release_date", -"release_date_precision", -"track_href", -"track_uri", -"type", -"uri", -"album_name_lower", -"album_type", -"possible_album", -"possible_lyrics", -"disco_audio_feats", -"data", -"future_map_df", -"map_chr", -"is_collaboration", -"key_name", -"mode_name", -"lyrics", -"na.omit", -"parse_playlist_to_df", -"release_date", -"selected_artist", -"track_n", -"track_title", -"track_url", -"volume", -"primary_color", -"track_id", -"track.id", -"playlist_id", -"playlist_owner_name", -"playlist_owner_id", -"added_at", -"artist_names", -"artists", -"available_markets", -"duration_ms", -"genius_album", -"popularity", -"track_number", -".") +globalVars <- c("album_name", "album_name_", "album_release_year_", + "album_rank", "album_release_date", "album_release_year", + "album_uri", "analysis_url", "base_album", + "base_album_name", "key", "name", "num_albums", + "num_base_albums", "playlist_img", "playlist_name", + "playlist_uri", "preview_url", "href", "album_id", + "images", "release_date", "release_date_precision", + "track_href", "track_uri", "type", "uri", + "album_name_lower", "album_type", "possible_album", + "possible_lyrics", "disco_audio_feats", "data", + "future_map_df", "map_chr", "is_collaboration", "key_name", + "mode_name", "lyrics", "na.omit", "parse_playlist_to_df", + "release_date", "selected_artist", "track_n", "track_title", + "track_url", "volume", "primary_color", "track_id", + "track.id", "playlist_id", "playlist_owner_name", + "playlist_owner_id", "added_at", "artist_names", "artists", + "available_markets", "duration_ms", "genius_album", + "popularity", "track_number", ".") ## quiets concerns of R CMD check re: the .'s that appear in pipelines -if(getRversion() >= "2.15.1") utils::globalVariables(globalVars) +if (getRversion() >= "2.15.1") { + utils::globalVariables(globalVars) +} + diff --git a/R/tracks.R b/R/tracks.R index edea81d..d2d8e37 100644 --- a/R/tracks.R +++ b/R/tracks.R @@ -6,7 +6,8 @@ #' Returns a data frame of results containing track audio analysis data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_track_audio_analysis <- function(id, authorization = get_spotify_access_token()) { +get_track_audio_analysis <- function(id, + authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/audio-analysis' url <- paste0(base_url, "/", id) tinyoauth::oauth_request(authorization, url, "GET", flatten = TRUE) @@ -23,10 +24,11 @@ get_track_audio_analysis <- function(id, authorization = get_spotify_access_toke #' Returns a data frame of results containing track audio features data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_track_audio_features <- function(ids, authorization = get_spotify_access_token()) { +get_track_audio_features <- function(ids, + authorization = get_spotify_access_token()) { .Deprecated(msg = paste("get_track_audio_features(): Spotify restricted", - "GET /v1/audio-features (HTTP 403) in November 2024; it no longer", - "returns data for apps without prior access.")) + "GET /v1/audio-features (HTTP 403) in November 2024; it no longer", + "returns data for apps without prior access.")) stopifnot(length(ids) <= 100) base_url <- 'https://api.spotify.com/v1/audio-features' params <- list(ids = paste0(ids, collapse = ',')) @@ -45,7 +47,8 @@ get_track_audio_features <- function(ids, authorization = get_spotify_access_tok #' Returns a data frame of results containing track data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_track <- function(id, market = NULL, authorization = get_spotify_access_token()) { +get_track <- function(id, market = NULL, + authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/tracks' if (!is.null(market)) { if (!grepl('^[[:alpha:]]{2}$', market)) { @@ -68,7 +71,9 @@ get_track <- function(id, market = NULL, authorization = get_spotify_access_toke #' Returns a data frame of results containing track data. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_tracks <- function(ids, market = NULL, authorization = get_spotify_access_token(), include_meta_info = FALSE) { +get_tracks <- function(ids, market = NULL, + authorization = get_spotify_access_token(), + include_meta_info = FALSE) { base_url <- 'https://api.spotify.com/v1/tracks' if (!is.null(market)) { if (!grepl('^[[:alpha:]]{2}$', market)) { @@ -83,3 +88,4 @@ get_tracks <- function(ids, market = NULL, authorization = get_spotify_access_to } res } + diff --git a/R/users_profile.R b/R/users_profile.R index fa2c366..1d17a6f 100644 --- a/R/users_profile.R +++ b/R/users_profile.R @@ -8,9 +8,10 @@ get_my_profile <- function(authorization = get_spotify_authorization_code()) { base_url <- 'https://api.spotify.com/v1/me/' - res <- tinyoauth::oauth_request(authorization, base_url, "GET", flatten = TRUE) + res <- tinyoauth::oauth_request(authorization, base_url, "GET", + flatten = TRUE) res <- t(unlist(res)) - + return(res) } @@ -22,12 +23,15 @@ get_my_profile <- function(authorization = get_spotify_authorization_code()) { #' Returns a data frame of results containing user profile information. See \url{https://developer.spotify.com/documentation/web-api} for more information. #' @export -get_user_profile <- function(user_id, authorization = get_spotify_access_token()) { +get_user_profile <- function(user_id, + authorization = get_spotify_access_token()) { base_url <- 'https://api.spotify.com/v1/users' url <- paste0(base_url, "/", user_id) - params = list() - res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE) + params <- list() + res <- tinyoauth::oauth_request(authorization, url, "GET", + query = params, flatten = TRUE) res <- t(unlist(res)) return(res) } + diff --git a/R/utils.R b/R/utils.R index 58ff286..d405fe1 100644 --- a/R/utils.R +++ b/R/utils.R @@ -7,10 +7,10 @@ #' @export is_uri <- function(s) { nchar(s) == 22 & - !grepl(' ', s) & - grepl('[[:digit:]]', s) & - grepl('[[:lower:]]', s) & - grepl('[[:upper:]]', s) + !grepl(' ', s) & + grepl('[[:digit:]]', s) & + grepl('[[:lower:]]', s) & + grepl('[[:upper:]]', s) } #' Pitch class notation lookup @@ -19,7 +19,8 @@ is_uri <- function(s) { #' @return #' Returns a character vector. #' @export -pitch_class_lookup <- c('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B') +pitch_class_lookup <- c('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', + 'G#', 'A', 'A#', 'B') #' Verify API result #' @@ -41,14 +42,15 @@ verify_result <- function(res) { #' Returns a character vector. #' @export scopes <- c("ugc-image-upload", "user-read-recently-played", - "user-read-playback-state", "user-top-read", "app-remote-control", - "playlist-modify-public", "user-modify-playback-state", - "playlist-modify-private", "user-follow-modify", - "user-read-currently-playing", "user-follow-read", - "user-library-modify", "user-read-playback-position", - "playlist-read-private", "user-read-email", "user-read-private", - "user-library-read", "playlist-read-collaborative", "streaming") - + "user-read-playback-state", "user-top-read", + "app-remote-control", "playlist-modify-public", + "user-modify-playback-state", "playlist-modify-private", + "user-follow-modify", "user-read-currently-playing", + "user-follow-read", "user-library-modify", + "user-read-playback-position", "playlist-read-private", + "user-read-email", "user-read-private", "user-library-read", + "playlist-read-collaborative", "streaming") + # xml2::read_html("https://developer.spotify.com/documentation/general/guides/scopes/") %>% # html_nodes('code') %>% # html_text() %>% @@ -62,9 +64,9 @@ scopes <- c("ugc-image-upload", "user-read-recently-played", # #' @param album_release_year_col String of field name containing album release year # #' @export # dedupe_album_names <- function(df, album_name_col = 'album_name', album_release_year_col = 'album_release_year') { -# +# # album_dupe_regex <- '(deluxe|international|anniversary|version|edition|remaster|re-master|live|mono|stereo)' -# +# # base_album_names <- df %>% # mutate_('album_name_' = album_name_col, # 'album_release_year_' = album_release_year_col) %>% @@ -81,9 +83,10 @@ scopes <- c("ugc-image-upload", "user-read-recently-played", # ungroup() %>% # dplyr::filter((base_album == 1) |((num_base_albums == 0 | num_base_albums > 1) & row_number() == 1)) %>% # pull(album_name_) -# +# # df %>% # mutate_('album_name_' = album_name_col) %>% # filter(album_name_ %in% base_album_names) %>% # select(-album_name_) # } + From 2ec0f9f8a697513b0808605442a6da995b083996 Mon Sep 17 00:00:00 2001 From: TroyHernandez Date: Sat, 6 Jun 2026 22:58:33 -0500 Subject: [PATCH 4/5] Bump version to 0.2.3.1 --- DESCRIPTION | 2 +- NEWS.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 NEWS.md diff --git a/DESCRIPTION b/DESCRIPTION index cfb2491..c36e61c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: tinyspotifyr Title: Tinyverse R Wrapper for the 'Spotify' Web API -Version: 0.2.3 +Version: 0.2.3.1 Date: 2026-06-06 Authors@R: c(person("Troy", "Hernandez", email = "troy@cornball.ai", role = c("aut", "cre", "cph"), comment = c(ORCID = "0009-0005-4248-604X")), person("Charlie", "Thompson", email = "chuck@rcharlie.com", role = c("aut", "cph")), person("Josiah", "Parry", email = "josiah.parry@yahoo.com", role = "aut"), person("Donal", "Phipps", email = "donal.phipps@gmail.com", role = "aut"), person("Tom", "Wolff", email = "tom.wolff@duke.edu", role = "aut")) Description: An R wrapper for the 'Spotify' Web API diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..907cc29 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,5 @@ +# tinyspotifyr 0.2.3.1 + +* Replaced the httr backend with tinyoauth (curl + jsonlite + serverSocket); Imports trimmed to tinyoauth alone. Existing httr .httr-oauth caches carry over via oauth_import_httr() (no re-login). +* Fixed pre-existing get_artist() and get_album() bugs surfaced during the migration. + From 4ed8bb0b3ad54dac9a4924c240d7a2fa0857046e Mon Sep 17 00:00:00 2001 From: Troy Hernandez Date: Mon, 8 Jun 2026 11:10:51 -0500 Subject: [PATCH 5/5] Fix get_shows_episodes() sending market parameter twice (#7) * Fix get_shows_episodes() sending market twice market was baked into the URL (?market=) and ALSO passed via query=, so tinyoauth::oauth_request()'s paste0(url, '?', qs) produced '.../episodes?market=US?market=US'. Spotify parsed the market as 'US?market=US' and returned HTTP 400 'Invalid market parameter'. Build the path only and let oauth_request add the query, matching the other shows.R functions. * Bump version to 0.2.3.2 --- DESCRIPTION | 2 +- NEWS.md | 7 +++++++ R/shows.R | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index c36e61c..e33003a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: tinyspotifyr Title: Tinyverse R Wrapper for the 'Spotify' Web API -Version: 0.2.3.1 +Version: 0.2.3.2 Date: 2026-06-06 Authors@R: c(person("Troy", "Hernandez", email = "troy@cornball.ai", role = c("aut", "cre", "cph"), comment = c(ORCID = "0009-0005-4248-604X")), person("Charlie", "Thompson", email = "chuck@rcharlie.com", role = c("aut", "cph")), person("Josiah", "Parry", email = "josiah.parry@yahoo.com", role = "aut"), person("Donal", "Phipps", email = "donal.phipps@gmail.com", role = "aut"), person("Tom", "Wolff", email = "tom.wolff@duke.edu", role = "aut")) Description: An R wrapper for the 'Spotify' Web API diff --git a/NEWS.md b/NEWS.md index 907cc29..d3d737c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# tinyspotifyr 0.2.3.2 + +* Fixed `get_shows_episodes()` sending `market` twice (in the URL and via the + query), producing a malformed query and a Spotify "Invalid market parameter" + 400. Another migration leftover, like the get_artist()/get_album() fixes in + 0.2.3.1. + # tinyspotifyr 0.2.3.1 * Replaced the httr backend with tinyoauth (curl + jsonlite + serverSocket); Imports trimmed to tinyoauth alone. Existing httr .httr-oauth caches carry over via oauth_import_httr() (no re-login). diff --git a/R/shows.R b/R/shows.R index 1c1dbda..08ee733 100644 --- a/R/shows.R +++ b/R/shows.R @@ -63,7 +63,7 @@ get_shows_episodes <- function(id, market = "US", base_url <- 'https://api.spotify.com/v1/shows' params <- list(market = market) - url <- paste0(base_url, "/", id, "/episodes?market=", market) + url <- paste0(base_url, "/", id, "/episodes") res <- tinyoauth::oauth_request(authorization, url, "GET", query = params, flatten = TRUE)