diff --git a/bridges/SpotifyBridge.php b/bridges/SpotifyBridge.php index e03d43a1332..ab093a61e5b 100644 --- a/bridges/SpotifyBridge.php +++ b/bridges/SpotifyBridge.php @@ -37,7 +37,10 @@ class SpotifyBridge extends BridgeAbstract 'name' => 'Spotify URIs', 'type' => 'text', 'required' => true, - 'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ [,spotify:playlist:37i9dQZF1DXcBWIGoYBM5M,spotify:show:6ShFMYxeDNMo15COLObDvC]', + + // spotify:playlist:37i9dQZF1DXcBWIGoYBM5M + // spotify:show:6ShFMYxeDNMo15COLObDvC + 'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ', ], 'albumtype' => [ 'name' => 'Album type', @@ -93,6 +96,25 @@ class SpotifyBridge extends BridgeAbstract private $token = ''; public function collectData() + { + /** + * https://developer.spotify.com/documentation/web-api/concepts/rate-limits + */ + $cacheKey = 'spotify_rate_limit'; + + try { + $this->collectDataInternal(); + } catch (HttpException $e) { + if ($e->getCode() === 429) { + $retryAfter = $e->response->getHeader('Retry-After') ?? (60 * 5); + $this->cache->set($cacheKey, true, $retryAfter); + throw new RateLimitException(sprintf('Rate limited by spotify, try again in %s seconds', $retryAfter)); + } + throw $e; + } + } + + private function collectDataInternal() { $this->fetchAccessToken(); @@ -125,6 +147,27 @@ public function collectData() } } + private function fetchAccessToken() + { + $cacheKey = sprintf('SpotifyBridge:%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret')); + + $token = $this->cache->get($cacheKey); + if ($token) { + $this->token = $token; + } else { + $basicAuth = base64_encode(sprintf('%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret'))); + $json = getContents('https://accounts.spotify.com/api/token', [ + "Authorization: Basic $basicAuth", + ], [ + CURLOPT_POSTFIELDS => 'grant_type=client_credentials', + ]); + $data = Json::decode($json); + $this->token = $data['access_token']; + + $this->cache->set($cacheKey, $this->token, 3600); + } + } + private function getEntriesFromQuery() { $entries = []; @@ -276,27 +319,6 @@ private function getDate($entry) return DateTime::createFromFormat('Y-m-d', $date)->getTimestamp(); } - private function fetchAccessToken() - { - $cacheKey = sprintf('SpotifyBridge:%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret')); - - $token = $this->cache->get($cacheKey); - if ($token) { - $this->token = $token; - } else { - $basicAuth = base64_encode(sprintf('%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret'))); - $json = getContents('https://accounts.spotify.com/api/token', [ - "Authorization: Basic $basicAuth", - ], [ - CURLOPT_POSTFIELDS => 'grant_type=client_credentials', - ]); - $data = Json::decode($json); - $this->token = $data['access_token']; - - $this->cache->set($cacheKey, $this->token, 3600); - } - } - public function getURI() { if (empty($this->uri)) { @@ -346,4 +368,4 @@ public function getIcon() { return 'https://www.scdn.co/i/_global/favicon.png'; } -} +} \ No newline at end of file diff --git a/middlewares/CacheMiddleware.php b/middlewares/CacheMiddleware.php index ae0d0d33eb2..bffde4af235 100644 --- a/middlewares/CacheMiddleware.php +++ b/middlewares/CacheMiddleware.php @@ -44,8 +44,8 @@ public function __invoke(Request $request, $next): Response $response = $next($request); if (in_array($response->getCode(), [403, 429, 500, 503])) { - // Cache these responses for about ~20 mins on average - $this->cache->set($cacheKey, $response, 60 * 15 + rand(1, 60 * 10)); + // Cache these responses for about ~10 mins on average + $this->cache->set($cacheKey, $response, 60 * 5 + rand(1, 60 * 10)); } // For 1% of requests, prune cache