From 64a9f41a643512c48b3f4086f52ef69105e1d34c Mon Sep 17 00:00:00 2001 From: Timothy J Warren Date: Wed, 15 Aug 2018 14:05:28 -0400 Subject: [PATCH] Making API requests to Anilist, see #5 --- src/API/Anilist.php | 29 +++- src/API/Anilist/AnilistTrait.php | 128 ++++++++++++------ .../GraphQL/Queries/UserAnimeList.graphql | 56 ++++++++ .../GraphQL/Queries/UserMangaList.graphql | 56 ++++++++ src/API/Anilist/Model.php | 120 +--------------- .../Transformer/AnimeListTransformer.php | 27 ++++ .../Transformer/MangaListTransformer.php | 28 ++++ src/API/Enum/MangaReadingStatus/Anilist.php | 4 +- 8 files changed, 283 insertions(+), 165 deletions(-) create mode 100644 src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql create mode 100644 src/API/Anilist/GraphQL/Queries/UserMangaList.graphql create mode 100644 src/API/Anilist/Transformer/AnimeListTransformer.php create mode 100644 src/API/Anilist/Transformer/MangaListTransformer.php diff --git a/src/API/Anilist.php b/src/API/Anilist.php index ec5bb837..8b413327 100644 --- a/src/API/Anilist.php +++ b/src/API/Anilist.php @@ -41,11 +41,27 @@ final class Anilist { ]; const ANILIST_KITSU_WATCHING_STATUS_MAP = [ - 'CURRENT' => KAWS::WATCHING, - 'COMPLETED' => KAWS::COMPLETED, - 'PAUSED' => KAWS::ON_HOLD, - 'DROPPED' => KAWS::DROPPED, - 'PLANNING' => KAWS::PLAN_TO_WATCH, + AnimeWatchingStatus::WATCHING => KAWS::WATCHING, + AnimeWatchingStatus::COMPLETED => KAWS::COMPLETED, + AnimeWatchingStatus::ON_HOLD => KAWS::ON_HOLD, + AnimeWatchingStatus::DROPPED => KAWS::DROPPED, + AnimeWatchingStatus::PLAN_TO_WATCH => KAWS::PLAN_TO_WATCH, + ]; + + const KITSU_ANILIST_READING_STATUS_MAP = [ + KMRS::READING => MangaReadingStatus::READING, + KMRS::COMPLETED => MangaReadingStatus::COMPLETED, + KMRS::ON_HOLD => MangaReadingStatus::ON_HOLD, + KMRS::DROPPED => MangaReadingStatus::DROPPED, + KMRS::PLAN_TO_READ => MangaReadingStatus::PLAN_TO_READ, + ]; + + const ANILIST_KITSU_READING_STATUS_MAP = [ + MangaReadingStatus::READING => KMRS::READING, + MangaReadingStatus::COMPLETED => KMRS::COMPLETED, + MangaReadingStatus::ON_HOLD => KMRS::ON_HOLD, + MangaReadingStatus::DROPPED => KMRS::DROPPED, + MangaReadingStatus::PLAN_TO_READ => KMRS::PLAN_TO_READ, ]; public static function getIdToWatchingStatusMap() @@ -67,7 +83,8 @@ final class Anilist { 'COMPLETED' => MangaReadingStatus::COMPLETED, 'PAUSED' => MangaReadingStatus::ON_HOLD, 'DROPPED' => MangaReadingStatus::DROPPED, - 'PLANNING' => MangaReadingStatus::PLAN_TO_READ + 'PLANNING' => MangaReadingStatus::PLAN_TO_READ, + 'REPEATING' => MangaReadingStatus::READING, ]; } } \ No newline at end of file diff --git a/src/API/Anilist/AnilistTrait.php b/src/API/Anilist/AnilistTrait.php index bebbf04a..a9fae0c4 100644 --- a/src/API/Anilist/AnilistTrait.php +++ b/src/API/Anilist/AnilistTrait.php @@ -16,14 +16,20 @@ namespace Aviat\AnimeClient\API\Anilist; +use Amp\Artax\Request; +use Amp\Artax\Response; use function Amp\Promise\wait; use Aviat\AnimeClient\API\{ Anilist, HummingbirdClient }; +use const Aviat\AnimeClient\SESSION_SEGMENT; +use Aviat\Ion\Json; +use Aviat\Ion\Di\ContainerAware; trait AnilistTrait { + use ContainerAware; /** * The request builder for the MAL API @@ -66,27 +72,92 @@ trait AnilistTrait { * @param string $url * @param array $options - * @return \Amp\Artax\Response + * @return Request */ - public function setUpRequest(string $url, array $options = []) + public function setUpRequest(string $url, array $options = []): Request { - // @TODO Implement + $config = $this->getContainer()->get('config'); + $anilistConfig = $config->get('anilist'); + + $request = $this->requestBuilder->newRequest('POST', $url); + $sessionSegment = $this->getContainer() + ->get('session') + ->getSegment(SESSION_SEGMENT); + + $authenticated = $sessionSegment->get('auth_token') !== NULL; + + if ($authenticated) + { + $request = $request->setAuth('bearer', $anilistConfig['access_token']); + } + + if (array_key_exists('form_params', $options)) { + $request = $request->setFormFields($options['form_params']); + } + + if (array_key_exists('query', $options)) { + $request = $request->setQuery($options['query']); + } + + if (array_key_exists('body', $options)) { + $request = $request->setJsonBody($options['body']); + } + + if (array_key_exists('headers', $options)) { + $request = $request->setHeaders($options['headers']); + } + + return $request->getFullRequest(); + } + + /** + * Run a GraphQL API query + * + * @param string $name + * @param array $variables + * @return array + */ + public function runQuery(string $name, array $variables = []): array + { + $file = realpath(__DIR__ . "/GraphQL/Queries/{$name}.graphql"); + if ( ! file_exists($file)) + { + throw new \LogicException('GraphQL query file does not exist.'); + } + + // $query = str_replace(["\t", "\n"], ' ', file_get_contents($file)); + $query = file_get_contents($file); + $body = [ + 'query' => $query + ]; + + if ( ! empty($variables)) + { + $body['variables'] = []; + foreach($variables as $key => $val) + { + $body['variables'][$key] = $val; + } + } + + return $this->postRequest([ + 'body' => $body + ]); } /** * Make a request * - * @param string $type * @param string $url * @param array $options - * @return \Amp\Artax\Response + * @return Response */ - private function getResponse(string $type, string $url, array $options = []) + private function getResponse(string $url, array $options = []): Response { $logger = NULL; if ($this->getContainer()) { - $logger = $this->container->getLogger('mal-request'); + $logger = $this->container->getLogger('anilist-request'); } $request = $this->setUpRequest($url, $options); @@ -104,14 +175,12 @@ trait AnilistTrait { } /** - * Make a request + * Remove some boilerplate for post requests * - * @param string $type - * @param string $url * @param array $options * @return array */ - private function request(string $type, string $url, array $options = []): array + protected function postRequest(array $options = []): array { $logger = NULL; if ($this->getContainer()) @@ -119,44 +188,19 @@ trait AnilistTrait { $logger = $this->container->getLogger('anilist-request'); } - $response = $this->getResponse($type, $url, $options); - - if ((int) $response->getStatus() > 299 OR (int) $response->getStatus() < 200) - { - if ($logger) - { - $logger->warning('Non 200 response for api call', (array)$response->getBody()); - } - } - - return XML::toArray(wait($response->getBody())); - } - - /** - * Remove some boilerplate for post requests - * - * @param mixed ...$args - * @return array - */ - protected function postRequest(...$args): array - { - $logger = NULL; - if ($this->getContainer()) - { - $logger = $this->container->getLogger('anilist-request'); - } - - $response = $this->getResponse('POST', ...$args); + $response = $this->getResponse(Anilist::BASE_URL, $options); $validResponseCodes = [200, 201]; - if ( ! \in_array((int) $response->getStatus(), $validResponseCodes, TRUE)) + if ( ! \in_array($response->getStatus(), $validResponseCodes, TRUE)) { if ($logger) { - $logger->warning('Non 201 response for POST api call', (array)$response->getBody()); + $logger->warning('Non 200 response for POST api call', (array)$response->getBody()); } } - return XML::toArray($response->getBody()); + // dump(wait($response->getBody())); + + return Json::decode(wait($response->getBody())); } } \ No newline at end of file diff --git a/src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql b/src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql new file mode 100644 index 00000000..ea25ddca --- /dev/null +++ b/src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql @@ -0,0 +1,56 @@ +query ($name: String) { + MediaListCollection(userName: $name, type: ANIME) { + lists { + entries { + id + mediaId + score + progress + repeat + private + notes + status + media { + id + idMal + title { + romaji + english + native + userPreferred + } + type + format + status + episodes + season + genres + synonyms + countryOfOrigin + source + trailer { + id + } + coverImage { + large + medium + } + bannerImage + tags { + id + } + externalLinks { + id + } + mediaListEntry { + id + } + } + user { + id + } + } + } + } +} + diff --git a/src/API/Anilist/GraphQL/Queries/UserMangaList.graphql b/src/API/Anilist/GraphQL/Queries/UserMangaList.graphql new file mode 100644 index 00000000..39ddbb41 --- /dev/null +++ b/src/API/Anilist/GraphQL/Queries/UserMangaList.graphql @@ -0,0 +1,56 @@ +{query ($name: String) { + MediaListCollection(userName: $name, type: MANGA) { + lists { + entries { + id + mediaId + score + progress + progressVolumes + repeat + private + notes + status + media { + id + idMal + title { + romaji + english + native + userPreferred + } + type + format + status + chapters + volumes + genres + synonyms + countryOfOrigin + source + trailer { + id + } + coverImage { + large + medium + } + bannerImage + tags { + id + } + externalLinks { + id + } + mediaListEntry { + id + } + } + user { + id + } + } + } + } +} diff --git a/src/API/Anilist/Model.php b/src/API/Anilist/Model.php index a61854c7..25e93a6b 100644 --- a/src/API/Anilist/Model.php +++ b/src/API/Anilist/Model.php @@ -39,127 +39,17 @@ final class Model public function __construct(ListItem $listItem) { $this->listItem = $listItem; + } - public function getAnimeList() + public function getAnimeList(): array { - $graphQL = <<runQuery('UserAnimeList', ['name' => 'timw4mail']); } - public function getMangaList() + public function getMangaList(): array { - $graphQL = <<runQuery('UserMangaList', ['name' => 'timw4mail']); } // ------------------------------------------------------------------------- diff --git a/src/API/Anilist/Transformer/AnimeListTransformer.php b/src/API/Anilist/Transformer/AnimeListTransformer.php new file mode 100644 index 00000000..18aece35 --- /dev/null +++ b/src/API/Anilist/Transformer/AnimeListTransformer.php @@ -0,0 +1,27 @@ + + * @copyright 2015 - 2018 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.0 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\API\Anilist\Transformer; + +use Aviat\Ion\Transformer\AbstractTransformer; + +class AnimeListTransformer extends AbstractTransformer { + + public function transform($item) + { + + } +} \ No newline at end of file diff --git a/src/API/Anilist/Transformer/MangaListTransformer.php b/src/API/Anilist/Transformer/MangaListTransformer.php new file mode 100644 index 00000000..cd8a7f35 --- /dev/null +++ b/src/API/Anilist/Transformer/MangaListTransformer.php @@ -0,0 +1,28 @@ + + * @copyright 2015 - 2018 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 4.0 + * @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient + */ + +namespace Aviat\AnimeClient\API\Anilist\Transformer; + +use Aviat\Ion\Transformer\AbstractTransformer; + +class MangaListTransformer extends AbstractTransformer +{ + + public function transform($item) + { + + } +} \ No newline at end of file diff --git a/src/API/Enum/MangaReadingStatus/Anilist.php b/src/API/Enum/MangaReadingStatus/Anilist.php index c2466045..2dbc6bec 100644 --- a/src/API/Enum/MangaReadingStatus/Anilist.php +++ b/src/API/Enum/MangaReadingStatus/Anilist.php @@ -22,10 +22,10 @@ use Aviat\Ion\Enum; * Possible values for watching status for the current anime */ final class Anilist extends Enum { - const WATCHING = 'CURRENT'; + const READING = 'CURRENT'; const COMPLETED = 'COMPLETED'; const ON_HOLD = 'PAUSED'; const DROPPED = 'DROPPED'; - const PLAN_TO_WATCH = 'PLANNING'; + const PLAN_TO_READ = 'PLANNING'; const REPEATING = 'REPEATING'; } \ No newline at end of file