fix(spotify): detect rate limiting (#4253)

This commit is contained in:
Dag 2024-09-03 07:02:37 +02:00 committed by GitHub
parent 3dc8b65a0b
commit 293d04f296
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 25 deletions

View file

@ -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 @@ class SpotifyBridge extends BridgeAbstract
}
}
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 @@ class SpotifyBridge extends BridgeAbstract
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 @@ class SpotifyBridge extends BridgeAbstract
{
return 'https://www.scdn.co/i/_global/favicon.png';
}
}
}

View file

@ -44,8 +44,8 @@ class CacheMiddleware implements Middleware
$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