Version 5.1 - All the GraphQL #32
@ -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',
|
||||||
|
@ -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);
|
||||||
|
@ -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>
|
||||||
|
2
console
2
console
@ -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)
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
@ -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(),
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user