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

@ -209,6 +209,12 @@ return [
'controller' => DEFAULT_CONTROLLER, 'controller' => DEFAULT_CONTROLLER,
'verb' => 'get', 'verb' => 'get',
], ],
'settings' => [
'path' => '/settings',
'action' => 'settings',
'controller' => DEFAULT_CONTROLLER,
'verb' => 'get',
],
'login' => [ 'login' => [
'path' => '/login', 'path' => '/login',
'action' => 'login', 'action' => 'login',

View File

@ -144,6 +144,20 @@ return function (array $configArray = []) {
$model->setRequestBuilder($requestBuilder); $model->setRequestBuilder($requestBuilder);
return $model; 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) { $container->set('api-model', function($container) {
return new Model\API($container); return new Model\API($container);

View File

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

View File

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

View File

@ -48,6 +48,9 @@ $di = require $APP_DIR . '/bootstrap.php';
$config = loadToml($CONF_DIR); $config = loadToml($CONF_DIR);
$config_array = array_merge($base_config, $config); $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); $container = $di($config_array);

View File

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

View File

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

View File

@ -17,9 +17,6 @@
namespace Aviat\AnimeClient\API\Anilist; namespace Aviat\AnimeClient\API\Anilist;
use Amp\Artax\{FormBody, Request}; use Amp\Artax\{FormBody, Request};
use Aviat\AnimeClient\API\{
XML
};
use Aviat\AnimeClient\Types\AbstractType; use Aviat\AnimeClient\Types\AbstractType;
use Aviat\Ion\Di\ContainerAware; use Aviat\Ion\Di\ContainerAware;
@ -27,8 +24,8 @@ use Aviat\Ion\Di\ContainerAware;
* CRUD operations for MAL list items * CRUD operations for MAL list items
*/ */
final class ListItem { final class ListItem {
use ContainerAware;
use AnilistTrait; use AnilistTrait;
use ContainerAware;
/** /**
* Create a list item * Create a list item
@ -39,20 +36,7 @@ final class ListItem {
*/ */
public function create(array $data, string $type = 'anime'): Request public function create(array $data, string $type = 'anime'): Request
{ {
$id = $data['id']; // @TODO: implement
$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();
} }
/** /**
@ -64,21 +48,12 @@ final class ListItem {
*/ */
public function delete(string $id, string $type = 'anime'): Request public function delete(string $id, string $type = 'anime'): Request
{ {
$config = $this->container->get('config'); // @TODO: implement
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'
} }
public function get(string $id): array 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 public function update(string $id, AbstractType $data, string $type = 'anime'): Request
{ {
$config = $this->container->get('config'); // @TODO: implement
$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();
} }
} }

View File

@ -16,8 +16,216 @@
namespace Aviat\AnimeClient\API\Anilist; namespace Aviat\AnimeClient\API\Anilist;
use Amp\Artax\Request;
use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus};
use Aviat\AnimeClient\Types\FormItem;
/** /**
* Anilist API Model * 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

@ -77,7 +77,13 @@ final class Index extends BaseController {
*/ */
public function anilistRedirect() public function anilistRedirect()
{ {
$redirectUrl = 'https://anilist.co/api/v2/oauth/authorize?' .
http_build_query([
'client_id' => 271,
'response_type' => 'code',
]);
$this->redirect($redirectUrl, 301);
} }
/** /**
@ -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 * Get image covers from kitsu
* *