diff --git a/api/go.mod b/api/go.mod new file mode 100644 index 0000000..9806ead --- /dev/null +++ b/api/go.mod @@ -0,0 +1,5 @@ +module cs2440.joshashton.dev/api + +go 1.23.5 + +require github.com/joho/godotenv v1.5.1 // indirect diff --git a/api/go.sum b/api/go.sum new file mode 100644 index 0000000..d61b19e --- /dev/null +++ b/api/go.sum @@ -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= diff --git a/api/main.go b/api/main.go new file mode 100644 index 0000000..34a1f5e --- /dev/null +++ b/api/main.go @@ -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) +} diff --git a/music/core.php b/music/core.php index 2e7f596..66c494b 100644 --- a/music/core.php +++ b/music/core.php @@ -1,30 +1,28 @@ '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' => 'To Pimp a Butterfly', 'artist' => 'Kendrick Lamar', 'link' => 'https://open.spotify.com/album/7ycBtnsMtyVbbwTfJwRjSP'), - array('name' => 'Off the Wall', 'artist' => 'Michael Jackson', 'link' => 'https://open.spotify.com/album/2ZytN2cY4Zjrr9ukb2rqTP'), - array('name' => 'Vol. 3: The Subliminal Verses', 'artist' => 'Slipknot', 'link' => 'https://open.spotify.com/album/4ZDBQSIDIZRUBOG2OHcN3T'), - array('name' => 'Этажи', 'artist' => 'Molchat Doma', 'link' => 'https://open.spotify.com/album/1FHREwXgTQvqiG8q5KlRzc'), - array('name' => 'Hot Pink', 'artist' => 'Doja Cat', 'link' => 'https://open.spotify.com/album/1MmVkhiwTH0BkNOU3nw5d3'), - 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' => 'Teenage Dream', 'artist' => 'Katy Perry', 'link' => 'https://open.spotify.com/album/2eQMC9nJE3f3hCNKlYYHL1'), - ]; - shuffle($albums); +$albums = [ + 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' => 'To Pimp a Butterfly', 'artist' => 'Kendrick Lamar', 'link' => 'https://open.spotify.com/album/7ycBtnsMtyVbbwTfJwRjSP'), + array('name' => 'Off the Wall', 'artist' => 'Michael Jackson', 'link' => 'https://open.spotify.com/album/2ZytN2cY4Zjrr9ukb2rqTP'), + array('name' => 'Vol. 3: The Subliminal Verses', 'artist' => 'Slipknot', 'link' => 'https://open.spotify.com/album/4ZDBQSIDIZRUBOG2OHcN3T'), + array('name' => 'Этажи', 'artist' => 'Molchat Doma', 'link' => 'https://open.spotify.com/album/1FHREwXgTQvqiG8q5KlRzc'), + array('name' => 'Hot Pink', 'artist' => 'Doja Cat', 'link' => 'https://open.spotify.com/album/1MmVkhiwTH0BkNOU3nw5d3'), + 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' => 'Teenage Dream', 'artist' => 'Katy Perry', 'link' => 'https://open.spotify.com/album/2eQMC9nJE3f3hCNKlYYHL1'), +]; +shuffle($albums); - $content = ''; - foreach ($albums as $album) { - $content = $content . ' +$content = ''; +foreach ($albums as $album) { + $content = $content . ' ' . $album['name'] . ' ' . $album['artist'] . ' '; - } +} - $html = ' +$html = ' @@ -34,6 +32,5 @@ function get_core()
Name
'; - return $html; -} +echo $html; ?> diff --git a/music/explore.php b/music/explore.php index 9b4aa03..71499df 100644 --- a/music/explore.php +++ b/music/explore.php @@ -7,7 +7,11 @@ $html = ''; $client_id = $_ENV['SPOTIFY_CLIENT_ID']; $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: Implement server-side caching for faster load times. @@ -24,9 +28,11 @@ $albums = [ '2eQMC9nJE3f3hCNKlYYHL1' ]; +shuffle($albums); + $content = ''; foreach ($albums as $album_id) { - $data = get_album($access_token, $album_id); + $data = get_album($client_credentials, $album_id); $content = $content . ' ' . $data['name'] . ' @@ -44,7 +50,7 @@ $html = ' Spotify ' . $content . ''; -function get_access_token($client_id, $client_secret) +function get_client_credentials($client_id, $client_secret) { $url = 'https://accounts.spotify.com/api/token'; @@ -80,7 +86,7 @@ function get_access_token($client_id, $client_secret) 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; @@ -89,7 +95,7 @@ function get_album($access_token, $album_id) curl_setopt_array($ch, array( CURLOPT_RETURNTRANSFER => true, 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); } -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 ' + +

Name: ' . $s['song_name'] . ' - ' . $s['artist'] . '

+

Album: ' . $s['album_name'] . '

+
Song ID: ' . $s['song_id'] . '
+
Album ID: ' . $s['album_id'] . '
+ '; + } +} + +get_albums($auth_code, $client_id, $client_secret); +// echo $html; ?> diff --git a/music/index.php b/music/index.php index 41f6505..d852629 100644 --- a/music/index.php +++ b/music/index.php @@ -1,6 +1,6 @@ @@ -14,12 +14,10 @@ exec('php explore.php &');

My Favorite Albums

- +
- +
diff --git a/music/js/switch.js b/music/js/switch.js index 8607ee0..02d88a9 100644 --- a/music/js/switch.js +++ b/music/js/switch.js @@ -1,10 +1,25 @@ -async function modeSwitch() { +async function modeSwitch(mode) { const content = document.getElementById("content"); - var response = await fetch('explore.php'); + console.log(mode); + if (mode == 'explore') { + var response = await fetch('explore.php'); - if (response.status === 200) { - let data = async () => { return await response.text() }; - let text = await data(); - content.innerHTML = text; + if (response.status === 200) { + let data = async () => { return await response.text() }; + let text = await data(); + 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'; } } diff --git a/music/process.php b/music/process.php deleted file mode 100644 index 10e2c0d..0000000 --- a/music/process.php +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/music/test.php b/music/test.php deleted file mode 100644 index bf43174..0000000 --- a/music/test.php +++ /dev/null @@ -1,3 +0,0 @@ -Test

'; -?>