HummingBirdAnimeClient/src/Controller/Index.php

268 lines
6.1 KiB
PHP
Raw Normal View History

2017-03-31 13:37:53 -04:00
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
2018-08-22 13:48:27 -04:00
* An API client for Kitsu to manage anime and manga watch lists
2017-03-31 13:37:53 -04:00
*
2018-10-01 11:35:51 -04:00
* PHP version 7.1
2017-03-31 13:37:53 -04:00
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
2018-01-15 14:43:15 -05:00
* @copyright 2015 - 2018 Timothy J. Warren
2017-03-31 13:37:53 -04:00
* @license http://www.opensource.org/licenses/mit-license.html MIT License
2018-10-01 11:35:51 -04:00
* @version 4.1
2017-03-31 13:37:53 -04:00
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Controller;
use function Amp\Promise\wait;
2017-03-31 13:37:53 -04:00
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\API\{HummingbirdClient, JsonAPI};
2017-03-31 13:37:53 -04:00
use Aviat\Ion\View\HtmlView;
/**
* Controller for handling routes that don't fit elsewhere
*/
final class Index extends BaseController {
2017-03-31 13:37:53 -04:00
/**
* Purges the API cache
*
2018-02-02 09:50:58 -05:00
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
2017-03-31 13:37:53 -04:00
* @return void
*/
public function clearCache()
{
$this->cache->clear();
$this->outputHTML('blank', [
'title' => 'Cache cleared'
2018-02-02 09:50:58 -05:00
]);
2017-03-31 13:37:53 -04:00
}
/**
* Show the login form
*
* @param string $status
2018-02-02 09:50:58 -05:00
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
2017-03-31 13:37:53 -04:00
* @return void
*/
public function login(string $status = '')
{
$message = '';
$view = new HtmlView($this->container);
if ($status !== '')
{
$message = $this->showMessage($view, 'error', $status);
}
// Set the redirect url
$this->setSessionRedirect();
$this->outputHTML('login', [
'title' => 'Api login',
'message' => $message
], $view);
}
2018-08-15 08:51:37 -04:00
/**
* Redirect to Anilist to start Oauth flow
*/
public function anilistRedirect()
{
2018-08-15 08:51:37 -04:00
$redirectUrl = 'https://anilist.co/api/v2/oauth/authorize?' .
http_build_query([
2018-10-05 14:32:05 -04:00
'client_id' => $this->config->get(['anilist', 'client_id']),
2018-08-15 08:51:37 -04:00
'response_type' => 'code',
]);
$this->redirect($redirectUrl, 301);
}
2018-08-15 08:51:37 -04:00
/**
* Oauth callback for Anilist API
*/
public function anilistCallback()
{
$this->outputHTML('blank', [
'title' => 'Oauth!'
]);
}
2017-03-31 13:37:53 -04:00
/**
* Attempt login authentication
*
2018-02-02 09:50:58 -05:00
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \Aura\Router\Exception\RouteNotFound
* @throws \InvalidArgumentException
2017-03-31 13:37:53 -04:00
* @return void
*/
public function loginAction()
{
$auth = $this->container->get('auth');
$post = $this->request->getParsedBody();
2018-10-05 14:32:05 -04:00
2017-03-31 13:37:53 -04:00
if ($auth->authenticate($post['password']))
{
$this->sessionRedirect();
return;
}
$this->setFlashMessage('Invalid username or password.');
$this->redirect($this->url->generate('login'), 303);
}
/**
* Deauthorize the current user
*
2018-02-02 09:50:58 -05:00
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
2017-03-31 13:37:53 -04:00
* @return void
*/
public function logout()
{
$auth = $this->container->get('auth');
$auth->logout();
$this->redirectToDefaultRoute();
}
/**
* Show the user profile page
*
2018-02-02 09:50:58 -05:00
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
2017-03-31 13:37:53 -04:00
* @return void
*/
public function me()
{
$username = $this->config->get(['kitsu_username']);
$model = $this->container->get('kitsu-model');
$data = $model->getUserData($username);
$orgData = JsonAPI::organizeData($data)[0];
$rels = $orgData['relationships'] ?? [];
$favorites = array_key_exists('favorites', $rels) ? $rels['favorites'] : [];
2018-02-02 09:50:58 -05:00
2017-03-31 13:37:53 -04:00
$this->outputHTML('me', [
2017-04-17 16:13:36 -04:00
'title' => 'About ' . $this->config->get('whose_list'),
'data' => $orgData,
'attributes' => $orgData['attributes'],
'relationships' => $rels,
'favorites' => $this->organizeFavorites($favorites),
2017-03-31 13:37:53 -04:00
]);
}
2018-08-15 08:51:37 -04:00
/**
* Show the user settings, if logged in
*/
public function settings()
{
$auth = $this->container->get('auth');
2018-09-27 16:45:12 -04:00
$this->outputHTML('settings', [
'auth' => $auth,
'config' => $this->config,
'title' => $this->config->get('whose_list') . "'s Settings",
]);
}
public function settings_post()
{
$auth = $this->container->get('auth');
2018-08-15 08:51:37 -04:00
$this->outputHTML('settings', [
'auth' => $auth,
2018-08-20 13:01:16 -04:00
'config' => $this->config,
2018-08-15 08:51:37 -04:00
'title' => $this->config->get('whose_list') . "'s Settings",
]);
}
/**
* Get image covers from kitsu
*
2018-02-02 09:50:58 -05:00
* @param string $type The category of image
* @param string $file The filename to look for
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
* @throws \TypeError
* @throws \Error
* @throws \Throwable
* @return void
*/
2018-02-02 09:50:58 -05:00
public function images(string $type, string $file): void
{
$kitsuUrl = 'https://media.kitsu.io/';
2018-10-01 13:03:48 -04:00
[$id, $ext] = explode('.', basename($file));
switch ($type)
{
case 'anime':
$kitsuUrl .= "anime/poster_images/{$id}/small.{$ext}";
break;
case 'avatars':
$kitsuUrl .= "users/avatars/{$id}/original.{$ext}";
break;
case 'manga':
$kitsuUrl .= "manga/poster_images/{$id}/small.{$ext}";
break;
case 'characters':
$kitsuUrl .= "characters/images/{$id}/original.{$ext}";
break;
default:
$this->notFound();
return;
}
$promise = (new HummingbirdClient)->request($kitsuUrl);
$response = wait($promise);
$data = wait($response->getBody());
$baseSavePath = $this->config->get('img_cache_path');
file_put_contents("{$baseSavePath}/{$type}/{$id}.{$ext}", $data);
header('Content-type: ' . $response->getHeader('content-type')[0]);
echo $data;
}
2018-02-02 09:50:58 -05:00
/**
* Reorganize favorites data to be more useful
*
* @param array $rawfavorites
* @return array
*/
2017-03-31 13:37:53 -04:00
private function organizeFavorites(array $rawfavorites): array
{
$output = [];
2017-04-10 15:31:35 -04:00
unset($rawfavorites['data']);
2017-03-31 13:37:53 -04:00
foreach($rawfavorites as $item)
{
$rank = $item['attributes']['favRank'];
foreach($item['relationships']['item'] as $key => $fav)
{
$output[$key] = $output[$key] ?? [];
foreach ($fav as $id => $data)
{
$output[$key][$rank] = array_merge(['id' => $id], $data['attributes']);
2017-03-31 13:37:53 -04:00
}
}
ksort($output[$key]);
}
return $output;
}
}