Skip to content

Commit 34d0f23

Browse files
Merge pull request #58 from wjakethompson/the-life-of-a-showgirl
The Life of a Showgirl
2 parents 2744a5a + 8d016dc commit 34d0f23

File tree

84 files changed

+11177
-776
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+11177
-776
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
^\.github$
1313
^\.lintr$
1414
^CRAN-SUBMISSION$
15+
^\.httr-oauth$
1516
^[.]?air[.]toml$
1617
^\.vscode$

.github/workflows/R-CMD-check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- {os: windows-latest, r: 'release'}
2525
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
2626
- {os: ubuntu-latest, r: 'release'}
27-
- {os: ubuntu-latest, r: 'oldrel-1'}
27+
# - {os: ubuntu-latest, r: 'oldrel-1'}
2828

2929
env:
3030
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
.Ruserdata
55
docs
66
inst/doc
7+
.httr-oauth
78
data-raw/*.rds
89
data-raw/soundstat/*.rds

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Authors@R:
77
Description: A comprehensive resource for data on Taylor Swift songs. Data
88
is included for all officially released studio albums, extended plays
99
(EPs), and individual singles are included. Data comes from 'Genius'
10-
(lyrics) and 'Spotify' (song characteristics). Additional functions
10+
(lyrics) and 'SoundStat' (song characteristics). Additional functions
1111
are included for easily creating data visualizations with color
1212
palettes inspired by Taylor Swift's album covers.
1313
License: MIT + file LICENSE

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ export(scale_fill_taylor_b)
3333
export(scale_fill_taylor_c)
3434
export(scale_fill_taylor_d)
3535
export(set_soundstat_api_key)
36+
export(set_spotify_api_key)
3637
export(taylor_examples)
38+
export(taylor_sitrep)
3739
export(title_case)
3840
export(translate_bracelet)
3941
import(vctrs)

NEWS.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# taylor (development version)
22

3+
* New data and visualization tools have been added for
4+
*The Life of a Showgirl*.
5+
* Added lyrics and SoundState audio features to `taylor_all_songs` and
6+
`taylor_album_songs`.
7+
* Added composite critic score from Metacritic to `taylor_albums`.
8+
* Added a new themed color palette to `album_palettes`.
9+
* Added a new single color to `album_compare`.
10+
11+
* New functions for accessing APIs for track information
12+
(`get_spotify_track_info()`) and audio features
13+
(`get_soundstat_audio_features()` and `get_reccobeats_audio_features()`).
14+
15+
* New helper functions for setting up API configuration.
16+
* `set_spotify_api_key()` / `get_spotify_api_key()`
17+
* `set_soundstat_api_key()` / `get_soundstat_api_key()`
18+
19+
* `taylor_sitrep()` can be used to quickly check the configuration of API keys.
20+
321
* Updated data API due to Spotify changes. Implications for data:
422
* Lost columns: `liveness`, `speechiness`, `time_signature`
523
* Data may be slightly different due to differences between the Spotify and
@@ -50,9 +68,8 @@
5068
* New data and visualization tools have been added for
5169
*THE TORTURED POETS DEPARTMENT*.
5270
* Added lyrics and Spotify audio features to `taylor_all_songs` and
53-
`taylor_album_songs`.
54-
* Added composite critic score from Metacritic to
55-
`taylor_albums`.
71+
`taylor_album_songs`.
72+
* Added composite critic score from Metacritic to `taylor_albums`.
5673
* Added a new themed color palette to `album_palettes`.
5774
* Added a new single color to `album_compare`.
5875

R/api-access.R

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ get_spotify_track_info <- function(
3232
api_key = get_spotify_access_token()
3333
) {
3434
check_character(track_id, allow_na = TRUE)
35-
check_character(api_key)
35+
check_character(api_key$client_id)
36+
check_character(api_key$client_secret)
37+
api_key <- spotifyr::get_spotify_access_token(
38+
client_id = api_key$client_id,
39+
client_secret = api_key$client_secret
40+
)
3641

3742
if (is.na(track_id) || track_id == "") {
3843
return(NULL)
@@ -60,19 +65,24 @@ get_spotify_track_info <- function(
6065

6166
#' Spotify API helpers
6267
#'
63-
#' This is a wrapper around [spotifyr::get_spotify_access_token()] to create a
64-
#' Spotify access token from stored environment variables.
68+
#' Set and retrieve Spotify client information.
69+
#'
70+
#' @param id A Spotify Client ID.
71+
#' @param secret A Spotify Client Secret.
6572
#'
66-
#' @returns The Spotify access token.
73+
#' @returns
74+
#' * `get_spotify_api_key()` returns a previously stored Client ID and Secret.
75+
#' * `set_spotify_api_key()` is called for side effects only.
76+
#' @name spotify-api
6777
#' @export
6878
#'
6979
#' @examplesIf taylor_examples()
7080
#' \donttest{get_spotify_access_token()}
7181
get_spotify_access_token <- function() {
7282
client_id <- Sys.getenv("SPOTIFY_CLIENT_ID")
7383
client_secret <- Sys.getenv("SPOTIFY_CLIENT_SECRET")
74-
if (!any(identical(client_id, ""), identical(client_secret, ""))) {
75-
token <- spotifyr::get_spotify_access_token(
84+
if (all(nzchar(client_id), nzchar(client_secret))) {
85+
token <- list(
7686
client_id = client_id,
7787
client_secret = client_secret
7888
)
@@ -85,16 +95,39 @@ get_spotify_access_token <- function() {
8595
cli::cli_abort(
8696
cli::format_message(
8797
c(
88-
"No access token found, please see",
98+
"Client ID or Secret not found, please see",
8999
"{.fun spotifyr::get_spotify_access_token}"
90100
)
91101
)
92102
)
93103
}
94104
}
95105

106+
#' @export
107+
#' @rdname spotify-api
108+
set_spotify_api_key <- function(id = NULL, secret = NULL) {
109+
check_character(id, allow_null = TRUE)
110+
check_character(secret, allow_null = TRUE)
111+
112+
if (is.null(id)) {
113+
id <- askpass::askpass("Please enter your Client ID")
114+
if (is.null(id)) {
115+
cli::cli_abort("Client ID not provided")
116+
}
117+
}
118+
Sys.setenv("SPOTIFY_CLIENT_ID" = id)
119+
120+
if (is.null(secret)) {
121+
secret <- askpass::askpass("Please enter your Client Secret")
122+
if (is.null(secret)) {
123+
cli::cli_abort("Client Secret not provided")
124+
}
125+
}
126+
Sys.setenv("SPOTIFY_CLIENT_SECRET" = secret)
127+
}
128+
96129
spotify_testing_key <- function() {
97-
spotifyr::get_spotify_access_token(
130+
list(
98131
client_id = httr2::secret_decrypt(
99132
"UOF5NVolAFuZUfPsrqB6zRGiuT2U6kZTly16hmop_vkzywAmTyHJaDuWl13gymsI",
100133
"TAYLOR_KEY"
@@ -120,10 +153,11 @@ spotify_testing_key <- function() {
120153
#'
121154
#' @details
122155
#' Due to differences in algorithms and methodologies, the SoundStat audio
123-
#' features are on a slightly different scale than the Spotify audio features
124-
#' that were originally included in [taylor] prior the [changes to the Spotify
125-
#' API](). We can convert the SoundStat values to the Spotify scale using the
126-
#' formulas in the [SoundStat
156+
#' features are on a slightly different scale than the audio features that were
157+
#' originally included in [taylor] prior to the [changes to the Spotify
158+
#' API](https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api).
159+
#' We can convert the SoundStat values to the Spotify scale using the formulas
160+
#' in the [SoundStat
127161
#' docs](https://soundstat.info/article/Understanding-Audio-Analysis.html):
128162
#'
129163
#' ```

R/data.R

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@
66
#'
77
#' @details
88
#' `taylor_all_songs` contains all songs in Taylor's discography.
9-
#' Lyrics come from Genius, and songs characteristics come from the Spotify API.
9+
#' Lyrics come from Genius, and songs characteristics come from the SoundStat
10+
#' API.
1011
#' Some data is known to be missing. The Beautiful Eyes EP is not available on
11-
#' any streaming service, and therefore has no data from the Spotify API.
12+
#' any streaming service, and therefore has no data from the SoundStat API.
1213
#' Similarly, the song *American Girl*, a cover of the Tom Petty original, was
1314
#' released exclusively on Rhapsody (now Napster), and therefore also does not
14-
#' have data from the Spotify API.
15+
#' have data from the SoundStat API.
1516
#'
16-
#' For songs released separately from Taylor's official albums or EPs, album
17-
#' information is not included. For example, *I Don't Wanna Live Forever* was
18-
#' released as part of the *Fifty Shades Darker* movie soundtrack. However, the
19-
#' `album_name` column for this song is `NA`, indicating that it does not appear
20-
#' on one of Taylor's albums.
17+
#' For songs released separately from Taylor's official albums or EPs, full
18+
#' album information is not included.
19+
#' For example, *I Don't Wanna Live Forever* was released as part of the
20+
#' *Fifty Shades Darker (Original Motion Picture Soundtrack)*.
21+
#' However, the `album_release` and `track_number` columns for this song are
22+
#' `NA`.
2123
#'
2224
#' Songs are only included one time. For example, if a song appears on both the
2325
#' standard and deluxe version of an album, there is only one record of the
@@ -36,14 +38,6 @@
3638
#' `taylor_album_songs` contains the same information as `taylor_all_songs`, but
3739
#' only for Taylor's official studio albums. Thus, `taylor_album_songs` is a
3840
#' subset of [`taylor_all_songs`], with EPs and individual singles excluded.
39-
#' Critically, this subset also only includes versions owned by Taylor when
40-
#' possible, because we stan artists owning their own work. This means that
41-
#' although both *Fearless* and *Fearless (Taylor's Version)* appear in the full
42-
#' [`taylor_all_songs`] data, only *Fearless (Taylor's Version)* appears in this
43-
#' subset. This also means that this data set will change as additional
44-
#' re-releases are made available (i.e., *Red* was replaced with
45-
#' *Red (Taylor's Version)* in [version
46-
#' 1.0.0](https://wjakethompson.com/blog/taylor/2021-12-17-taylor-1.0.0/)).
4741
#'
4842
#' @format `taylor_all_songs` is a [tibble][tibble::tibble-package] with
4943
#' `r nrow(taylor_all_songs)` rows and `r ncol(taylor_all_songs)` variables.
@@ -94,7 +88,7 @@
9488
#' * `mode`: Modality of a track (major/minor). `0` = minor, `1` = major.
9589
#'
9690
#' Finally, the last set of variables includes those calculated from the
97-
#' Soundstat API data, and a list-column containing song lyrics.
91+
#' SoundStat API data, and a list-column containing song lyrics.
9892
#' * `key_name`: Corresponds directly to the `key`, but the integer is converted
9993
#' to the key name using Pitch Class notation (e.g., `0` becomes `C`).
10094
#' * `mode_name`: Corresponds directly to the `mode`, but the integer is

R/ggplot2-color-scales.R

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,17 @@ scale_fill_albums <- function(
238238
limits = force,
239239
na.value = NA
240240
) {
241-
album_pal <- vec_data(taylor::album_compare)
242-
names(album_pal) <- taylor::album_levels
241+
album_pal <- album_labels() |>
242+
dplyr::select("name", "value") |>
243+
tibble::deframe()
244+
245+
album_pal <- rep(album_pal, 4) |>
246+
rlang::set_names(c(
247+
names(album_pal),
248+
tolower(names(album_pal)),
249+
toupper(names(album_pal)),
250+
title_case(names(album_pal))
251+
))
243252

244253
ggplot2::scale_fill_manual(
245254
values = album_pal,
@@ -260,8 +269,17 @@ scale_colour_albums <- function(
260269
limits = force,
261270
na.value = NA
262271
) {
263-
album_pal <- vec_data(taylor::album_compare)
264-
names(album_pal) <- taylor::album_levels
272+
album_pal <- album_labels() |>
273+
dplyr::select("name", "value") |>
274+
tibble::deframe()
275+
276+
album_pal <- rep(album_pal, 4) |>
277+
rlang::set_names(c(
278+
names(album_pal),
279+
tolower(names(album_pal)),
280+
toupper(names(album_pal)),
281+
title_case(names(album_pal))
282+
))
265283

266284
ggplot2::scale_colour_manual(
267285
values = album_pal,

R/sitrep.R

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#' Situation report for APIs
2+
#'
3+
#' Check configuration status for Spotify and SoundStat APIs.
4+
#'
5+
#' @return Called for side effects.
6+
#' @export
7+
#'
8+
#' @examplesIf taylor_examples()
9+
#' taylor_sitrep()
10+
taylor_sitrep <- function() {
11+
cli::cli_h1("taylor Situation Report")
12+
13+
display_heading("Spotify Configuration")
14+
display_status("SPOTIFY_CLIENT_ID", name = "Client ID")
15+
display_status("SPOTIFY_CLIENT_SECRET", name = "Client Secret", n = NULL)
16+
17+
display_heading("SoundStat Configuration")
18+
display_status("SOUNDSTAT_KEY", name = "API Key")
19+
}
20+
21+
22+
has_key <- function(key) {
23+
nzchar(Sys.getenv(key))
24+
}
25+
26+
display_key <- function(key, n = 6) {
27+
cli::format_message("{.strong {substr(Sys.getenv(key), 1, n)}}...")
28+
}
29+
30+
display_status <- function(key, name, n = 6) {
31+
if (has_key(key) && !is.null(n)) {
32+
cli::cli_alert_success("{name}: {display_key(key, n = n)}")
33+
} else if (has_key(key) && is.null(n)) {
34+
cli::cli_alert_success("{name}: {.strong Found}")
35+
} else {
36+
cli::cli_alert_danger("{name}: {.strong Not found}")
37+
}
38+
}
39+
40+
display_heading <- function(text) {
41+
cli::cli_div(theme = list(h2 = list(`margin-bottom` = 0)))
42+
cli::cli_h2(text)
43+
cli::cli_end()
44+
}

0 commit comments

Comments
 (0)