diff options
Diffstat (limited to 'src/SpotifyApiClient.php')
| -rw-r--r-- | src/SpotifyApiClient.php | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/SpotifyApiClient.php b/src/SpotifyApiClient.php new file mode 100644 index 0000000..a78f05b --- /dev/null +++ b/src/SpotifyApiClient.php @@ -0,0 +1,140 @@ +<?php + +declare(strict_types=1); + +namespace TCB; + +use TCB\TokenManager; +use TCB\HistoryStorage; + +final class SpotifyApiClient +{ + public function __construct( + private readonly TokenManager $tokenManager, + private readonly HistoryStorage $historyStorage, + ) {} + + public function pickRandomSongFromPlaylist(string $playlistName): array + { + echo "Picking a random song from the playlist $playlistName.\n"; + + if ( + !array_key_exists($playlistName, $this->historyStorage->playlists) + || $this->historyStorage->playlists[$playlistName] === '' + ) { + $this->getPlaylistID($playlistName); + } + + $items = $this->getPlaylistItems($this->historyStorage->playlists[$playlistName]); + + if (!count($items)) { + echo "Playlist appears empty.\n"; + exit(1); + } + + $items = array_values(array_filter($items, function (array $item): bool { + return !array_key_exists($item['id'], $this->historyStorage->history); + })); + + if (!count($items)) { + echo "No songs left to pick.\n"; + exit(1); + } + + $key = array_rand($items); + + $song = $items[$key]; + + $this->historyStorage->saveSong($song); + + return $song; + } + + private function getPlaylistID(string $playlistName): void + { + echo "Looking up the Spotify playlist ID.\n"; + + $url = 'https://api.spotify.com/v1/me/playlists?limit=50'; + + $ch = curl_init(); + + while ($url !== null) { + curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_HTTPGET => true, + CURLOPT_HTTPHEADER => [ + "Authorization: Bearer {$this->tokenManager->getAccessToken()}", + ], + CURLOPT_RETURNTRANSFER => true, + ]); + + $response = curl_exec($ch); + $statusCode = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); + + if ($statusCode !== 200) { + echo "Non-200 response from Spotify: $statusCode $response\n"; + exit(1); + } + + $data = json_decode($response, true) ?? []; + + foreach ($data['items'] ?? [] as $item) { + if ($item['name'] === $playlistName) { + $this->historyStorage->playlists[$playlistName] = $item['id']; + $this->historyStorage->save(); + + return; + } + } + + $url = $data['next'] ?? null; + } + + echo "Unable to find a playlist named $playlistName.\n"; + exit(1); + } + + private function getPlaylistItems(string $playlistID): array + { + $items = []; + + $query = http_build_query([ + 'fields' => 'next,items(item(id,name,artists(name)))', + ]); + + $url = "https://api.spotify.com/v1/playlists/$playlistID/items?limit=50&$query"; + + $ch = curl_init(); + + while ($url !== null) { + curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_HTTPGET => true, + CURLOPT_HTTPHEADER => [ + "Authorization: Bearer {$this->tokenManager->getAccessToken()}", + ], + CURLOPT_RETURNTRANSFER => true, + ]); + + $response = curl_exec($ch); + $statusCode = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); + + if ($statusCode !== 200) { + echo "Non-200 response from Spotify: $statusCode $response\n"; + exit(1); + } + + $data = json_decode($response, true) ?? []; + + foreach ($data['items'] ?? [] as $item) { + if (isset($item['item'])) { + $items[] = $item['item']; + } + } + + $url = $data['next'] ?? null; + } + + return $items; + } +} |
