Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
5 changed files with 27 additions and 290 deletions
Showing only changes of commit 9bd5d62ca7 - Show all commits

View File

@ -84,18 +84,6 @@ class KitsuModel {
return false;
}
public function getAnimeGenres($animeId): array
{
return $this->getGenres('anime', $animeId);
}
public function getMangaGenres($mangaId): array
{
return $this->getGenres('manga', $mangaId);
}
public function getAnime(string $animeId): array
{
$baseData = $this->getRawAnimeData($animeId);
@ -121,7 +109,7 @@ class KitsuModel {
'media_type' => 'Anime',
'status' => $status,
],
'include' => 'media,user',
'include' => 'media',
'page' => [
'offset' => 0,
'limit' => 200
@ -132,9 +120,9 @@ class KitsuModel {
$data = $this->getRequest('library-entries', $options);
foreach($data['data'] as &$item)
foreach($data['data'] as $i => &$item)
{
$item['anime'] = $this->getRawAnimeData($item['relationships']['media']['data']['id']);
$item['anime'] = $data['included'][$i];
}
$transformed = $this->animeListTransformer->transformCollection($data['data']);

View File

@ -120,7 +120,7 @@ trait KitsuTrait {
}
/**
* Remove some boilerplate for get requests
* Remove some boilerplate for post requests
*
* @param array $args
* @return array
@ -129,4 +129,15 @@ trait KitsuTrait {
{
return $this->request('POST', ...$args);
}
/**
* Remove some boilerplate for delete requests
*
* @param array $args
* @return array
*/
protected function deleteRequest(...$args): array
{
return $this->request('DELETE', ...$args);
}
}

View File

@ -33,18 +33,18 @@ class AnimeListTransformer extends AbstractTransformer {
public function transform($item)
{
/* ?><pre><?= print_r($item, TRUE) ?></pre><?php
die();*/
// die(); */
$anime =& $item['anime'];
$genres = $item['anime']['genres'] ?? [];
$rating = (int) 2 * $item['attributes']['rating'];
$total_episodes = is_numeric($anime['episodeCount'])
? $anime['episodeCount']
$total_episodes = array_key_exists('episodeCount', $item['anime'])
? (int) $anime['episodeCount']
: '-';
$alternate_title = NULL;
if (array_key_exists('en_jp', $anime['titles']))
if (array_key_exists('titles', $item['anime']) && array_key_exists('en_jp', $anime['titles']))
{
// If the alternate title is very similar, or
// a subset of the main title, don't list the
@ -62,21 +62,21 @@ die();*/
'episodes' => [
'watched' => $item['attributes']['progress'],
'total' => $total_episodes,
'length' => $anime['episodeLength'],
'length' => $anime['attributes']['episodeLength'],
],
'airing' => [
'status' => $anime['status'] ?? '',
'started' => $anime['startDate'],
'ended' => $anime['endDate']
'started' => $anime['attributes']['startDate'],
'ended' => $anime['attributes']['endDate']
],
'anime' => [
'age_rating' => $anime['ageRating'],
'title' => $anime['canonicalTitle'],
'age_rating' => $anime['attributes']['ageRating'],
'title' => $anime['attributes']['canonicalTitle'],
'alternate_title' => $alternate_title,
'slug' => $item['relationships']['media']['data']['id'],//$anime['slug'],
'url' => $anime['url'] ?? '',
'type' => $anime['showType'],
'image' => $anime['posterImage']['small'],
'url' => $anime['attributes']['url'] ?? '',
'type' => $anime['attributes']['showType'],
'image' => $anime['attributes']['posterImage']['small'],
'genres' => $genres,
],
'watching_status' => $item['attributes']['status'],

View File

@ -16,23 +16,11 @@
namespace Aviat\AnimeClient\Model;
use Aviat\AnimeClient\AnimeClient;
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
use Aviat\Ion\Model;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use Psr\Http\Message\ResponseInterface;
/**
* Base model for api interaction
*
* @method ResponseInterface get(string $uri, array $options);
* @method ResponseInterface delete(string $uri, array $options);
* @method ResponseInterface head(string $uri, array $options);
* @method ResponseInterface options(string $uri, array $options);
* @method ResponseInterface patch(string $uri, array $options);
* @method ResponseInterface post(string $uri, array $options);
* @method ResponseInterface put(string $uri, array $options);
*/
class API extends Model {
@ -44,24 +32,6 @@ class API extends Model {
*/
protected $config;
/**
* Base url for making api requests
* @var string
*/
protected $base_url = '';
/**
* The Guzzle http client object
* @var object
*/
protected $client;
/**
* Cookie jar object for api requests
* @var object
*/
protected $cookieJar;
/**
* Cache manager
* @var \Aviat\Ion\Cache\CacheInterface
@ -83,87 +53,6 @@ class API extends Model {
{
$this->container = $container;
$this->config = $container->get('config');
$this->cache = $container->get('cache');
$this->init();
}
/**
* Set up the class properties
*
* @return void
*/
protected function init()
{
$this->cookieJar = new CookieJar();
$this->client = new Client([
'base_uri' => $this->base_url,
'cookies' => TRUE,
'http_errors' => FALSE,
'defaults' => array_merge([
'cookies' => $this->cookieJar,
'headers' => [
'User-Agent' => "Tim's Anime Client/4.0",
'Accept-Encoding' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json'
],
'timeout' => 25,
'connect_timeout' => 25
], $this->connectionDefaults)
]);
}
/**
* Magic methods to call guzzle api client
*
* @param string $method
* @param array $args
* @return ResponseInterface|null
*/
public function __call($method, $args)
{
$valid_methods = [
'get',
'getAsync',
'delete',
'deleteAsync',
'head',
'headAsync',
'options',
'optionsAsync',
'patch',
'patchAsync',
'post',
'postAsync',
'put',
'putAsync'
];
if ( ! in_array($method, $valid_methods))
{
return NULL;
}
array_unshift($args, strtoupper($method));
return call_user_func_array([$this->client, 'request'], $args);
}
/**
* Get the data for the specified library entry
*
* @param string $id
* @param string $status
* @return array
*/
public function get_library_item($id, $status)
{
$data = $this->_get_list_from_api($status);
$index_array = array_column($data, 'id');
$key = array_search($id, $index_array);
return $key !== FALSE
? $data[$key]
: [];
}
/**
@ -185,18 +74,5 @@ class API extends Model {
array_multisort($sort, SORT_ASC, $array);
}
/**
* Dummy function that should be abstract. Is not abstract because
* this class is used concretely for authorizing API calls
*
* @TODO Refactor, and make this abstract
* @param string $status
* @return array
*/
protected function _get_list_from_api(string $status): array
{
return [];
}
}
// End of BaseApiModel.php

View File

@ -32,12 +32,6 @@ class Anime extends API {
const ON_HOLD = 'On Hold';
const COMPLETED = 'Completed';
/**
* The base url for api requests
* @var string $base_url
*/
protected $base_url = "https://kitsu.io/api/edge/";
/**
* Map of API status constants to display constants
* @var array
@ -60,91 +54,6 @@ class Anime extends API {
$this->kitsuModel = $container->get('kitsu-model');
}
/**
* Update the selected anime
*
* @param array $data
* @return array|false
*/
public function update($data)
{
$auth = $this->container->get('auth');
if ( ! $auth->is_authenticated() OR ! array_key_exists('id', $data))
{
return FALSE;
}
$id = $data['id'];
$data['auth_token'] = $auth->get_auth_token();
$response = $this->client->post("libraries/{$id}", [
'form_params' => $data
]);
return [
'statusCode' => $response->getStatusCode(),
'body' => Json::decode($response->getBody(), TRUE)
];
}
/**
* Remove an anime from a list
*
* @param array $data
* @return array|false
*/
public function delete($data)
{
$auth = $this->container->get('auth');
if ( ! $auth->is_authenticated() OR ! array_key_exists('id', $data))
{
return FALSE;
}
$id = $data['id'];
$data['auth_token'] = $auth->get_auth_token();
$response = $this->client->post("libraries/{$id}/remove", [
'form_params' => $data
]);
return [
'statusCode' => $response->getStatusCode(),
'body' => Json::decode($response->getBody(), TRUE)
];
}
/**
* Get the full set of anime lists
*
* @return array
*/
public function get_all_lists()
{
$output = [
self::WATCHING => [],
self::PLAN_TO_WATCH => [],
self::ON_HOLD => [],
self::DROPPED => [],
self::COMPLETED => [],
];
$data = $this->_get_list_from_api();
foreach ($data as $datum)
{
$output[$this->const_map[$datum['watching_status']]][] = $datum;
}
// Sort anime by name
foreach ($output as &$status_list)
{
$this->sort_by_name($status_list, 'anime');
}
return $output;
}
/**
* Get a category out of the full list
*
@ -172,52 +81,5 @@ class Anime extends API {
{
return $this->kitsuModel->getAnime($anime_id);
}
/**
* Search for anime by name
*
* @param string $name
* @return array
* @throws \RuntimeException
*/
public function search($name)
{
$logger = $this->container->getLogger('default');
$config = [
'query' => [
'query' => $name
]
];
$response = $this->get('search/anime', $config);
if ((int) $response->getStatusCode() !== 200)
{
$logger->warning("Non 200 response for search api call");
$logger->warning($response->getBody());
throw new \RuntimeException($response->getEffectiveUrl());
}
return Json::decode($response->getBody(), TRUE);
}
/**
* Get the full list from the api
*
* @return array
*/
public function get_raw_list()
{
$config = [
'allow_redirects' => FALSE
];
$username = $this->config->get('hummingbird_username');
$response = $this->get("users/{$username}/library", $config);
return Json::decode($response->getBody(), TRUE);
}
}
// End of AnimeModel.php