Skip to content

Commit

Permalink
Resolving inconsistency with inputs and imports #59 issue (#61)
Browse files Browse the repository at this point in the history
* accepts strings not only data.frame

* import explicitly dependency

* explicit imports

* import purrr
  • Loading branch information
antaldaniel authored and charlie86 committed Jan 27, 2019
1 parent a052aeb commit 8d7e80e
Show file tree
Hide file tree
Showing 19 changed files with 139 additions and 38 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Imports:
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
RoxygenNote: 6.1.0
RoxygenNote: 6.1.1
Suggests: testthat
URL: http://github.com/charlie86/spotifyr
BugReports: http://github.com/charlie86/spotifyr/issues
8 changes: 8 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,16 @@ import(httr)
import(purrr)
import(stringr)
import(tidyr)
importFrom(dplyr,filter)
importFrom(dplyr,mutate)
importFrom(dplyr,mutate_at)
importFrom(dplyr,rename)
importFrom(dplyr,select)
importFrom(dplyr,slice)
importFrom(lubridate,as_datetime)
importFrom(lubridate,year)
importFrom(purrr,map)
importFrom(purrr,map_df)
importFrom(purrr,possibly)
importFrom(readr,read_lines)
importFrom(rvest,html_attr)
Expand All @@ -59,6 +66,7 @@ importFrom(rvest,html_nodes)
importFrom(rvest,html_session)
importFrom(rvest,html_text)
importFrom(stringr,str_detect)
importFrom(stringr,str_glue)
importFrom(stringr,str_replace_all)
importFrom(stringr,str_trim)
importFrom(tibble,as_tibble)
Expand Down
86 changes: 70 additions & 16 deletions R/tracks.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,36 @@ get_tracks <- function(track_name, artist_name = NULL, album_name = NULL, return
return(tracks)
}


#' Check track URI validity
#'
#' This function takes a track URI and returns a list containing an audio analysis object
#' from Spotify's audio analysis endpoint
#' @param track_uri A string with a track URI, either in form
#' \code{'3qZCK4Fg655xHnlgHK6H63'} or \code{'spotify:track:3qZCK4Fg655xHnlgHK6H63'}
#' @keywords track uri string search
#' @examples
#' \dontrun{
#' check_uri ( track_uri ='3qZCK4Fg655xHnlgHK6H63')
#' check_uri ( track_uri = '3qZCK4Fg655xHnlgHK6H6') #one character missing
#' }

check_uri <- function ( track_uri ) {
is_uri <- function(x) {
nchar(x) == 22 &
!str_detect(x, ' ') &
str_detect(x, '[[:digit:]]') &
str_detect(x, '[[:lower:]]') &
str_detect(x, '[[:upper:]]')
}

track_uri <- gsub('spotify:track:', '', track_uri)

if (!is_uri(track_uri)) {
stop('Error: Must enter a valid uri')
}
}

#' Get track audio analysis by URI
#'
#' This function takes a track URI and returns a list containing an audio analysis object
Expand All @@ -76,6 +106,8 @@ get_tracks <- function(track_name, artist_name = NULL, album_name = NULL, return
#' kid_a_audio_analysis <- get_track_audio_analysis(kid_a$track_uri)
#' }



get_track_audio_analysis <- function(track_uri, access_token = get_spotify_access_token()) {

is_uri <- function(x) {
Expand All @@ -100,9 +132,14 @@ get_track_audio_analysis <- function(track_uri, access_token = get_spotify_acces
#' Get audio features from one or more tracks on Spotify
#'
#' This function returns audio features from a dataframe of tracks on Spotify
#' @param tracks Dataframe containing a column `track_uri`, corresponding to Spotify Album URIs. Can be output from spotifyr::get_album_tracks or spotifyr::get_playlist_tracks()
#' @param access_token Spotify Web API token. Defaults to spotifyr::get_spotify_access_token()
#' @param tracks May be directly given as a ataframe containing a column `track_uri`, corresponding to Spotify Album URIs.
#' Can be output from \code{\link{get_album_tracks}} or \code{\link{get_playlist_tracks}},
#' or alternatively as a character vector of valid URIs.
#' @param access_token Spotify Web API token. Defaults to \code{\link{get_spotify_access_token()}}
#' @keywords track audio features
#' @importFrom stringr str_glue
#' @importFrom dplyr select slice filter mutate mutate_at rename
#' @importFrom purrr map_df
#' @export
#' @examples
#' \dontrun{
Expand All @@ -117,27 +154,44 @@ get_track_audio_analysis <- function(track_uri, access_token = get_spotify_acces
#' obama_audio_features <- get_track_audio_features(tracks)
#' }

get_track_audio_features <- function(tracks, access_token = get_spotify_access_token()) {
get_track_audio_features <- function(tracks,
access_token = get_spotify_access_token()
) {

audio_feature_vars <- c('danceability', 'energy', 'key', 'loudness', 'mode', 'speechiness', 'acousticness',
'instrumentalness', 'liveness', 'valence', 'tempo', 'duration_ms', 'time_signature')

# create lookup to classify key: https://developer.spotify.com/web-api/get-audio-features/
pitch_class_lookup <- c('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B')

num_loops <- ceiling(sum(!duplicated(tracks$track_uri)) / 100)
if ( ! class (tracks) %in% 'data.frame' ) {
sapply ( tracks, check_uri) #internal functin uri checker
num_loops <- ceiling(sum(!duplicated(tracks) / 100)) #if a character vector is inputed

} else {
num_loops <- ceiling(sum(!duplicated(tracks$track_uri)) / 100)
}

track_audio_features <- purrr::map_df(1:num_loops, function(this_loop) {

if ( ! class (tracks) %in% 'data.frame' ) {
uris <- paste0(tracks, collapse = ',')
} else {
uris <- tracks %>%
dplyr::filter(!duplicated(track_uri)) %>%
dplyr::slice(((this_loop * 100) - 99):(this_loop * 100)) %>%
dplyr::select(track_uri) %>%
.[[1]] %>%
paste0(collapse = ',')
}

track_audio_features <- map_df(1:num_loops, function(this_loop) {

uris <- tracks %>%
dplyr::filter(!duplicated(track_uri)) %>%
slice(((this_loop * 100) - 99):(this_loop * 100)) %>%
select(track_uri) %>%
.[[1]] %>%
paste0(collapse = ',')

res <- RETRY('GET', url = str_glue('https://api.spotify.com/v1/audio-features/?ids={uris}'),
query = list(access_token = access_token), quiet = TRUE, times = 10) %>% content
res <- RETRY('GET',
url = stringr::str_glue('https://api.spotify.com/v1/audio-features/?ids={uris}'),
query = list(access_token = access_token),
quiet = TRUE, times = 10) %>%
content

content <- res$audio_features

Expand All @@ -161,9 +215,9 @@ get_track_audio_features <- function(tracks, access_token = get_spotify_access_t
return(audio_features_df)

}) %>% select(-c(type, uri, track_href, analysis_url)) %>%
rename(track_uri = id) %>%
mutate_at(audio_feature_vars, as.numeric) %>%
mutate(key = pitch_class_lookup[key + 1],
dplyr::rename(track_uri = id) %>%
dplyr::mutate_at(audio_feature_vars, as.numeric) %>%
dplyr::mutate(key = pitch_class_lookup[key + 1],
mode = case_when(mode == 1 ~ 'major',
mode == 0 ~ 'minor',
TRUE ~ as.character(NA)),
Expand Down
26 changes: 26 additions & 0 deletions man/check_uri.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_album_data.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_albums.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions man/get_artist_albums.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions man/get_artist_audio_features.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_discography.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/get_label_albums.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/get_my_top_artists.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_playlist_audio_features.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_spotify_authorization_code.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_track_audio_analysis.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions man/get_track_audio_features.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_tracks.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_user_audio_features.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/get_user_playlist_count.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion man/prep_info.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8d7e80e

Please sign in to comment.