Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
10 changed files with 277 additions and 81 deletions
Showing only changes of commit 1ab47ca03a - Show all commits

View File

@ -186,12 +186,12 @@ return [
'anilist-redirect' => [
'path' => '/anilist-redirect',
'action' => 'anilistRedirect',
'controller' => DEFAULT_CONTROLLER,
'controller' => DEFAULT_CONTROLLER,
],
'anilist-oauth' => [
'path' => '/anilist-oauth',
'action' => 'anilistCallback',
'controller' => DEFAULT_CONTROLLER,
'controller' => DEFAULT_CONTROLLER,
],
'image_proxy' => [
'path' => '/public/images/{type}/{file}',
@ -209,6 +209,12 @@ return [
'controller' => DEFAULT_CONTROLLER,
'verb' => 'get',
],
'settings' => [
'path' => '/settings',
'action' => 'settings',
'controller' => DEFAULT_CONTROLLER,
'verb' => 'get',
],
'login' => [
'path' => '/login',
'action' => 'login',

View File

@ -144,6 +144,20 @@ return function (array $configArray = []) {
$model->setRequestBuilder($requestBuilder);
return $model;
});
$container->set('anilist-model', function($container) {
$requestBuilder = new Anilist\AnilistRequestBuilder();
$requestBuilder->setLogger($container->getLogger('anilist-request'));
$listItem = new Anilist\ListItem();
$listItem->setContainer($container);
$listItem->setRequestBuilder($requestBuilder);
$model = new Anilist\Model($listItem);
$model->setContainer($container);
$model->setRequestBuilder($requestBuilder);
return $model;
});
$container->set('api-model', function($container) {
return new Model\API($container);

View File

@ -5,6 +5,8 @@ namespace Aviat\AnimeClient;
$whose = $config->get('whose_list') . "'s ";
$lastSegment = $urlGenerator->lastSegment();
$extraSegment = $lastSegment === 'list' ? '/list' : '';
$hasAnime = stripos($_SERVER['REQUEST_URI'], 'anime') !== FALSE;
$hasManga = stripos($_SERVER['REQUEST_URI'], 'manga') !== FALSE;
?>
<div id="main-nav" class="flex flex-align-end flex-wrap">
@ -69,7 +71,7 @@ $extraSegment = $lastSegment === 'list' ? '/list' : '';
</span>
</div>
<nav>
<?php if ($container->get('util')->isViewPage()): ?>
<?php if ($container->get('util')->isViewPage() && ($hasAnime || $hasManga)): ?>
<?= $helper->menu($menu_name) ?>
<br />
<ul>

View File

@ -17,7 +17,7 @@ try
(new Console([
'cache:clear' => Command\CacheClear::class,
'cache:refresh' => Command\CachePrime::class,
'lists:sync' => Command\SyncLists::class,
// 'lists:sync' => Command\SyncLists::class,
]))->run();
}
catch (\Exception $e)

View File

@ -48,6 +48,9 @@ $di = require $APP_DIR . '/bootstrap.php';
$config = loadToml($CONF_DIR);
$config_array = array_merge($base_config, $config);
// User config
$config_array['default_config'] = $base_config;
$config_array['user_config_settings'] = $config;
$container = $di($config_array);

View File

@ -26,8 +26,8 @@ final class AnilistRequestBuilder extends APIRequestBuilder {
* The base url for api requests
* @var string $base_url
*/
protected $baseUrl = 'https://kitsu.io/api/edge/';
protected $baseUrl = 'https://graphql.anilist.co';
/**
* Valid HTTP request methods
* @var array
@ -41,9 +41,7 @@ final class AnilistRequestBuilder extends APIRequestBuilder {
*/
protected $defaultHeaders = [
'User-Agent' => USER_AGENT,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'CLIENT_ID' => 'dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd',
'CLIENT_SECRET' => '54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
];
}

View File

@ -14,7 +14,7 @@
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\API\MAL;
namespace Aviat\AnimeClient\API\Anilist;
use function Amp\Promise\wait;
@ -52,7 +52,7 @@ trait AnilistTrait {
/**
* Set the request builder object
*
* @param MALRequestBuilder $requestBuilder
* @param AnilistRequestBuilder $requestBuilder
* @return self
*/
public function setRequestBuilder($requestBuilder): self
@ -63,31 +63,14 @@ trait AnilistTrait {
/**
* Create a request object
*
* @param string $type
* @param string $url
* @param array $options
* @return \Amp\Artax\Response
*/
public function setUpRequest(string $type, string $url, array $options = [])
public function setUpRequest(string $url, array $options = [])
{
$config = $this->container->get('config');
$request = $this->requestBuilder
->newRequest($type, $url)
->setBasicAuth($config->get(['mal','username']), $config->get(['mal','password']));
if (array_key_exists('query', $options))
{
$request = $request->setQuery($options['query']);
}
if (array_key_exists('body', $options))
{
$request = $request->setBody($options['body']);
}
return $request->getFullRequest();
// @TODO Implement
}
/**
@ -106,10 +89,10 @@ trait AnilistTrait {
$logger = $this->container->getLogger('mal-request');
}
$request = $this->setUpRequest($type, $url, $options);
$request = $this->setUpRequest($url, $options);
$response = wait((new HummingbirdClient)->request($request));
$logger->debug('MAL api response', [
$logger->debug('Anilist response', [
'status' => $response->getStatus(),
'reason' => $response->getReason(),
'body' => $response->getBody(),

View File

@ -17,9 +17,6 @@
namespace Aviat\AnimeClient\API\Anilist;
use Amp\Artax\{FormBody, Request};
use Aviat\AnimeClient\API\{
XML
};
use Aviat\AnimeClient\Types\AbstractType;
use Aviat\Ion\Di\ContainerAware;
@ -27,8 +24,8 @@ use Aviat\Ion\Di\ContainerAware;
* CRUD operations for MAL list items
*/
final class ListItem {
use ContainerAware;
use AnilistTrait;
use ContainerAware;
/**
* Create a list item
@ -39,20 +36,7 @@ final class ListItem {
*/
public function create(array $data, string $type = 'anime'): Request
{
$id = $data['id'];
$createData = [
'id' => $id,
'data' => XML::toXML([
'entry' => $data['data']
])
];
$config = $this->container->get('config');
return $this->requestBuilder->newRequest('POST', "{$type}list/add/{$id}.xml")
->setFormFields($createData)
->setBasicAuth($config->get(['mal','username']), $config->get(['mal', 'password']))
->getFullRequest();
// @TODO: implement
}
/**
@ -64,21 +48,12 @@ final class ListItem {
*/
public function delete(string $id, string $type = 'anime'): Request
{
$config = $this->container->get('config');
return $this->requestBuilder->newRequest('DELETE', "{$type}list/delete/{$id}.xml")
->setFormFields([
'id' => $id
])
->setBasicAuth($config->get(['mal','username']), $config->get(['mal', 'password']))
->getFullRequest();
// return $response->getBody() === 'Deleted'
// @TODO: implement
}
public function get(string $id): array
{
return [];
// @TODO: implement
}
/**
@ -91,19 +66,6 @@ final class ListItem {
*/
public function update(string $id, AbstractType $data, string $type = 'anime'): Request
{
$config = $this->container->get('config');
$xml = XML::toXML(['entry' => $data]);
$body = new FormBody();
$body->addField('id', $id);
$body->addField('data', $xml);
return $this->requestBuilder->newRequest('POST', "{$type}list/update/{$id}.xml")
->setFormFields([
'id' => $id,
'data' => $xml
])
->setBasicAuth($config->get(['mal','username']), $config->get(['mal', 'password']))
->getFullRequest();
// @TODO: implement
}
}

View File

@ -16,8 +16,216 @@
namespace Aviat\AnimeClient\API\Anilist;
use Amp\Artax\Request;
use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus};
use Aviat\AnimeClient\Types\FormItem;
/**
* Anilist API Model
*/
final class Model {
final class Model
{
use AnilistTrait;
/**
* @var ListItem
*/
private $listItem;
/**
* Constructor
*
* @param ListItem $listItem
*/
public function __construct(ListItem $listItem)
{
$this->listItem = $listItem;
}
public function getAnimeList()
{
$graphQL = <<<GQL
{
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()
{
$graphQL = <<<GQL
{
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;
}
// -------------------------------------------------------------------------
// ! Generic API calls
// -------------------------------------------------------------------------
/**
* Create a list item
*
* @param array $data
* @param string $type
* @return Request
*/
public function createListItem(array $data, string $type = 'anime'): Request
{
$createData = [];
if ($type === 'anime') {
$createData = [
'id' => $data['id'],
'data' => [
'status' => AnimeWatchingStatus::KITSU_TO_ANILIST[$data['status']]
]
];
} elseif ($type === 'manga') {
$createData = [
'id' => $data['id'],
'data' => [
'status' => MangaReadingStatus::KITSU_TO_ANILIST[$data['status']]
]
];
}
return $this->listItem->create($createData, $type);
}
/**
* Get the data for a specific list item, generally for editing
*
* @param string $listId - The unique identifier of that list item
* @return mixed
*/
public function getListItem(string $listId)
{
// @TODO: implement
}
/**
* Modify a list item
*
* @param FormItem $data
* @return Request
*/
public function updateListItem(FormItem $data): Request
{
return $this->listItem->update($data['id'], $data['data']);
}
/**
* Remove a list item
*
* @param string $id - The id of the list item to remove
* @return Request
*/
public function deleteListItem(string $id): Request
{
return $this->listItem->delete($id);
}
}

View File

@ -71,15 +71,21 @@ final class Index extends BaseController {
'message' => $message
], $view);
}
/**
* Redirect to Anilist to start Oauth flow
*/
public function anilistRedirect()
{
$redirectUrl = 'https://anilist.co/api/v2/oauth/authorize?' .
http_build_query([
'client_id' => 271,
'response_type' => 'code',
]);
$this->redirect($redirectUrl, 301);
}
/**
* Oauth callback for Anilist API
*/
@ -156,6 +162,20 @@ final class Index extends BaseController {
]);
}
/**
* Show the user settings, if logged in
*/
public function settings()
{
$auth = $this->container->get('auth');
$this->outputHTML('settings', [
'auth' => $auth,
'title' => $this->config->get('whose_list') . "'s Settings",
'base_settings' => $this->config->get('default_config'),
'user_settings' => $this->config->get('user_config_settings'),
]);
}
/**
* Get image covers from kitsu
*