##Spotify API

# =============================================

# Paquete para hacer consultas
# Función: POST --> para obtener el token
# Función GET --> para hacer consultas (buscar artista, canciones, etc)
library(httr)
library(ggplot2)

# Copiar y pegar el id y el secret de la APP creada en Spotify
my_client_id <- "01b3592ab4984061ba478e309a304114"
my_client_secret <- "d0ef37d14c23433c8d33f749670ac157"

———– Obtener token - autenticación () ———–

# Obtener bearer token
r0 <- POST(
  "https://accounts.spotify.com/api/token",
  config = authenticate(user = my_client_id, 
                        password = my_client_secret),
  body = list(grant_type = "client_credentials"), 
  encode = "form"
)

token <-  content(r0) 
bearer_token <- paste(token$token_type, token$access_token)
url_base <- "https://api.spotify.com/v1"

———– Obtener el ID de un artista ———–

artista <- "Shakira"

get_artist_id <- function(artista, bearer_token){
  # Función para obtener el id de un artista a partir de su nombre
  # Parámetros:
  #    - artista: nombre del artista a buscar (cadena de caracteres)
  # Salida: id de Spotify asociado al artista
  
  # Preparación de la consulta
  artista_limpio <- gsub(" ", "_", artista)
  query <- paste0(url_base, "/search?q=", artista_limpio, "&type=artist")
  
  # Consulta (query) y respuesta (response)
  response <- GET(query, config = add_headers(Authorization = bearer_token))
  resultado <- content(response)  # El resultado está cotenido en la respuesta
  #print(result)
  
  # Obtenemos el data.frame con los nombres y los ids de los artistas que 
  # coinciden con la búsqueda
  df <- data.frame(id = sapply(resultado[[1]]$items, "[[", "id"),
                   nombre = sapply(resultado[[1]]$items, "[[", "name"))
  # print(df)
  
  # Seleccionamos los que nos interesan
  id <- df$id[tolower(df$nombre) == tolower(artista)][1]
  if(is.null(id) | nrow(df) == 0){
    warning("No se han encontrado coincidencias\n")
  }
  return(id)
}


# Pruebas para las que debe funcionar get_artist_id
artista_id <- get_artist_id(artista, bearer_token);artista_id
## [1] "0EmeFodog0BfCgMzAIvKQp"

———– Obtener el ID de un artista ———–

#Mirar en la API como se ve la consulta para los albumes del artista
get_albums<-function(artista_id, bearer_token){
  if(!is.null(artista_id)){
  url_base<-"https://api.spotify.com/v1"
  query<-paste0(url_base, 
                "/artists/", 
                artista_id, 
                "/albums?include_groups=album&limit=50")
  
  # Consulta query y respuesta (response)
  respuesta <- GET(query, config = add_headers(Authorization = bearer_token))
  resultado <- content(respuesta)  # El resultado está cotenido en la respuesta
  
  resultado$items
  # Obtenemos el data.frame con los nombres y los ids de los albumen del artista: 
  df <- data.frame(id = sapply(resultado$items, "[[", "id"),
                   nombre = sapply(resultado$items, "[[", "name"))
  
  
  while (!is.null(resultado$`next`)) {
    Sys.sleep(3)
    respuesta<-GET(resultado$`next`, 
                   config = add_headers(Authorization = bearer_token))
    resultado<-content(respuesta) # el resultado esta contenido en la respuesta
    df<-rbind(df,
              data.frame(id = sapply(resultado$items, "[[", "id"),
                         nombre = sapply(resultado$items, "[[", "name")))
    
  }
  return(df)
  }
}

#Pruebas para las que debe funcionar df_albums
df_albums <- get_albums(get_artist_id(artista, bearer_token), bearer_token);df_albums
##                        id                                               nombre
## 1  6WaruQqgJzSlSzZz2YdUku Laundry Service: Washed and Dried (Expanded Edition)
## 2  5EdGgMlsJ7bv8IUqkaaPZN             Shakira In Concert: El Dorado World Tour
## 3  6bUxh58rYTL67FS8dyTKMN                                            El Dorado
## 4  4nXeW6UwZGBnv6zops27k4                          Shakira. (Expanded Edition)
## 5  5meb7aKE722LA66ssBhvfM        Shakira. (Expanded Edition) [Spanish Version]
## 6  0qE6Dd97eQiywwpbrhb5fX                                      Live From Paris
## 7  3gR578qnw47M30LVBTjrlW                                          Sale el Sol
## 8  5GuMQnx4X4mfHEcYQe7ql9                                                 Loba
## 9  5u0OuxRnf3FzvZR07xAxL2                          She Wolf (Expanded Edition)
## 10 5ppnlEoj4HdRRdRihnY3jU             Oral Fixation, Vol. 2 (Expanded Edition)
## 11 3zHPYwiMJqa3hTBgk695Ae                                Fijación Oral, Vol. 1
## 12 5f5LXKRiPDf23T5QM2MEmX                                Live & Off The Record
## 13 4DyMK9x2gnmRkRa16zHaEV                                      Laundry Service
## 14 62F8unRY46ZDR2EE5ag5Z5                               Servicio De Lavandería
## 15 3yQQUyIA3vRIRnB4rqtThe                                Shakira MTV Unplugged
## 16 5hcKSTqKOLuzJgYIQileAe                             Donde Estan Los Ladrones
## 17 2G7F89aCUNtwnj3vYKNMfF                                          The Remixes
## 18 3HLngzP9wVd8p3SMDQgyd9                                       Pies Descalzos

———– Canciones por album ———–

get_tracks <- function(artista, bearer_token){
  lista_albums <- paste(df_albums$id, collapse = ",")
  url_base<-"https://api.spotify.com/v1"
  query<-paste0(url_base, 
                "/albums?ids=", 
                lista_albums)
  
  #Consulta (query) y respuesta (response)
  respuesta <- GET(query, config = add_headers(Authorization = bearer_token))
  resultado <- content(respuesta) #El resultado está contenido en la respuesta
  
  #Filtrar el resultado
  lista_tracks <- lapply(resultado[[1]], "[[", "tracks")
  lista_items <- sapply(lista_tracks, "[[", "items")
  lista_nombres <- lapply(lista_items, sapply, "[[", "name")
  nombres <- do.call(c, lista_nombres)
  
  #Obtener el data frame de tracks
  df_tracks <- c()
  for (album in resultado$albums) {
    for (track in album$tracks$items) {  
      df_tracks <- rbind(df_tracks, 
                         data.frame(id = track$id, 
                                    name = track$name))
    }
  }

  return(df_tracks)
}

#Pruebas del funcionamiento de get_tracks
df_canciones <- get_tracks(artista, bearer_token)

———– Energia por cancion ———–

get_features <- function(track_id, bearer_token){
    query <- paste0(url_base, 
                    "/audio-features/", 
                    track_id)
    
    respuesta <- GET(query, config = add_headers(Authorization = bearer_token))
    resultado <- content(respuesta)
    
  
    audio_features <- data.frame(id = track_id,
                           energia = resultado$energy,
                           valencia = resultado$valence)
    return(audio_features)
  }
  
lista_canciones <- df_canciones$id
df_features <- do.call(rbind, lapply(lista_canciones, get_features, bearer_token = bearer_token))

———–Grafica———————

plot_features <- function(df_features){
  ggplot(df_features, aes(x = valencia, y = energia, color = id)) +
    geom_point(show.legend = FALSE) +
    labs(title = "Energia y valencia",
         x = "Valencia",
         y = "Energia") +
    annotate("text", x = 0, y = 1, label = "Turbulent/Angry", hjust = 0, vjust = 1) +
    annotate("text", x = 1, y = 1, label = "Happy/Joyful", hjust = 1, vjust = 1) +
    annotate("text", x = 0, y = 0, label = "Sad/Depressing", hjust = 0, vjust = 0) +
    annotate("text", x = 1, y = 0, label = "Chill/Peaceful", hjust = 1, vjust = 0) +
    theme(axis.text = element_text(face = "bold")) +
    geom_hline(yintercept = 0.5, size = 0.5) +
    geom_vline(xintercept = 0.5, size = 0.5) +
    coord_cartesian(xlim = c(-0,1), ylim = c(-0, 1))
}

———– USO ———–

grafica_artista <- function(artista, bearer_token){
  artista_id <- get_artist_id(artista, bearer_token)
  df_albums <- get_albums(artista_id, bearer_token)
  df_canciones <- get_tracks(df_albums, bearer_token)
  df_features <- do.call(rbind, lapply(df_canciones$id, get_features, bearer_token = bearer_token))
  ggplot_obj <- plot_features(df_features)
  
  # Mostrar la gráfica
  print(ggplot_obj)
}

artista <- "Shakira"
bearer_token <- bearer_token
grafica_artista(artista, bearer_token)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.