displays the user's top songs via spotify api, authentication via oauth 2.

This commit is contained in:
Joshua Ashton
2025-02-01 21:53:45 -07:00
parent 331bfa0a01
commit eab066346e
9 changed files with 191 additions and 45 deletions
+5
View File
@@ -0,0 +1,5 @@
module cs2440.joshashton.dev/api
go 1.23.5
require github.com/joho/godotenv v1.5.1 // indirect
+2
View File
@@ -0,0 +1,2 @@
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+42
View File
@@ -0,0 +1,42 @@
package main
import (
"crypto/rand"
"fmt"
"github.com/joho/godotenv"
"log"
"net/http"
"os"
"strings"
)
func generateRandomString(length int) string {
var b = make([]byte, length)
rand.Read(b)
return fmt.Sprintf("%x", b)
}
func main() {
err := godotenv.Load("../.env")
if err != nil {
log.Fatalf("Error loading .env file: %s", err)
}
client_id := os.Getenv("SPOTIFY_CLIENT_ID")
redirect_uri := "http://localhost/music"
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
scope := "user-top-read"
redirectURL := "https://accounts.spotify.com/authorize?" + strings.Join([]string{
"response_type=code",
"client_id=" + client_id,
"scope=" + scope,
"redirect_uri=" + redirect_uri,
}, "&")
http.Redirect(w, r, redirectURL, http.StatusFound)
})
http.ListenAndServe(":8080", nil)
}
+8 -11
View File
@@ -1,7 +1,5 @@
<?php <?php
function get_core() $albums = [
{
$albums = [
array('name' => 'Abyss', 'artist' => 'Pastel Ghost', 'link' => 'https://open.spotify.com/album/2FQieUp8BxPN7OR8fE76TE'), array('name' => 'Abyss', 'artist' => 'Pastel Ghost', 'link' => 'https://open.spotify.com/album/2FQieUp8BxPN7OR8fE76TE'),
array('name' => 'Golden Age - The 4th Album', 'artist' => 'NCT 127', 'link' => 'https://open.spotify.com/album/5mUo2e4QpUA7NJl2t51uFu'), array('name' => 'Golden Age - The 4th Album', 'artist' => 'NCT 127', 'link' => 'https://open.spotify.com/album/5mUo2e4QpUA7NJl2t51uFu'),
array('name' => 'To Pimp a Butterfly', 'artist' => 'Kendrick Lamar', 'link' => 'https://open.spotify.com/album/7ycBtnsMtyVbbwTfJwRjSP'), array('name' => 'To Pimp a Butterfly', 'artist' => 'Kendrick Lamar', 'link' => 'https://open.spotify.com/album/7ycBtnsMtyVbbwTfJwRjSP'),
@@ -12,19 +10,19 @@ function get_core()
array('name' => 'Currents', 'artist' => 'Tame Impala', 'link' => 'https://open.spotify.com/album/79dL7FLiJFOO0EoehUHQBv'), array('name' => 'Currents', 'artist' => 'Tame Impala', 'link' => 'https://open.spotify.com/album/79dL7FLiJFOO0EoehUHQBv'),
array('name' => 'INSIDE', 'artist' => 'Bo Burnham', 'link' => 'https://open.spotify.com/album/35qVMfUfBN6q2xzm9rZn5a'), array('name' => 'INSIDE', 'artist' => 'Bo Burnham', 'link' => 'https://open.spotify.com/album/35qVMfUfBN6q2xzm9rZn5a'),
array('name' => 'Teenage Dream', 'artist' => 'Katy Perry', 'link' => 'https://open.spotify.com/album/2eQMC9nJE3f3hCNKlYYHL1'), array('name' => 'Teenage Dream', 'artist' => 'Katy Perry', 'link' => 'https://open.spotify.com/album/2eQMC9nJE3f3hCNKlYYHL1'),
]; ];
shuffle($albums); shuffle($albums);
$content = ''; $content = '';
foreach ($albums as $album) { foreach ($albums as $album) {
$content = $content . ' $content = $content . '
<tr> <tr>
<td><a href="' . $album['link'] . '" target="_blank">' . $album['name'] . '</a></td> <td><a href="' . $album['link'] . '" target="_blank">' . $album['name'] . '</a></td>
<td>' . $album['artist'] . '</td> <td>' . $album['artist'] . '</td>
</tr>'; </tr>';
} }
$html = ' $html = '
<table> <table>
<tr> <tr>
<th>Name</th> <th>Name</th>
@@ -34,6 +32,5 @@ function get_core()
</table> </table>
'; ';
return $html; echo $html;
}
?> ?>
+99 -6
View File
@@ -7,7 +7,11 @@ $html = '';
$client_id = $_ENV['SPOTIFY_CLIENT_ID']; $client_id = $_ENV['SPOTIFY_CLIENT_ID'];
$client_secret = $_ENV['SPOTIFY_CLIENT_SECRET']; $client_secret = $_ENV['SPOTIFY_CLIENT_SECRET'];
$access_token = get_access_token($client_id, $client_secret); // $auth_code = $_ENV['SPOTIFY_AUTH_CODE'];
$auth_code = $_GET['code'];
// $auth_state = $_GET['state'];
$client_credentials = get_client_credentials($client_id, $client_secret);
// TODO: Dynamically retrieve top 10 albums from Spotify API // TODO: Dynamically retrieve top 10 albums from Spotify API
// TODO: Implement server-side caching for faster load times. // TODO: Implement server-side caching for faster load times.
@@ -24,9 +28,11 @@ $albums = [
'2eQMC9nJE3f3hCNKlYYHL1' '2eQMC9nJE3f3hCNKlYYHL1'
]; ];
shuffle($albums);
$content = ''; $content = '';
foreach ($albums as $album_id) { foreach ($albums as $album_id) {
$data = get_album($access_token, $album_id); $data = get_album($client_credentials, $album_id);
$content = $content . '<tr> $content = $content . '<tr>
<td><img src="' . $data['images'][0]['url'] . '" /></td> <td><img src="' . $data['images'][0]['url'] . '" /></td>
<td>' . $data['name'] . '</td> <td>' . $data['name'] . '</td>
@@ -44,7 +50,7 @@ $html = '
<th>Spotify</th> <th>Spotify</th>
</tr>' . $content . '</table>'; </tr>' . $content . '</table>';
function get_access_token($client_id, $client_secret) function get_client_credentials($client_id, $client_secret)
{ {
$url = 'https://accounts.spotify.com/api/token'; $url = 'https://accounts.spotify.com/api/token';
@@ -80,7 +86,7 @@ function get_access_token($client_id, $client_secret)
curl_close($ch); curl_close($ch);
} }
function get_album($access_token, $album_id) function get_album($client_credentials, $album_id)
{ {
$url = 'https://api.spotify.com/v1/albums/' . $album_id; $url = 'https://api.spotify.com/v1/albums/' . $album_id;
@@ -89,7 +95,7 @@ function get_album($access_token, $album_id)
curl_setopt_array($ch, array( curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array( CURLOPT_HTTPHEADER => array(
"Authorization: Bearer $access_token" "Authorization: Bearer $client_credentials"
) )
)); ));
@@ -105,5 +111,92 @@ function get_album($access_token, $album_id)
curl_close($ch); curl_close($ch);
} }
echo $html; function get_access_token($auth_code, $client_id, $client_secret)
{
$url = 'https://accounts.spotify.com/api/token';
$data = array(
'grant_type' => 'authorization_code',
'code' => $auth_code,
'redirect_uri' => 'http://localhost/music'
);
$client_info = base64_encode("$client_id:$client_secret");
$post_data = http_build_query($data);
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
"Authorization: Basic $client_info",
'Content-Type: application/x-www-form-urlencoded'
),
CURLOPT_POSTFIELDS => $post_data
));
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch);
} else {
$data = json_decode($response, true);
curl_close($ch);
return $data['access_token'];
}
curl_close($ch);
}
function get_albums($auth_code, $client_id, $client_secret)
{
$access_token = get_access_token($auth_code, $client_id, $client_secret);
$url = 'https://api.spotify.com/v1/me/top/tracks';
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
"Authorization: Bearer $access_token"
)
));
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch);
return;
} else {
$data = json_decode($response, true);
$top_songs = $data['items'];
}
curl_close($ch);
$song_data = [];
foreach ($top_songs as $song) {
$song_data[] = array(
'image' => $song['album']['images'][0]['url'],
'song_name' => $song['name'],
'song_id' => $song['id'],
'album_name' => $song['album']['name'],
'album_id' => $song['album']['id'],
'artist' => $song['artists'][0]['name'],
);
}
foreach ($song_data as $s) {
echo '
<img src="' . $s['image'] . '">
<h3>Name: ' . $s['song_name'] . ' - ' . $s['artist'] . '</h3>
<h4>Album: ' . $s['album_name'] . '</h4>
<h6>Song ID: ' . $s['song_id'] . '</h6>
<h6>Album ID: ' . $s['album_id'] . '</h6>
';
}
}
get_albums($auth_code, $client_id, $client_secret);
// echo $html;
?> ?>
+3 -5
View File
@@ -1,6 +1,6 @@
<?php <?php
session_start(); session_start();
include ('core.php'); include ('login.php');
exec('php explore.php &'); exec('php explore.php &');
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@@ -14,12 +14,10 @@ exec('php explore.php &');
<body> <body>
<h1>My Favorite Albums</h1> <h1>My Favorite Albums</h1>
<button onclick=modeSwitch() type="submit">Click me</button> <button id="switcher" onclick=modeSwitch('core')>Core</button>
<div id="content"> <div id="content">
<?php <?php include ('explore.php'); ?>
echo get_core();
?>
</div> </div>
</body> </body>
</html> </html>
+16 -1
View File
@@ -1,5 +1,7 @@
async function modeSwitch() { async function modeSwitch(mode) {
const content = document.getElementById("content"); const content = document.getElementById("content");
console.log(mode);
if (mode == 'explore') {
var response = await fetch('explore.php'); var response = await fetch('explore.php');
if (response.status === 200) { if (response.status === 200) {
@@ -7,4 +9,17 @@ async function modeSwitch() {
let text = await data(); let text = await data();
content.innerHTML = text; content.innerHTML = text;
} }
switcher.setAttribute("onclick", "modeSwitch('core')")
switcher.innerText = 'Core';
} else {
var response = await fetch('core.php');
if (response.status === 200) {
let data = async () => { return await response.text() };
let text = await data();
content.innerHTML = text;
}
switcher.setAttribute("onclick", "modeSwitch('explore')")
switcher.innerText = 'Explore';
}
} }
-3
View File
@@ -1,3 +0,0 @@
<?php
echo 'test';
?>
-3
View File
@@ -1,3 +0,0 @@
<?php
echo '<p>Test</p>';
?>