1
0
mirror of https://github.com/devfake/flox.git synced 2024-11-15 06:32:34 +01:00

Fix tmdb limit reaching (#47)

* Fix tmdb limit reaching

* code review

* remove unused fixtures
This commit is contained in:
Tim Meier 2017-02-13 10:19:37 +01:00 committed by Tim Meier
parent 3000e3f222
commit 2f9f82e5b4
4 changed files with 103 additions and 70 deletions

View File

@ -8,6 +8,7 @@
use GuzzleHttp\Client;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use GuzzleHttp\Exception\ClientException;
class TMDB {
@ -37,12 +38,8 @@
*/
public function search($title)
{
$response = $this->client->get($this->base . '/3/search/multi', [
'query' => [
'api_key' => $this->apiKey,
'query' => $title,
'language' => strtolower($this->translation)
]
$response = $this->requestTmdb($this->base . '/3/search/multi', [
'query' => $title
]);
return $this->createItems($response);
@ -79,12 +76,7 @@
*/
private function searchSuggestions($mediaType, $tmdbID, $type)
{
$response = $this->client->get($this->base . '/3/' . $mediaType . '/' . $tmdbID . '/' . $type, [
'query' => [
'api_key' => $this->apiKey,
'language' => strtolower($this->translation)
]
]);
$response = $this->requestTmdb($this->base . '/3/' . $mediaType . '/' . $tmdbID . '/' . $type);
return collect($this->createItems($response, $mediaType));
}
@ -97,12 +89,7 @@
public function upcoming()
{
return Cache::remember('upcoming', $this->untilEndOfDay(), function() {
$response = $this->client->get($this->base . '/3/movie/upcoming', [
'query' => [
'api_key' => $this->apiKey,
'language' => strtolower($this->translation)
]
]);
$response = $this->requestTmdb($this->base . '/3/movie/upcoming');
$items = collect($this->createItems($response, 'movie'));
@ -156,12 +143,7 @@
private function fetchPopular($mediaType)
{
return $this->client->get($this->base . '/3/' . $mediaType . '/popular', [
'query' => [
'api_key' => $this->apiKey,
'language' => strtolower($this->translation)
]
]);
return $this->requestTmdb($this->base . '/3/' . $mediaType . '/popular');
}
/**
@ -202,6 +184,34 @@
return $items;
}
private function requestTmdb($url, $query = [])
{
$query = array_merge($query, [
'api_key' => $this->apiKey,
'language' => strtolower($this->translation)
]);
try {
$response = $this->client->get($url, [
'query' => $query
]);
if($this->hasLimitRemaining($response)) {
return $response;
}
} catch (ClientException $e) {
// wtf? throws exception because of "bad" statuscode?
$response = $e->getResponse();
if($this->hasLimitRemaining($response)) {
return $response;
}
}
sleep(1);
return $this->requestTmdb($url, $query);
}
/**
* Get full movie or tv details.
*
@ -211,20 +221,9 @@
*/
public function details($tmdbId, $mediaType)
{
$response = $this->client->get($this->base . '/3/' . $mediaType . '/' . $tmdbId, [
'query' => [
'api_key' => $this->apiKey,
'language' => strtolower($this->translation)
]
]);
$response = $this->requestTmdb($this->base . '/3/' . $mediaType . '/' . $tmdbId);
if($this->hasLimitRemaining($response)) {
return json_decode($response->getBody());
}
// After 10 seconds the TMDB request limit is resetted.
sleep(10);
return $this->details($tmdbId, $mediaType);
return json_decode($response->getBody());
}
/**
@ -237,12 +236,7 @@
private function tvSeasonsCount($id, $mediaType)
{
if($mediaType == 'tv') {
$response = $this->client->get($this->base . '/3/tv/' . $id, [
'query' => [
'api_key' => $this->apiKey,
'language' => strtolower($this->translation)
]
]);
$response = $this->requestTmdb($this->base . '/3/tv/' . $id);
$seasons = collect(json_decode($response->getBody())->seasons);
@ -267,12 +261,7 @@
$data = [];
for($i = 1; $i <= $seasons; $i++) {
$response = $this->client->get($this->base . '/3/tv/' . $id . '/season/' . $i, [
'query' => [
'api_key' => $this->apiKey,
'language' => strtolower($this->translation)
]
]);
$response = $this->requestTmdb($this->base . '/3/tv/' . $id . '/season/' . $i);
$data[$i] = json_decode($response->getBody());
}
@ -290,28 +279,18 @@
{
$response = $this->fetchAlternativeTitles($item);
if($this->hasLimitRemaining($response)) {
$body = json_decode($response->getBody());
$body = json_decode($response->getBody());
if(property_exists($body, 'titles') || property_exists($body, 'results')) {
return isset($body->titles) ? $body->titles : $body->results;
}
return [];
if(property_exists($body, 'titles') || property_exists($body, 'results')) {
return isset($body->titles) ? $body->titles : $body->results;
}
// After 10 seconds the TMDB request limit is resetted.
sleep(10);
return $this->getAlternativeTitles($item);
return [];
}
public function fetchAlternativeTitles($item)
{
return $this->client->get($this->base . '/3/' . $item['media_type'] . '/' . $item['tmdb_id'] . '/alternative_titles', [
'query' => [
'api_key' => $this->apiKey
]
]);
return $this->requestTmdb($this->base . '/3/' . $item['media_type'] . '/' . $item['tmdb_id'] . '/alternative_titles');
}
/**
@ -371,11 +350,15 @@
/**
* @param $response
* @return int
* @return boolean
*/
public function hasLimitRemaining($response)
{
return (int) $response->getHeader('X-RateLimit-Remaining')[0] > 1;
if($response->getStatusCode() == 429) {
return false;
}
return ((int) $response->getHeader('X-RateLimit-Remaining')[0]) > 1;
}
/**

View File

@ -128,4 +128,4 @@
$alternativeTitleMock = $this->mock(AlternativeTitleService::class);
$alternativeTitleMock->shouldReceive('create')->once()->andReturn(true);
}
}
}

View File

@ -56,6 +56,26 @@
$this->assertArrayNotHasKey('rating', $trending[1]);
}
/** @test */
public function it_should_respect_request_limit()
{
$fixture = $this->tmdbFixtures('multi');
$mock = new MockHandler([
new Response(429, []),
new Response(200, ['X-RateLimit-Remaining' => [40]], $fixture),
]);
$handler = HandlerStack::create($mock);
$this->app->instance(Client::class, new Client(['handler' => $handler]));
$tmdb = app(TMDB::class);
$result = $tmdb->search('Avatar - Legend of Korra');
$this->assertCount(1, $result);
$this->assertArrayHasKey('tmdb_id', $result[0]);
}
private function in_array_r($item , $array){
return (bool) preg_match('/"' . $item . '"/i' , json_encode($array));
}
@ -63,11 +83,11 @@
private function createGuzzleMock($fixture, $fixture2 = null)
{
$mock = new MockHandler([
new Response(200, [], $fixture),
new Response(200, [], $fixture2),
new Response(200, ['X-RateLimit-Remaining' => [40]], $fixture),
new Response(200, ['X-RateLimit-Remaining' => [40]], $fixture2),
]);
$handler = HandlerStack::create($mock);
$this->app->instance(Client::class, new Client(['handler' => $handler]));
}
}
}

30
backend/tests/fixtures/tmdb/multi.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
"page": 1,
"results": [
{
"poster_path": "\/8uOOycL6r4vqOT8tgw4behO5MmB.jpg",
"popularity": 4.791115,
"id": 33880,
"overview": "The Legend of Korra is an American animated television series that premiered on the Nickelodeon television network in 2012. It was created by Bryan Konietzko and Michael Dante DiMartino as a sequel to their series Avatar: The Last Airbender, which aired on Nickelodeon from 2005 to 2008. Several people involved with creating Avatar, including designer Joaquim Dos Santos and composers Jeremy Zuckerman and Benjamin Wynn, returned to work on The Legend of Korra.\n\nThe series is set in a fictional universe where some people can manipulate, or \"bend\", the elements of water, earth, fire, or air. Only one person, the \"Avatar\", can bend all four elements, and is responsible for maintaining balance in the world. The series follows Avatar Korra, the successor of Aang from the previous series, as she faces political and spiritual unrest in a modernizing world.\n\nThe series, whose style is strongly influenced by Japanese animation, has been a critical and commercial success. It obtained the highest audience total for an animated series in the United States in 2012. The series was praised by reviewers for its high production values and for addressing difficult sociopolitical issues such as social unrest and terrorism. It was initially conceived as a miniseries of 12 episodes, but it is now set to run for 52 episodes separated into four seasons, each of which tells a separate story.",
"backdrop_path": "\/r1oTzR9Ke7pICxe1eiP8ZjoGJju.jpg",
"vote_average": 7.52,
"media_type": "tv",
"first_air_date": "2012-04-14",
"origin_country": [
"US"
],
"genre_ids": [
10765,
16,
18,
10751
],
"original_language": "en",
"vote_count": 44,
"name": "The Legend of Korra",
"original_name": "The Legend of Korra"
}
],
"total_results": 1,
"total_pages": 1
}