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