Nothing
#' @title Get User Playlist
#'
#' @description Get a playlist owned by a Spotify user.
#'
#' @importFrom stringr str_glue
#' @importFrom purrr pluck map map_dfr
#' @importFrom dplyr bind_rows
#' @param playlist_id Required. The \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify ID} for the playlist.
#' @param fields Optional.
#' Filters for the query: a comma-separated list of the fields to return.
#' If omitted, all fields are returned. For example, to get just the playlist’s description
#' and URI: \cr
#' \code{fields = c("description", "uri")} \cr A dot separator can be used to specify non-reoccurring fields, while parentheses can be used to specify reoccurring fields within objects. For example, to get just the added date and user ID of the adder: \cr
#' \code{fields = "tracks.items(added_at,added_by.id)"} \cr Use multiple parentheses to drill down into nested objects, for example: \cr
#' \code{fields = "tracks.items(track(name,href,album(name,href)))"} \cr Fields can be excluded by prefixing them with an exclamation mark, for example: \cr
#' \code{fields = "tracks.items(track(name,href,album(!name,href)))"}
#' @param market Optional. \cr
#' An ISO 3166-1 alpha-2 country code or the string \code{"from_token"}.
#' Provide this parameter if you want to apply \href{https://developer.spotify.com/documentation/general/guides/track-relinking-guide/}{Track Relinking}
#' @param authorization Required. A valid access token from the Spotify Accounts service.
#' See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization guide} for more details. Both Public and Private playlists belonging to any user are retrievable on provision of a valid access token. Defaults to \code{spotifyr::get_spotify_access_token()}
#' @return
#' Returns a data frame of results containing user profile information.
#' See \url{https://developer.spotify.com/documentation/web-api/reference/users-profile/get-current-users-profile/} for more information.
#' @family playlist functions
#' @export
get_playlist <- function(playlist_id, fields = NULL,
market = NULL,
authorization = get_spotify_access_token()
) {
base_url <- 'https://api.spotify.com/v1/playlists'
url <- str_glue('{base_url}/{playlist_id}')
params <- list(
fields = paste(fields, collapse = ','),
market = market,
access_token = authorization
)
# stopping is built into query_playlist()
init_query <- query_playlist(url, params = params)
# identify how many pages there are
total_tracks <- pluck(init_query, "tracks", "total")
if (total_tracks > 100) {
n_pages <- total_tracks %/% 100
# identify pagination offsets
offsets <- seq(from = 1, to = n_pages) * 100
# create page urls
page_urls <- str_glue("{url}/tracks?offset={offsets}&limit=100")
# query api
other_pages <- map(page_urls, query_playlist, params)
# merge the song track results
all_items <- bind_rows(
pluck(init_query, "tracks", "items"),
map_dfr(other_pages, pluck, "items")
)
# overwrite init_query item results
init_query[["tracks"]][["items"]] <- all_items
}
#return init_query object
structure(init_query, class = c("playlist", "list"))
}
#' @title Get Details of User Playlist Tracks.
#'
#' @description Get full details of the tracks of a playlist owned by a Spotify user.
#' @param playlist_id Required.
#' The \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify ID} for the playlist.
#' @param fields Optional. Filters for the query: a comma-separated list of the fields
#' to return. If omitted, all fields are returned.
#' For example, to get just the playlist’s creation date and album information: \code{fields = c("added_at", "track.album")}. A dot separator can be used to specify non-reoccurring fields, while parentheses can be used to specify reoccurring fields within objects. For example, to get just the added date and user ID of the adder: \cr
#' \code{fields = "tracks.items(added_at,added_by.id)"}. Use multiple parentheses to drill down into nested objects, for example: \cr
#' \code{fields = "tracks.items(track(name,href,album(name,href)))"}. Fields can be excluded by prefixing them with an exclamation mark, for example: \cr
#' \code{fields = "tracks.items(track(name,href,album(!name,href)))"}.
#' @param limit Optional. \cr
#' Maximum number of tracks to return. \cr
#' Default: 100 \cr
#' Minimum: 1 \cr
#' Maximum: 100 \cr
#' @param offset Optional. \cr
#' The index of the first track to return. \cr
#' Default: 0 (the first object). \cr
#' @param market Optional. \cr
#' An ISO 3166-1 alpha-2 country code or the string \code{"from_token"}.
#' Provide this parameter if you want to apply
#' \href{https://developer.spotify.com/documentation/general/guides/track-relinking-guide/}{Track Relinking}
#' @param authorization Required. A valid access token from the Spotify Accounts service.
#' See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization guide} for more details. Both Public and Private playlists belonging to any user are retrievable on provision of a valid access token. Defaults to \code{spotifyr::get_spotify_access_token()}
#' @param include_meta_info Optional. Boolean indicating whether to include full result,
#' with meta information such as \code{"total"}, and \code{"limit"}.
#' Defaults to \code{FALSE}.
#' @return
#' Returns a data frame of results containing user profile information.
#' See \url{https://developer.spotify.com/documentation/web-api/reference/users-profile/get-current-users-profile/} for more information.
#' @family track functions
#' @export
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 <- str_glue('{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
)
res <- RETRY('GET', url, query = params, encode = 'json')
stop_for_status(res)
res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'), flatten = TRUE)
if (!include_meta_info) {
res <- res$items
}
return(res)
}
#' Get List of My Playlists
#'
#' Get a list of the playlists owned or followed by the current Spotify user.
#'
#' @param limit Optional. \cr
#' Maximum number of playlists to return. \cr
#' Default: 20 \cr
#' Minimum: 1 \cr
#' Maximum: 50 \cr
#' @param offset Optional. \cr
#' The index of the first playlist to return. \cr
#' Default: 0 (the first object). Maximum offset: 100,000. Use with \code{limit}
#' to get the next set of playlists.
#' @param authorization Required. A valid access token from the Spotify Accounts service.
#' See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization Guide} for more details. Defaults to \code{spotifyr::get_spotify_authorization_code()}. The access token must have been issued on behalf of the current user. \cr
#' Private playlists are only retrievable for the current user and requires the
#' \code{playlist-read-private} \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{scope} to have been authorized by the user. Note that this scope alone will not return collaborative playlists, even though they are always private. \cr
#' Collaborative playlists are only retrievable for the current user and requires the
#' \code{playlist-read-collaborative} \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{scope} to have been authorized by the user.
#' @param include_meta_info Optional. Boolean indicating whether to include full result,
#' with meta information such as \code{"total"}, and \code{"limit"}.
#' Defaults to \code{FALSE}.
#' @return
#' Returns a data frame of results containing user profile information.
#' See \url{https://developer.spotify.com/documentation/web-api/reference/users-profile/get-current-users-profile/} for more information.
#' @family playlist functions
#' @export
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 <- 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)
if (!include_meta_info) {
res <- res$items
}
res
}
#' Get List of User Playlists
#'
#' Get a list of the playlists owned or followed by a Spotify user.
#'
#' @param user_id Required.
#' The user's \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify user ID}.
#' @param limit Optional. \cr
#' Maximum number of playlists to return. \cr
#' Default: 20 \cr
#' Minimum: 1 \cr
#' Maximum: 50 \cr
#' @param offset Optional. \cr
#' The index of the first playlist to return. \cr
#' Default: 0 (the first object). Maximum offset: 100,000. Use with \code{limit}
#' to get the next set of playlists.
#' @param authorization Required. A valid access token from the Spotify Accounts service.
#' See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization Guide} for more details. Defaults to \code{spotifyr::get_spotify_authorization_code()}. The access token must have been issued on behalf of the current user. \cr
#' Private playlists are only retrievable for the current user and requires the
#' \code{playlist-read-private} \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{scope} to have been authorized by the user. Note that this scope alone will not return collaborative playlists, even though they are always private. \cr
#' Collaborative playlists are only retrievable for the current user and requires the
#' \code{playlist-read-collaborative}
#' \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{scope} to have been authorized by the user.
#' @param include_meta_info Optional. Boolean indicating whether to include full result,
#' with meta information such as \code{"total"}, and \code{"limit"}.
#' Defaults to \code{FALSE}.
#' @return
#' Returns a data frame of results containing user playlist information.
#' See the official \href{https://developer.spotify.com/documentation/web-api/reference/playlists/get-list-users-playlists/}{Spotify Web API documentation} for more information.
#' @family playlist functions
#' @export
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 <- str_glue('{base_url}/{user_id}/playlists')
params <- list(
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)
if (!include_meta_info) {
res <- res$items
}
res
}
#' Get Image Associated with Playlist
#'
#' Get the current image associated with a specific playlist.
#'
#' @param playlist_id Required. The \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify ID} for the playlist.
#' @param authorization Required. A valid access token from the Spotify Accounts service.
#' See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization Guide} for more details. Defaults to \code{spotifyr::get_spotify_authorization_code()}. The access token must have been issued on behalf of the current user. \cr
#' Current playlist image for both Public and Private playlists of any user are retrievable on
#' provision of a valid access token.
#' @return
#' Returns a data frame of results containing playlist cover image information.
#' See the official
#' \href{https://developer.spotify.com/documentation/web-api/reference/playlists/get-playlist-cover/}{Spotify Web API Documentation} for more information.
#' @export
get_playlist_cover_image <- function(playlist_id,
authorization = get_spotify_authorization_code()
) {
base_url <- 'https://api.spotify.com/v1/playlists'
url <- str_glue('{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)
res
}
#' Create Playlist for User
#'
#' Create a playlist for a Spotify user.
#' The playlist will be empty until you add tracks.
#'
#' @param user_id Required. The user's \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify user ID}.
#' @param name Required. String containing the name for the new playlist, for example \code{"Your Coolest Playlist"}. This name does not need to be unique; a user may have several playlists with the same name.
#' @param public Optional. Boolean. Defaults to \code{TRUE}. If \code{TRUE} the playlist will be public. If \code{FALSE} it will be private. To be able to create private playlists, the user must have granted the \code{playlist-modify-private} \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{scope}
#' @param collaborative Optional. Boolean. Defaults to \code{FALSE}. If \code{TRUE} the playlist will be collaborative. Note that to create a collaborative playlist you must also set \code{public} to \code{FALES}. To create collaborative playlists you must have granted \code{playlist-modify-private} and \code{playlist-modify-public} \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{scopes}.
#' @param description Optional. String containing the playlist description as displayed in Spotify Clients and in the Web API.
#' @param authorization Required. A valid access token from the Spotify Accounts service. See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization Guide} for more details. Defaults to \code{spotifyr::get_spotify_authorization_code()}. The access token must have been issued on behalf of the current user. \cr
#' Creating a public playlist for a user requires authorization of the \code{playlist-modify-public} scope; creating a private playlist requires the \code{playlist-modify-private} scope. See \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{Using Scopes}.
#' @return The response from the Spotify Web API on the \code{POST} request, with a meaningful
#' error message if the operation was not successful.
#' @family playlist functions
#' @export
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 <- str_glue('{base_url}/{user_id}/playlists')
params <- list(
name = name,
public = public,
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)
res
}
#' Add Tracks to User’s Playlist
#'
#' Add one or more tracks 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.
#' @param uris Optional. A character vector of
#' \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify track URIs} to add.
#' For example: \cr
#' uris = c("61H97kuKIpi6kJQRnUEIlh", "2q6vlgBJ432KeZZNt2ZZBV")\cr
#' A maximum of 100 tracks can be added in one request.
#' The uris will be formed as
#' uris = c("spotify%3Atrack%3A61H97kuKIpi6kJQRnUEIlh", "spotify%3Atrack%3A2q6vlgBJ432KeZZNt2ZZBV").
#' If you have the \code{"spotify:track:"} prefix in your vector it will
#' not be duplicated, otherwise it will be added.
#' @param position Optional. Integer indicating the position to insert the tracks,
#' a zero-based index. For example, to insert the tracks in the first position:
#' \code{position = 0}; to insert the tracks in the third position:
#' \code{position = 2}. If omitted, the tracks will be appended to the playlist.
#' Tracks are added in the order they are listed in the query string or request body.
#' @param authorization Required. A valid access token from the Spotify Accounts service.
#' See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization Guide} for more details. Defaults to \code{spotifyr::get_spotify_authorization_code()}.
#' The access token must have been issued on behalf of the current user. \cr
#' Adding tracks to the current user’s public playlists requires authorization of the
#' \code{playlist-modify-public} scope; adding tracks to the current user’s private
#' playlist (including collaborative playlists) requires the \code{playlist-modify-private} scope. See \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{Using Scopes}.
#' @return The response from the Spotify Web API on the
#' \code{POST} request, with a meaningful error message if the operation was not successful.
#' @family playlist functions
#' @export
add_tracks_to_playlist <- function(playlist_id,
uris,
position = NULL,
authorization = get_spotify_authorization_code()
) {
uris <- purrr::map_chr(uris, ~ifelse(stringr::str_detect(.x, "\\:"), .x, paste0("spotify:track:", .x)))
base_url <- 'https://api.spotify.com/v1/playlists'
url <- str_glue('{base_url}/{playlist_id}/tracks')
params <- list(
position = position,
uris = uris
)
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)
res
}
#' Remove Tracks from User’s Playlist
#'
#' Remove one or more tracks from 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.
#' @param uris Optional. A character vector of \href{https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids}{Spotify track URIs} to add. For example \cr
#' \code{uris = "spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "spotify:track:1301WleyT98MSxVHPZCA6M"} \cr
#' A maximum of 100 tracks can be removed in one request.
#' @param authorization Required. A valid access token from the Spotify Accounts service.
#' See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization Guide} for more details. Defaults to \code{spotifyr::get_spotify_authorization_code()}. The access token must have been issued on behalf of the current user. \cr
#' Removing tracks to the current user’s public playlists requires authorization of the
#' \code{playlist-modify-public} scope; removing tracks from the current user’s private
#' playlist (including collaborative playlists) requires the \code{playlist-modify-private}
#' scope. See \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{Using Scopes}.
#' @family playlist functions
#' @return The response from the Spotify Web API on the
#' \code{DELETE} request, with a meaningful error message if the operation was not successful.
#' @export
remove_tracks_from_playlist <- function(playlist_id,
uris,
authorization = get_spotify_authorization_code()) {
base_url <- 'https://api.spotify.com/v1/playlists'
url <- str_glue('{base_url}/{playlist_id}/tracks/')
playlist_id <- "0yyGrQtW5Nm5we8dHcNbgj"
# For DELETE request params URIs should be put in body
uris_list <- lapply(uris, function(x) list(uri = x))
params <- toJSON(list(tracks = uris_list), auto_unbox = T)
res <- RETRY('DELETE', url, body = params,
config(token = authorization),
encode = 'json')
stop_for_status(res)
res <- fromJSON(content(res, as = 'text', encoding = 'UTF-8'),
flatten = TRUE)
res
}
#' 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.
#' @param name Optional String containing the name for the new playlist, for example \code{"Your Coolest Playlist"}. This name does not need to be unique; a user may have several playlists with the same name.
#' @param public Optional. Boolean. If \code{TRUE} the playlist will be public. If \code{FALSE} it will be private.
#' @param collaborative Optional. Boolean. If \code{TRUE} the playlist will become collaborative and other users will be able to modify the playlist in their Spotify client.Note: you can only set \code{collaborative} to \code{TRUE} on non-public playlists.
#' @param description Optional. String containing the playlist description as displayed in Spotify Clients and in the Web API.
#' @param authorization Required. A valid access token from the Spotify Accounts service. See the \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/}{Web API authorization Guide} for more details. Defaults to \code{spotifyr::get_spotify_authorization_code()}. The access token must have been issued on behalf of the current user. \cr
#' Changing a public playlist for a user requires authorization of the \code{playlist-modify-public} scope; changing a private playlist requires the \code{playlist-modify-private} scope. See \href{https://developer.spotify.com/documentation/general/guides/authorization-guide/#list-of-scopes}{Using Scopes}.
#' @family playlist functions
#' @return The response from the Spotify Web API on the
#' \code{PUT} request, with a meaningful error message if the operation was not successful.
#' @export
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 <- str_glue('{base_url}/{playlist_id}')
params <- list(
name = name,
public = public,
collaborative = collaborative,
description = description
)
res <- RETRY('PUT', url,
body = params,
config(token = authorization),
encode = 'json')
stop_for_status(res)
res
}
#' Tidy a Playlist
#'
#' \code{\link{tidy}} extracts and tidies the data frame containing track level
#' information that is returned from \code{\link{get_playlist}} as a tibble.
#'
#' @param x A playlist object generated from
#' @param ... Generic arguments to be passed
#' @examples
#' \dontrun{
#' fall <- get_playlist("4GSV6uJzlbtTCPJhnVU1o8")
#' tidy(fall)
#'
#' print(fall)
#' }
#'
#' @importFrom purrr pluck map
#' @importFrom stringr str_remove
#' @importFrom dplyr as_tibble select mutate
#' @importFrom janitor make_clean_names
#' @family playlist functions
#' @return Return or print a tidy version a tibble containing the track level
#' information that is returned from \code{\link{get_playlist}}.
#' @export
tidy <- function(x, ...) {
UseMethod("tidy")
}
#' @export
#' @rdname tidy
tidy.playlist <- function(x, ...) {
# determine unneeded columns
# the added by features can all bne derived by the `added_by_uri` col
unneeded <- c("added_by_href", "added_by_uri", "added_by_external_urls_spotify",
# album information can be fetched with get_album
"album_uri", "album_href", "album_artists", "album_album_type",
"album_images", "album_release_date", "album_release_date_precision",
"album_total_tracks", "album_type", "album_external_urls_spotify",
"album_available_markets",
# do not need uri as that can be created from "spotify:{type}:{id}"
"uri")
# clean col names
track_items <- pluck(x, "tracks", "items")
colnames(track_items) <- make_clean_names(str_remove(names(track_items), "track"))
tidied <- track_items %>%
# select(artists) %>%
mutate(artist_names = map(artists, pull, "name")) %>%
select( -all_of(unneeded) ) %>%
select(track_name = name,
album_name, id,
artist_names, added_at,
duration_ms, popularity, track_number,
available_markets,
everything() # everything else goes after available markets
)
dplyr::as_tibble(tidied)
}
#' Print method for playlist object
#' @param x A playlist object generated from \code{get_playlist()}.
#' @param ... Unused.
#' @rdname tidy
#' @export
print.playlist <- function(x, ...) {
to_show <- c("description", "tracks", "type", "href", "images", "public", "collaborative")
frms <- format(c(
paste(x$name, "by", x$owner$display_name),
paste(x$tracks$total, "tracks"),
paste(x$followers$total, "followers"),
x$external_urls$spotify
))
cat(frms, "\n", fill = TRUE)
str(x[to_show], 1, no.list = T, indent.str = "- ", comp.str = "")
invisible(x)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.