Version 5.1 - All the GraphQL #32
@ -41,11 +41,27 @@ final class Anilist {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const ANILIST_KITSU_WATCHING_STATUS_MAP = [
|
const ANILIST_KITSU_WATCHING_STATUS_MAP = [
|
||||||
'CURRENT' => KAWS::WATCHING,
|
AnimeWatchingStatus::WATCHING => KAWS::WATCHING,
|
||||||
'COMPLETED' => KAWS::COMPLETED,
|
AnimeWatchingStatus::COMPLETED => KAWS::COMPLETED,
|
||||||
'PAUSED' => KAWS::ON_HOLD,
|
AnimeWatchingStatus::ON_HOLD => KAWS::ON_HOLD,
|
||||||
'DROPPED' => KAWS::DROPPED,
|
AnimeWatchingStatus::DROPPED => KAWS::DROPPED,
|
||||||
'PLANNING' => KAWS::PLAN_TO_WATCH,
|
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()
|
public static function getIdToWatchingStatusMap()
|
||||||
@ -67,7 +83,8 @@ final class Anilist {
|
|||||||
'COMPLETED' => MangaReadingStatus::COMPLETED,
|
'COMPLETED' => MangaReadingStatus::COMPLETED,
|
||||||
'PAUSED' => MangaReadingStatus::ON_HOLD,
|
'PAUSED' => MangaReadingStatus::ON_HOLD,
|
||||||
'DROPPED' => MangaReadingStatus::DROPPED,
|
'DROPPED' => MangaReadingStatus::DROPPED,
|
||||||
'PLANNING' => MangaReadingStatus::PLAN_TO_READ
|
'PLANNING' => MangaReadingStatus::PLAN_TO_READ,
|
||||||
|
'REPEATING' => MangaReadingStatus::READING,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,14 +16,20 @@
|
|||||||
|
|
||||||
namespace Aviat\AnimeClient\API\Anilist;
|
namespace Aviat\AnimeClient\API\Anilist;
|
||||||
|
|
||||||
|
use Amp\Artax\Request;
|
||||||
|
use Amp\Artax\Response;
|
||||||
use function Amp\Promise\wait;
|
use function Amp\Promise\wait;
|
||||||
|
|
||||||
use Aviat\AnimeClient\API\{
|
use Aviat\AnimeClient\API\{
|
||||||
Anilist,
|
Anilist,
|
||||||
HummingbirdClient
|
HummingbirdClient
|
||||||
};
|
};
|
||||||
|
use const Aviat\AnimeClient\SESSION_SEGMENT;
|
||||||
|
use Aviat\Ion\Json;
|
||||||
|
use Aviat\Ion\Di\ContainerAware;
|
||||||
|
|
||||||
trait AnilistTrait {
|
trait AnilistTrait {
|
||||||
|
use ContainerAware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The request builder for the MAL API
|
* The request builder for the MAL API
|
||||||
@ -66,27 +72,92 @@ trait AnilistTrait {
|
|||||||
|
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param array $options
|
* @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
|
* Make a request
|
||||||
*
|
*
|
||||||
* @param string $type
|
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param array $options
|
* @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;
|
$logger = NULL;
|
||||||
if ($this->getContainer())
|
if ($this->getContainer())
|
||||||
{
|
{
|
||||||
$logger = $this->container->getLogger('mal-request');
|
$logger = $this->container->getLogger('anilist-request');
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = $this->setUpRequest($url, $options);
|
$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
|
* @param array $options
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function request(string $type, string $url, array $options = []): array
|
protected function postRequest(array $options = []): array
|
||||||
{
|
{
|
||||||
$logger = NULL;
|
$logger = NULL;
|
||||||
if ($this->getContainer())
|
if ($this->getContainer())
|
||||||
@ -119,44 +188,19 @@ trait AnilistTrait {
|
|||||||
$logger = $this->container->getLogger('anilist-request');
|
$logger = $this->container->getLogger('anilist-request');
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $this->getResponse($type, $url, $options);
|
$response = $this->getResponse(Anilist::BASE_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);
|
|
||||||
$validResponseCodes = [200, 201];
|
$validResponseCodes = [200, 201];
|
||||||
|
|
||||||
if ( ! \in_array((int) $response->getStatus(), $validResponseCodes, TRUE))
|
if ( ! \in_array($response->getStatus(), $validResponseCodes, TRUE))
|
||||||
{
|
{
|
||||||
if ($logger)
|
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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
56
src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql
Normal file
56
src/API/Anilist/GraphQL/Queries/UserAnimeList.graphql
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
56
src/API/Anilist/GraphQL/Queries/UserMangaList.graphql
Normal file
56
src/API/Anilist/GraphQL/Queries/UserMangaList.graphql
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -39,127 +39,17 @@ final class Model
|
|||||||
public function __construct(ListItem $listItem)
|
public function __construct(ListItem $listItem)
|
||||||
{
|
{
|
||||||
$this->listItem = $listItem;
|
$this->listItem = $listItem;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAnimeList()
|
public function getAnimeList(): array
|
||||||
{
|
{
|
||||||
$graphQL = <<<GQL
|
return $this->runQuery('UserAnimeList', ['name' => 'timw4mail']);
|
||||||
{
|
|
||||||
MediaListCollection(userId: 103470, type: ANIME) {
|
|
||||||
lists {
|
|
||||||
entries {
|
|
||||||
id
|
|
||||||
mediaId
|
|
||||||
score
|
|
||||||
progress
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GQL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMangaList()
|
public function getMangaList(): array
|
||||||
{
|
{
|
||||||
$graphQL = <<<GQL
|
return $this->runQuery('UserMangaList', ['name' => 'timw4mail']);
|
||||||
{
|
|
||||||
MediaListCollection(userId: 103470, 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GQL;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
27
src/API/Anilist/Transformer/AnimeListTransformer.php
Normal file
27
src/API/Anilist/Transformer/AnimeListTransformer.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
/**
|
||||||
|
* Hummingbird Anime List Client
|
||||||
|
*
|
||||||
|
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
|
||||||
|
*
|
||||||
|
* PHP version 7
|
||||||
|
*
|
||||||
|
* @package HummingbirdAnimeClient
|
||||||
|
* @author Timothy J. Warren <tim@timshomepage.net>
|
||||||
|
* @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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
28
src/API/Anilist/Transformer/MangaListTransformer.php
Normal file
28
src/API/Anilist/Transformer/MangaListTransformer.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
/**
|
||||||
|
* Hummingbird Anime List Client
|
||||||
|
*
|
||||||
|
* An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
|
||||||
|
*
|
||||||
|
* PHP version 7
|
||||||
|
*
|
||||||
|
* @package HummingbirdAnimeClient
|
||||||
|
* @author Timothy J. Warren <tim@timshomepage.net>
|
||||||
|
* @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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -22,10 +22,10 @@ use Aviat\Ion\Enum;
|
|||||||
* Possible values for watching status for the current anime
|
* Possible values for watching status for the current anime
|
||||||
*/
|
*/
|
||||||
final class Anilist extends Enum {
|
final class Anilist extends Enum {
|
||||||
const WATCHING = 'CURRENT';
|
const READING = 'CURRENT';
|
||||||
const COMPLETED = 'COMPLETED';
|
const COMPLETED = 'COMPLETED';
|
||||||
const ON_HOLD = 'PAUSED';
|
const ON_HOLD = 'PAUSED';
|
||||||
const DROPPED = 'DROPPED';
|
const DROPPED = 'DROPPED';
|
||||||
const PLAN_TO_WATCH = 'PLANNING';
|
const PLAN_TO_READ = 'PLANNING';
|
||||||
const REPEATING = 'REPEATING';
|
const REPEATING = 'REPEATING';
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user