summaryrefslogtreecommitdiff
path: root/src/SpotifyApiClient.php
diff options
context:
space:
mode:
authorDavid T. Sadler <davidtsadler@googlemail.com>2026-08-09 20:04:39 +0100
committerDavid T. Sadler <davidtsadler@googlemail.com>2026-08-09 20:04:39 +0100
commitb9c4f1dcf1333c14e2d1b67561ec7a5f955baa6e (patch)
tree610536953be739d0778f19c90c477f080a24718a /src/SpotifyApiClient.php
Initial commitHEADmain
Diffstat (limited to 'src/SpotifyApiClient.php')
-rw-r--r--src/SpotifyApiClient.php140
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;
+ }
+}