Version 5.1 - All the GraphQL #32
@ -238,6 +238,14 @@ return [
|
||||
'action' => 'logout',
|
||||
'controller' => DEFAULT_CONTROLLER,
|
||||
],
|
||||
'increment' => [
|
||||
'path' => '/{controller}/increment',
|
||||
'action' => 'increment',
|
||||
'verb' => 'post',
|
||||
'tokens' => [
|
||||
'controller' => '[a-z_]+',
|
||||
],
|
||||
],
|
||||
'update' => [
|
||||
'path' => '/{controller}/update',
|
||||
'action' => 'update',
|
||||
|
@ -35,7 +35,7 @@ use Zend\Diactoros\{Response, ServerRequestFactory};
|
||||
// -----------------------------------------------------------------------------
|
||||
// Setup DI container
|
||||
// -----------------------------------------------------------------------------
|
||||
return function (array $configArray = []) {
|
||||
return function ($configArray = []) {
|
||||
$container = new Container();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -79,7 +79,9 @@
|
||||
<td> </td>
|
||||
<td>
|
||||
<input type="hidden" value="<?= $item['id'] ?>" name="id" />
|
||||
<input type="hidden" value="<?= $item['mal_id'] ?>" name="mal_id" />
|
||||
<?php if ( ! empty($item['mal_id'])): ?>
|
||||
<input type="hidden" value="<?= $item['mal_id'] ?? '' ?>" name="mal_id" />
|
||||
<?php endif ?>
|
||||
<input type="hidden" value="true" name="edit" />
|
||||
<button type="submit">Submit</button>
|
||||
</td>
|
||||
@ -100,7 +102,9 @@
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" value="<?= $item['id'] ?>" name="id" />
|
||||
<input type="hidden" value="<?= $item['mal_id'] ?>" name="mal_id" />
|
||||
<?php if (!empty($item['mal_id'])): ?>
|
||||
<input type="hidden" value="<?= $item['mal_id'] ?? '' ?>" name="mal_id" />
|
||||
<?php endif ?>
|
||||
<button type="submit" class="danger">Delete Entry</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -9,9 +9,8 @@
|
||||
<?php $i = 0; ?>
|
||||
<?php foreach ($sections as $name => $items): ?>
|
||||
<input <?= $i === 0 ? 'checked="checked"' : '' ?> type="radio" id="collection-tab-<?= $i ?>" name="collection-tabs" />
|
||||
<label for="collection-tab-<?= $i ?>"><?= $name ?></label>
|
||||
<label for="collection-tab-<?= $i ?>"><h2><?= $name ?></h2></label>
|
||||
<div class="content">
|
||||
<h2><?= $name ?></h2>
|
||||
<section class="media-wrap">
|
||||
<?php foreach ($items as $item): ?>
|
||||
<?php include __DIR__ . '/cover-item.php'; ?>
|
||||
|
@ -10,9 +10,8 @@
|
||||
<?php foreach ($sections as $name => $items): ?>
|
||||
<input <?= $i === 0 ? 'checked="checked"' : '' ?> type="radio" id="collection-tab-<?= $i ?>"
|
||||
name="collection-tabs"/>
|
||||
<label for="collection-tab-<?= $i ?>"><?= $name ?></label>
|
||||
<label for="collection-tab-<?= $i ?>"><h2><?= $name ?></h2></label>
|
||||
<div class="content">
|
||||
<h2><?= $name ?></h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -43,6 +43,11 @@ $hasManga = stripos($_SERVER['REQUEST_URI'], 'manga') !== FALSE;
|
||||
[<?= $helper->a($urlGenerator->defaultUrl('anime') . $extraSegment, 'Anime List') ?>]
|
||||
[<?= $helper->a($urlGenerator->defaultUrl('manga') . $extraSegment, 'Manga List') ?>]
|
||||
<?php endif ?>
|
||||
<?php if ($auth->isAuthenticated()): ?>
|
||||
<span class="flex-no-wrap small-font">
|
||||
<button type="button" class="js-clear-cache user-btn">Clear API Cache</button>
|
||||
</span>
|
||||
<?php endif ?>
|
||||
</span>
|
||||
|
||||
<span class="flex-no-wrap small-font">[<?= $helper->a(
|
||||
@ -51,24 +56,25 @@ $hasManga = stripos($_SERVER['REQUEST_URI'], 'manga') !== FALSE;
|
||||
) ?>]</span>
|
||||
|
||||
<?php if ($auth->isAuthenticated()): ?>
|
||||
<span class="flex-no-wrap"> </span>
|
||||
<span class="flex-no-wrap small-font">
|
||||
<button type="button" class="js-clear-cache user-btn">Clear API Cache</button>
|
||||
<?= $helper->a(
|
||||
$url->generate('settings'),
|
||||
'Settings',
|
||||
['class' => 'bracketed']
|
||||
) ?>
|
||||
</span>
|
||||
<span class="flex-no-wrap"> </span>
|
||||
<?php endif ?>
|
||||
|
||||
<span class="flex-no-wrap small-font">
|
||||
<?php if ($auth->isAuthenticated()): ?>
|
||||
<?= $helper->a(
|
||||
$url->generate('logout'),
|
||||
'Logout',
|
||||
['class' => 'bracketed']
|
||||
) ?>
|
||||
<?php else: ?>
|
||||
[<?= $helper->a($url->generate('login'), "{$whose} Login") ?>]
|
||||
<?php endif ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span class="flex-no-wrap small-font">
|
||||
[<?= $helper->a($url->generate('login'), "{$whose} Login") ?>]
|
||||
</span>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<nav>
|
||||
<?php if ($container->get('util')->isViewPage() && ($hasAnime || $hasManga)): ?>
|
||||
|
35
public/js/scripts-authed.min.js
vendored
35
public/js/scripts-authed.min.js
vendored
@ -2,21 +2,22 @@ var e=e||{};e.scope={};e.ASSUME_ES5=!1;e.ASSUME_NO_NATIVE_MAP=!1;e.ASSUME_NO_NAT
|
||||
e.initSymbol=function(){e.initSymbol=function(){};e.global.Symbol||(e.global.Symbol=e.Symbol)};e.Symbol=function(){var c=0;return function(f){return e.SYMBOL_PREFIX+(f||"")+c++}}();e.initSymbolIterator=function(){e.initSymbol();var c=e.global.Symbol.iterator;c||(c=e.global.Symbol.iterator=e.global.Symbol("iterator"));"function"!=typeof Array.prototype[c]&&e.defineProperty(Array.prototype,c,{configurable:!0,writable:!0,value:function(){return e.arrayIterator(this)}});e.initSymbolIterator=function(){}};
|
||||
e.arrayIterator=function(c){var f=0;return e.iteratorPrototype(function(){return f<c.length?{done:!1,value:c[f++]}:{done:!0}})};e.iteratorPrototype=function(c){e.initSymbolIterator();c={next:c};c[e.global.Symbol.iterator]=function(){return this};return c};
|
||||
e.iteratorFromArray=function(c,f){e.initSymbolIterator();c instanceof String&&(c+="");var k=0,g={next:function(){if(k<c.length){var m=k++;return{value:f(m,c[m]),done:!1}}g.next=function(){return{done:!0,value:void 0}};return g.next()}};g[Symbol.iterator]=function(){return g};return g};
|
||||
e.polyfill=function(c,f){if(f){var k=e.global;c=c.split(".");for(var g=0;g<c.length-1;g++){var m=c[g];m in k||(k[m]={});k=k[m]}c=c[c.length-1];g=k[c];f=f(g);f!=g&&null!=f&&e.defineProperty(k,c,{configurable:!0,writable:!0,value:f})}};e.polyfill("Array.prototype.keys",function(c){return c?c:function(){return e.iteratorFromArray(this,function(c){return c})}},"es6","es3");
|
||||
(function(){function c(d){a.$(".cssload-loader")[0].removeAttribute("hidden");a.get(a.url("/manga/search"),{query:d},function(b){b=JSON.parse(b);a.$(".cssload-loader")[0].setAttribute("hidden","hidden");a.$("#series_list")[0].innerHTML=n(b.data)})}function f(d){a.$(".cssload-loader")[0].removeAttribute("hidden");a.get(a.url("/anime-collection/search"),{query:d},function(b){b=JSON.parse(b);a.$(".cssload-loader")[0].setAttribute("hidden","hidden");a.$("#series_list")[0].innerHTML=p(b.data)})}function k(d,
|
||||
b,a){b.match(/^([\w\-]+)$/)||b.split(" ").forEach(function(b){k(d,b,a)});d.addEventListener(b,a,!1)}function g(d,b,l,c){k(d,l,function(l){a.$(b,d).forEach(function(b){l.target==b&&(c.call(b,l),l.stopPropagation())})})}function m(d){var b=[];Object.keys(d).forEach(function(a){var l=d[a].toString();a=encodeURIComponent(a);l=encodeURIComponent(l);b.push(a+"\x3d"+l)});return b.join("\x26")}function p(a){var b=[];a.forEach(function(a){var d=a.attributes,l=d.titles.reduce(function(b,a){return b+(a+"\x3cbr /\x3e")},
|
||||
[]);b.push('\n\t\t\t\x3carticle class\x3d"media search"\x3e\n\t\t\t\t\x3cdiv class\x3d"name"\x3e\n\t\t\t\t\t\x3cinput type\x3d"radio" class\x3d"big-check" id\x3d"'+d.slug+'" name\x3d"id" value\x3d"'+a.id+'" /\x3e\n\t\t\t\t\t\x3clabel for\x3d"'+d.slug+'"\x3e\n\t\t\t\t\t\t\x3cimg src\x3d"/public/images/anime/'+a.id+'.jpg" alt\x3d"" width\x3d"220" /\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"name"\x3e\n\t\t\t\t\t\t\t'+d.canonicalTitle+"\x3cbr /\x3e\n\t\t\t\t\t\t\t\x3csmall\x3e"+l+'\x3c/small\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/label\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3cdiv class\x3d"table"\x3e\n\t\t\t\t\t\x3cdiv class\x3d"row"\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"edit"\x3e\n\t\t\t\t\t\t\t\x3ca class\x3d"bracketed" href\x3d"/anime/details/'+
|
||||
d.slug+'"\x3eInfo Page\x3c/a\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\x3c/article\x3e\n\t\t')});return b.join("")}function n(a){var b=[];a.forEach(function(a){var d=a.attributes,l=d.titles.reduce(function(b,a){return b+(a+"\x3cbr /\x3e")},[]);b.push('\n\t\t\t\x3carticle class\x3d"media search"\x3e\n\t\t\t\t\x3cdiv class\x3d"name"\x3e\n\t\t\t\t\t\x3cinput type\x3d"radio" class\x3d"big-check" id\x3d"'+d.slug+'" name\x3d"id" value\x3d"'+a.id+'" /\x3e\n\t\t\t\t\t\x3clabel for\x3d"'+
|
||||
d.slug+'"\x3e\n\t\t\t\t\t\t\x3cimg src\x3d"/public/images/manga/'+a.id+'.jpg" alt\x3d"" width\x3d"220" /\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"name"\x3e\n\t\t\t\t\t\t\t'+d.canonicalTitle+"\x3cbr /\x3e\n\t\t\t\t\t\t\t\x3csmall\x3e"+l+'\x3c/small\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/label\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3cdiv class\x3d"table"\x3e\n\t\t\t\t\t\x3cdiv class\x3d"row"\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"edit"\x3e\n\t\t\t\t\t\t\t\x3ca class\x3d"bracketed" href\x3d"/manga/details/'+
|
||||
d.slug+'"\x3eInfo Page\x3c/a\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\x3c/article\x3e\n\t\t')});return b.join("")}var a={noop:function(){},$:function(a,b){b=void 0===b?null:b;if("string"!==typeof a)return a;b=null!==b&&1===b.nodeType?b:document;var d=[];a.match(/^#([\w]+$)/)?d.push(document.getElementById(a.split("#")[1])):d=[].slice.apply(b.querySelectorAll(a));return d},hasElement:function(d){return 0<a.$(d).length},scrollToTop:function(){window.scroll(0,
|
||||
0)},hide:function(a){a.setAttribute("hidden","hidden")},show:function(a){a.removeAttribute("hidden")},showMessage:function(d,b){d="\x3cdiv class\x3d'message "+d+"'\x3e\n\t\t\t\t\x3cspan class\x3d'icon'\x3e\x3c/span\x3e\n\t\t\t\t"+b+"\n\t\t\t\t\x3cspan class\x3d'close'\x3e\x3c/span\x3e\n\t\t\t\x3c/div\x3e";b=a.$(".message");void 0!==b[0]&&b[0].remove();a.$("header")[0].insertAdjacentHTML("beforeend",d)},closestParent:function(a,b){if(void 0!==Element.prototype.closest)return a.closest(b);for(;a!==
|
||||
document.documentElement;){for(var d=a,c=(d.document||d.ownerDocument).querySelectorAll(b),h=c.length;0<=--h&&c.item(h)!==d;);if(-1<h)return a;a=a.parentElement}return null},url:function(a){var b="//"+document.location.host;return b+="/"===a.charAt(0)?a:"/"+a},throttle:function(a,b,l){var d=!1;return function(c){for(var h=[],f=0;f<arguments.length;++f)h[f-0]=arguments[f];f=l||this;d||(b.apply(f,h),d=!0,setTimeout(function(){d=!1},a))}},on:function(d,b,l,c){3===arguments.length?(c=l,a.$(d).forEach(function(a){k(a,
|
||||
b,c)})):a.$(d).forEach(function(a){g(a,l,b,c)})},ajax:function(d,b){b=b||{};b.data=b.data||{};b.type=b.type||"GET";b.dataType=b.dataType||"";b.success=b.success||a.noop;b.mimeType=b.mimeType||"application/x-www-form-urlencoded";b.error=b.error||a.noop;var c=new XMLHttpRequest,f=String(b.type).toUpperCase();"GET"===f&&(d+=d.match(/\?/)?m(b.data):"?"+m(b.data));c.open(f,d);c.onreadystatechange=function(){if(4===c.readyState){var a="json"===c.responseType?JSON.parse(c.responseText):c.responseText;299<
|
||||
c.status?b.error.call(null,c.status,a,c.response):b.success.call(null,a,c.status)}};"json"===b.dataType?(b.data=JSON.stringify(b.data),b.mimeType="application/json"):b.data=m(b.data);c.setRequestHeader("Content-Type",b.mimeType);switch(f){case "GET":c.send(null);break;default:c.send(b.data)}},get:function(d,b,c){c=void 0===c?null:c;null===c&&(c=b,b={});return a.ajax(d,{data:b,success:c})}};a.on("header","click",".message",function(){a.hide(this)});a.on("form.js-delete","submit",function(a){!1===confirm("Are you ABSOLUTELY SURE you want to delete this item?")&&
|
||||
(a.preventDefault(),a.stopPropagation())});a.on(".js-clear-cache","click",function(){a.get("/cache_purge",function(){a.showMessage("success","Successfully purged api cache")})});"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then(function(a){console.log("Service worker registered",a.scope)}).catch(function(a){console.error("Failed to register service worker",a)});if(a.hasElement(".anime #search"))a.on("#search","keyup",a.throttle(250,function(){var a=encodeURIComponent(this.value);
|
||||
""!==a&&f(a)}));a.on("body.anime.list","click",".plus_one",function(c){var b=a.closestParent(c.target,"article"),d=parseInt(a.$(".completed_number",b)[0].textContent,10)||0;c=parseInt(a.$(".total_number",b)[0].textContent,10);var f=a.$(".name a",b)[0].textContent,h={id:b.dataset.kitsuId,mal_id:b.dataset.malId,data:{progress:d+1}};if(isNaN(d)||0===d)h.data.status="current";isNaN(d)||d+1!==c||(h.data.status="completed");a.show(a.$("#loading-shadow")[0]);a.ajax(a.url("/anime/update"),{data:h,dataType:"json",
|
||||
type:"POST",success:function(c){c=JSON.parse(c);c.errors?(a.hide(a.$("#loading-shadow")[0]),a.showMessage("error","Failed to update "+f+". ")):("completed"===c.data.attributes.status&&a.hide(b),a.hide(a.$("#loading-shadow")[0]),a.showMessage("success","Successfully updated "+f),a.$(".completed_number",b)[0].textContent=++d);a.scrollToTop()},error:function(){a.hide(a.$("#loading-shadow")[0]);a.showMessage("error","Failed to update "+f+". ");a.scrollToTop()}})});if(a.hasElement(".manga #search"))a.on("#search",
|
||||
"keyup",a.throttle(250,function(){var a=encodeURIComponent(this.value);""!==a&&c(a)}));a.on(".manga.list","click",".edit_buttons button",function(c){var b=c.target,d=a.closestParent(c.target,"article"),f=b.classList.contains("plus_one_chapter")?"chapter":"volume",h=parseInt(a.$("."+f+"s_read",d)[0].textContent,10)||0;c=parseInt(a.$("."+f+"_count",d)[0].textContent,10);var k=a.$(".name",d)[0].textContent;isNaN(h)&&(h=0);var g={id:d.dataset.kitsuId,mal_id:d.dataset.malId,data:{progress:h}};if(isNaN(h)||
|
||||
0===h)g.data.status="current";isNaN(h)||h+1!==c||(g.data.status="completed");g.data.progress=++h;a.show(a.$("#loading-shadow")[0]);a.ajax(a.url("/manga/update"),{data:g,dataType:"json",type:"POST",mimeType:"application/json",success:function(){"completed"===g.data.status&&a.hide(d);a.hide(a.$("#loading-shadow")[0]);a.$("."+f+"s_read",d)[0].textContent=h;a.showMessage("success","Successfully updated "+k);a.scrollToTop()},error:function(){a.hide(a.$("#loading-shadow")[0]);a.showMessage("error","Failed to update "+
|
||||
k);a.scrollToTop()}})})})();
|
||||
e.polyfill=function(c,f){if(f){var k=e.global;c=c.split(".");for(var g=0;g<c.length-1;g++){var m=c[g];m in k||(k[m]={});k=k[m]}c=c[c.length-1];g=k[c];f=f(g);f!=g&&null!=f&&e.defineProperty(k,c,{configurable:!0,writable:!0,value:f})}};e.polyfill("Array.prototype.keys",function(c){return c?c:function(){return e.iteratorFromArray(this,function(c){return c})}},"es6","es3");e.owns=function(c,f){return Object.prototype.hasOwnProperty.call(c,f)};
|
||||
e.assign="function"==typeof Object.assign?Object.assign:function(c,f){for(var k=1;k<arguments.length;k++){var g=arguments[k];if(g)for(var m in g)e.owns(g,m)&&(c[m]=g[m])}return c};e.polyfill("Object.assign",function(c){return c||e.assign},"es6","es3");
|
||||
(function(){function c(a){b.$(".cssload-loader")[0].removeAttribute("hidden");b.get(b.url("/manga/search"),{query:a},function(a){a=JSON.parse(a);b.$(".cssload-loader")[0].setAttribute("hidden","hidden");b.$("#series_list")[0].innerHTML=n(a.data)})}function f(a){b.$(".cssload-loader")[0].removeAttribute("hidden");b.get(b.url("/anime-collection/search"),{query:a},function(a){a=JSON.parse(a);b.$(".cssload-loader")[0].setAttribute("hidden","hidden");b.$("#series_list")[0].innerHTML=p(a.data)})}function k(a,
|
||||
b,d){b.match(/^([\w\-]+)$/)||b.split(" ").forEach(function(b){k(a,b,d)});a.addEventListener(b,d,!1)}function g(a,h,d,c){k(a,d,function(d){b.$(h,a).forEach(function(a){d.target==a&&(c.call(a,d),d.stopPropagation())})})}function m(a){var b=[];Object.keys(a).forEach(function(d){var h=a[d].toString();d=encodeURIComponent(d);h=encodeURIComponent(h);b.push(d+"\x3d"+h)});return b.join("\x26")}function p(a){var b=[];a.forEach(function(a){var d=a.attributes,h=d.titles.reduce(function(a,b){return a+(b+"\x3cbr /\x3e")},
|
||||
[]);b.push('\n\t\t\t\x3carticle class\x3d"media search"\x3e\n\t\t\t\t\x3cdiv class\x3d"name"\x3e\n\t\t\t\t\t\x3cinput type\x3d"radio" class\x3d"big-check" id\x3d"'+d.slug+'" name\x3d"id" value\x3d"'+a.id+'" /\x3e\n\t\t\t\t\t\x3clabel for\x3d"'+d.slug+'"\x3e\n\t\t\t\t\t\t\x3cimg src\x3d"/public/images/anime/'+a.id+'.jpg" alt\x3d"" width\x3d"220" /\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"name"\x3e\n\t\t\t\t\t\t\t'+d.canonicalTitle+"\x3cbr /\x3e\n\t\t\t\t\t\t\t\x3csmall\x3e"+h+'\x3c/small\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/label\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3cdiv class\x3d"table"\x3e\n\t\t\t\t\t\x3cdiv class\x3d"row"\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"edit"\x3e\n\t\t\t\t\t\t\t\x3ca class\x3d"bracketed" href\x3d"/anime/details/'+
|
||||
d.slug+'"\x3eInfo Page\x3c/a\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\x3c/article\x3e\n\t\t')});return b.join("")}function n(a){var b=[];a.forEach(function(a){var d=a.attributes,h=d.titles.reduce(function(a,b){return a+(b+"\x3cbr /\x3e")},[]);b.push('\n\t\t\t\x3carticle class\x3d"media search"\x3e\n\t\t\t\t\x3cdiv class\x3d"name"\x3e\n\t\t\t\t\t\x3cinput type\x3d"radio" class\x3d"big-check" id\x3d"'+d.slug+'" name\x3d"id" value\x3d"'+a.id+'" /\x3e\n\t\t\t\t\t\x3clabel for\x3d"'+
|
||||
d.slug+'"\x3e\n\t\t\t\t\t\t\x3cimg src\x3d"/public/images/manga/'+a.id+'.jpg" alt\x3d"" width\x3d"220" /\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"name"\x3e\n\t\t\t\t\t\t\t'+d.canonicalTitle+"\x3cbr /\x3e\n\t\t\t\t\t\t\t\x3csmall\x3e"+h+'\x3c/small\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/label\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3cdiv class\x3d"table"\x3e\n\t\t\t\t\t\x3cdiv class\x3d"row"\x3e\n\t\t\t\t\t\t\x3cspan class\x3d"edit"\x3e\n\t\t\t\t\t\t\t\x3ca class\x3d"bracketed" href\x3d"/manga/details/'+
|
||||
d.slug+'"\x3eInfo Page\x3c/a\x3e\n\t\t\t\t\t\t\x3c/span\x3e\n\t\t\t\t\t\x3c/div\x3e\n\t\t\t\t\x3c/div\x3e\n\t\t\t\x3c/article\x3e\n\t\t')});return b.join("")}var b={noop:function(){},$:function(a,b){b=void 0===b?null:b;if("string"!==typeof a)return a;b=null!==b&&1===b.nodeType?b:document;var d=[];a.match(/^#([\w]+$)/)?d.push(document.getElementById(a.split("#")[1])):d=[].slice.apply(b.querySelectorAll(a));return d},hasElement:function(a){return 0<b.$(a).length},scrollToTop:function(){window.scroll(0,
|
||||
0)},hide:function(a){a.setAttribute("hidden","hidden")},show:function(a){a.removeAttribute("hidden")},showMessage:function(a,h){a="\x3cdiv class\x3d'message "+a+"'\x3e\n\t\t\t\t\x3cspan class\x3d'icon'\x3e\x3c/span\x3e\n\t\t\t\t"+h+"\n\t\t\t\t\x3cspan class\x3d'close'\x3e\x3c/span\x3e\n\t\t\t\x3c/div\x3e";h=b.$(".message");void 0!==h[0]&&h[0].remove();b.$("header")[0].insertAdjacentHTML("beforeend",a)},closestParent:function(a,b){if(void 0!==Element.prototype.closest)return a.closest(b);for(;a!==
|
||||
document.documentElement;){for(var d=a,c=(d.document||d.ownerDocument).querySelectorAll(b),h=c.length;0<=--h&&c.item(h)!==d;);if(-1<h)return a;a=a.parentElement}return null},url:function(a){var b="//"+document.location.host;return b+="/"===a.charAt(0)?a:"/"+a},throttle:function(b,c,d){var a=!1;return function(h){for(var f=[],l=0;l<arguments.length;++l)f[l-0]=arguments[l];l=d||this;a||(c.apply(l,f),a=!0,setTimeout(function(){a=!1},b))}},on:function(a,c,d,f){void 0===f?(f=d,b.$(a).forEach(function(a){k(a,
|
||||
c,f)})):b.$(a).forEach(function(a){g(a,d,c,f)})},ajax:function(a,c){c=Object.assign({},{data:{},type:"GET",dataType:"",success:b.noop,mimeType:"application/x-www-form-urlencoded",error:b.noop},c);var d=new XMLHttpRequest,h=String(c.type).toUpperCase();"GET"===h&&(a+=a.match(/\?/)?m(c.data):"?"+m(c.data));d.open(h,a);d.onreadystatechange=function(){if(4===d.readyState){var a="json"===d.responseType?JSON.parse(d.responseText):d.responseText;299<d.status?c.error.call(null,d.status,a,d.response):c.success.call(null,
|
||||
a,d.status)}};"json"===c.dataType?(c.data=JSON.stringify(c.data),c.mimeType="application/json"):c.data=m(c.data);d.setRequestHeader("Content-Type",c.mimeType);switch(h){case "GET":d.send(null);break;default:d.send(c.data)}},get:function(a,c,d){d=void 0===d?null:d;null===d&&(d=c,c={});return b.ajax(a,{data:c,success:d})}};b.on("header","click",".message",function(a){b.hide(a.target)});b.on("form.js-delete","submit",function(a){!1===confirm("Are you ABSOLUTELY SURE you want to delete this item?")&&
|
||||
(a.preventDefault(),a.stopPropagation())});b.on(".js-clear-cache","click",function(){b.get("/cache_purge",function(){b.showMessage("success","Successfully purged api cache")})});"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then(function(a){console.log("Service worker registered",a.scope)}).catch(function(a){console.error("Failed to register service worker",a)});if(b.hasElement(".anime #search"))b.on("#search","keyup",b.throttle(250,function(a){a=encodeURIComponent(a.target.value);
|
||||
""!==a&&f(a)}));b.on("body.anime.list","click",".plus_one",function(a){var c=b.closestParent(a.target,"article"),d=parseInt(b.$(".completed_number",c)[0].textContent,10)||0;a=parseInt(b.$(".total_number",c)[0].textContent,10);var f=b.$(".name a",c)[0].textContent,l={id:c.dataset.kitsuId,mal_id:c.dataset.malId,data:{progress:d+1}};if(isNaN(d)||0===d)l.data.status="current";isNaN(d)||d+1!==a||(l.data.status="completed");b.show(b.$("#loading-shadow")[0]);b.ajax(b.url("/anime/increment"),{data:l,dataType:"json",
|
||||
type:"POST",success:function(a){a=JSON.parse(a);a.errors?(b.hide(b.$("#loading-shadow")[0]),b.showMessage("error","Failed to update "+f+". ")):("completed"===a.data.attributes.status&&b.hide(c),b.hide(b.$("#loading-shadow")[0]),b.showMessage("success","Successfully updated "+f),b.$(".completed_number",c)[0].textContent=++d);b.scrollToTop()},error:function(){b.hide(b.$("#loading-shadow")[0]);b.showMessage("error","Failed to update "+f+". ");b.scrollToTop()}})});if(b.hasElement(".manga #search"))b.on("#search",
|
||||
"keyup",b.throttle(250,function(a){a=encodeURIComponent(a.target.value);""!==a&&c(a)}));b.on(".manga.list","click",".edit_buttons button",function(a){var c=a.target,d=b.closestParent(a.target,"article"),f=c.classList.contains("plus_one_chapter")?"chapter":"volume",l=parseInt(b.$("."+f+"s_read",d)[0].textContent,10)||0;a=parseInt(b.$("."+f+"_count",d)[0].textContent,10);var k=b.$(".name",d)[0].textContent;isNaN(l)&&(l=0);var g={id:d.dataset.kitsuId,mal_id:d.dataset.malId,data:{progress:l}};if(isNaN(l)||
|
||||
0===l)g.data.status="current";isNaN(l)||l+1!==a||(g.data.status="completed");g.data.progress=++l;b.show(b.$("#loading-shadow")[0]);b.ajax(b.url("/manga/update"),{data:g,dataType:"json",type:"POST",mimeType:"application/json",success:function(){"completed"===g.data.status&&b.hide(d);b.hide(b.$("#loading-shadow")[0]);b.$("."+f+"s_read",d)[0].textContent=l;b.showMessage("success","Successfully updated "+k);b.scrollToTop()},error:function(){b.hide(b.$("#loading-shadow")[0]);b.showMessage("error","Failed to update "+
|
||||
k);b.scrollToTop()}})})})();
|
||||
//# sourceMappingURL=scripts-authed.min.js.map
|
||||
|
File diff suppressed because one or more lines are too long
19
public/js/scripts.min.js
vendored
19
public/js/scripts.min.js
vendored
@ -1,13 +1,14 @@
|
||||
var d=d||{};d.scope={};d.ASSUME_ES5=!1;d.ASSUME_NO_NATIVE_MAP=!1;d.ASSUME_NO_NATIVE_SET=!1;d.defineProperty=d.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,e,g){a!=Array.prototype&&a!=Object.prototype&&(a[e]=g.value)};d.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};d.global=d.getGlobal(this);d.SYMBOL_PREFIX="jscomp_symbol_";
|
||||
d.initSymbol=function(){d.initSymbol=function(){};d.global.Symbol||(d.global.Symbol=d.Symbol)};d.Symbol=function(){var a=0;return function(e){return d.SYMBOL_PREFIX+(e||"")+a++}}();d.initSymbolIterator=function(){d.initSymbol();var a=d.global.Symbol.iterator;a||(a=d.global.Symbol.iterator=d.global.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&d.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return d.arrayIterator(this)}});d.initSymbolIterator=function(){}};
|
||||
d.arrayIterator=function(a){var e=0;return d.iteratorPrototype(function(){return e<a.length?{done:!1,value:a[e++]}:{done:!0}})};d.iteratorPrototype=function(a){d.initSymbolIterator();a={next:a};a[d.global.Symbol.iterator]=function(){return this};return a};
|
||||
d.iteratorFromArray=function(a,e){d.initSymbolIterator();a instanceof String&&(a+="");var g=0,f={next:function(){if(g<a.length){var c=g++;return{value:e(c,a[c]),done:!1}}f.next=function(){return{done:!0,value:void 0}};return f.next()}};f[Symbol.iterator]=function(){return f};return f};
|
||||
d.polyfill=function(a,e){if(e){var g=d.global;a=a.split(".");for(var f=0;f<a.length-1;f++){var c=a[f];c in g||(g[c]={});g=g[c]}a=a[a.length-1];f=g[a];e=e(f);e!=f&&null!=e&&d.defineProperty(g,a,{configurable:!0,writable:!0,value:e})}};d.polyfill("Array.prototype.keys",function(a){return a?a:function(){return d.iteratorFromArray(this,function(a){return a})}},"es6","es3");
|
||||
(function(){function a(c,b,h){b.match(/^([\w\-]+)$/)||b.split(" ").forEach(function(b){a(c,b,h)});c.addEventListener(b,h,!1)}function e(c,b,h,k){a(c,h,function(a){f.$(b,c).forEach(function(b){a.target==b&&(k.call(b,a),a.stopPropagation())})})}function g(c){var b=[];Object.keys(c).forEach(function(a){var h=c[a].toString();a=encodeURIComponent(a);h=encodeURIComponent(h);b.push(a+"\x3d"+h)});return b.join("\x26")}var f={noop:function(){},$:function(c,b){b=void 0===b?null:b;if("string"!==typeof c)return c;
|
||||
b=null!==b&&1===b.nodeType?b:document;var a=[];c.match(/^#([\w]+$)/)?a.push(document.getElementById(c.split("#")[1])):a=[].slice.apply(b.querySelectorAll(c));return a},hasElement:function(c){return 0<f.$(c).length},scrollToTop:function(){window.scroll(0,0)},hide:function(c){c.setAttribute("hidden","hidden")},show:function(c){c.removeAttribute("hidden")},showMessage:function(c,b){c="\x3cdiv class\x3d'message "+c+"'\x3e\n\t\t\t\t\x3cspan class\x3d'icon'\x3e\x3c/span\x3e\n\t\t\t\t"+b+"\n\t\t\t\t\x3cspan class\x3d'close'\x3e\x3c/span\x3e\n\t\t\t\x3c/div\x3e";
|
||||
b=f.$(".message");void 0!==b[0]&&b[0].remove();f.$("header")[0].insertAdjacentHTML("beforeend",c)},closestParent:function(c,b){if(void 0!==Element.prototype.closest)return c.closest(b);for(;c!==document.documentElement;){for(var a=c,f=(a.document||a.ownerDocument).querySelectorAll(b),e=f.length;0<=--e&&f.item(e)!==a;);if(-1<e)return c;c=c.parentElement}return null},url:function(a){var b="//"+document.location.host;return b+="/"===a.charAt(0)?a:"/"+a},throttle:function(a,b,h){var c=!1;return function(f){for(var e=
|
||||
[],g=0;g<arguments.length;++g)e[g-0]=arguments[g];g=h||this;c||(b.apply(g,e),c=!0,setTimeout(function(){c=!1},a))}},on:function(c,b,h,g){3===arguments.length?(g=h,f.$(c).forEach(function(c){a(c,b,g)})):f.$(c).forEach(function(a){e(a,h,b,g)})},ajax:function(a,b){b=b||{};b.data=b.data||{};b.type=b.type||"GET";b.dataType=b.dataType||"";b.success=b.success||f.noop;b.mimeType=b.mimeType||"application/x-www-form-urlencoded";b.error=b.error||f.noop;var c=new XMLHttpRequest,e=String(b.type).toUpperCase();
|
||||
"GET"===e&&(a+=a.match(/\?/)?g(b.data):"?"+g(b.data));c.open(e,a);c.onreadystatechange=function(){if(4===c.readyState){var a="json"===c.responseType?JSON.parse(c.responseText):c.responseText;299<c.status?b.error.call(null,c.status,a,c.response):b.success.call(null,a,c.status)}};"json"===b.dataType?(b.data=JSON.stringify(b.data),b.mimeType="application/json"):b.data=g(b.data);c.setRequestHeader("Content-Type",b.mimeType);switch(e){case "GET":c.send(null);break;default:c.send(b.data)}},get:function(a,
|
||||
b,e){e=void 0===e?null:e;null===e&&(e=b,b={});return f.ajax(a,{data:b,success:e})}};f.on("header","click",".message",function(){f.hide(this)});f.on("form.js-delete","submit",function(a){!1===confirm("Are you ABSOLUTELY SURE you want to delete this item?")&&(a.preventDefault(),a.stopPropagation())});f.on(".js-clear-cache","click",function(){f.get("/cache_purge",function(){f.showMessage("success","Successfully purged api cache")})});"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then(function(a){console.log("Service worker registered",
|
||||
a.scope)}).catch(function(a){console.error("Failed to register service worker",a)})})();
|
||||
d.iteratorFromArray=function(a,e){d.initSymbolIterator();a instanceof String&&(a+="");var g=0,f={next:function(){if(g<a.length){var b=g++;return{value:e(b,a[b]),done:!1}}f.next=function(){return{done:!0,value:void 0}};return f.next()}};f[Symbol.iterator]=function(){return f};return f};
|
||||
d.polyfill=function(a,e){if(e){var g=d.global;a=a.split(".");for(var f=0;f<a.length-1;f++){var b=a[f];b in g||(g[b]={});g=g[b]}a=a[a.length-1];f=g[a];e=e(f);e!=f&&null!=e&&d.defineProperty(g,a,{configurable:!0,writable:!0,value:e})}};d.polyfill("Array.prototype.keys",function(a){return a?a:function(){return d.iteratorFromArray(this,function(a){return a})}},"es6","es3");d.owns=function(a,e){return Object.prototype.hasOwnProperty.call(a,e)};
|
||||
d.assign="function"==typeof Object.assign?Object.assign:function(a,e){for(var g=1;g<arguments.length;g++){var f=arguments[g];if(f)for(var b in f)d.owns(f,b)&&(a[b]=f[b])}return a};d.polyfill("Object.assign",function(a){return a||d.assign},"es6","es3");
|
||||
(function(){function a(b,c,h){c.match(/^([\w\-]+)$/)||c.split(" ").forEach(function(c){a(b,c,h)});b.addEventListener(c,h,!1)}function e(b,c,h,k){a(b,h,function(a){f.$(c,b).forEach(function(b){a.target==b&&(k.call(b,a),a.stopPropagation())})})}function g(b){var a=[];Object.keys(b).forEach(function(c){var h=b[c].toString();c=encodeURIComponent(c);h=encodeURIComponent(h);a.push(c+"\x3d"+h)});return a.join("\x26")}var f={noop:function(){},$:function(b,a){a=void 0===a?null:a;if("string"!==typeof b)return b;
|
||||
a=null!==a&&1===a.nodeType?a:document;var c=[];b.match(/^#([\w]+$)/)?c.push(document.getElementById(b.split("#")[1])):c=[].slice.apply(a.querySelectorAll(b));return c},hasElement:function(a){return 0<f.$(a).length},scrollToTop:function(){window.scroll(0,0)},hide:function(a){a.setAttribute("hidden","hidden")},show:function(a){a.removeAttribute("hidden")},showMessage:function(a,c){a="\x3cdiv class\x3d'message "+a+"'\x3e\n\t\t\t\t\x3cspan class\x3d'icon'\x3e\x3c/span\x3e\n\t\t\t\t"+c+"\n\t\t\t\t\x3cspan class\x3d'close'\x3e\x3c/span\x3e\n\t\t\t\x3c/div\x3e";
|
||||
c=f.$(".message");void 0!==c[0]&&c[0].remove();f.$("header")[0].insertAdjacentHTML("beforeend",a)},closestParent:function(a,c){if(void 0!==Element.prototype.closest)return a.closest(c);for(;a!==document.documentElement;){for(var b=a,f=(b.document||b.ownerDocument).querySelectorAll(c),e=f.length;0<=--e&&f.item(e)!==b;);if(-1<e)return a;a=a.parentElement}return null},url:function(a){var b="//"+document.location.host;return b+="/"===a.charAt(0)?a:"/"+a},throttle:function(a,c,f){var b=!1;return function(h){for(var e=
|
||||
[],g=0;g<arguments.length;++g)e[g-0]=arguments[g];g=f||this;b||(c.apply(g,e),b=!0,setTimeout(function(){b=!1},a))}},on:function(b,c,h,g){void 0===g?(g=h,f.$(b).forEach(function(b){a(b,c,g)})):f.$(b).forEach(function(a){e(a,h,c,g)})},ajax:function(a,c){c=Object.assign({},{data:{},type:"GET",dataType:"",success:f.noop,mimeType:"application/x-www-form-urlencoded",error:f.noop},c);var b=new XMLHttpRequest,e=String(c.type).toUpperCase();"GET"===e&&(a+=a.match(/\?/)?g(c.data):"?"+g(c.data));b.open(e,a);
|
||||
b.onreadystatechange=function(){if(4===b.readyState){var a="json"===b.responseType?JSON.parse(b.responseText):b.responseText;299<b.status?c.error.call(null,b.status,a,b.response):c.success.call(null,a,b.status)}};"json"===c.dataType?(c.data=JSON.stringify(c.data),c.mimeType="application/json"):c.data=g(c.data);b.setRequestHeader("Content-Type",c.mimeType);switch(e){case "GET":b.send(null);break;default:b.send(c.data)}},get:function(a,c,e){e=void 0===e?null:e;null===e&&(e=c,c={});return f.ajax(a,{data:c,
|
||||
success:e})}};f.on("header","click",".message",function(a){f.hide(a.target)});f.on("form.js-delete","submit",function(a){!1===confirm("Are you ABSOLUTELY SURE you want to delete this item?")&&(a.preventDefault(),a.stopPropagation())});f.on(".js-clear-cache","click",function(){f.get("/cache_purge",function(){f.showMessage("success","Successfully purged api cache")})});"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then(function(a){console.log("Service worker registered",a.scope)}).catch(function(a){console.error("Failed to register service worker",
|
||||
a)})})();
|
||||
//# sourceMappingURL=scripts.min.js.map
|
||||
|
File diff suppressed because one or more lines are too long
@ -58,7 +58,7 @@ _.on('body.anime.list', 'click', '.plus_one', (e) => {
|
||||
_.show(_.$('#loading-shadow')[ 0 ]);
|
||||
|
||||
// okay, lets actually make some changes!
|
||||
_.ajax(_.url('/anime/update'), {
|
||||
_.ajax(_.url('/anime/increment'), {
|
||||
data,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
|
@ -6,7 +6,7 @@ const plugins = [
|
||||
compilationLevel: 'SIMPLE', //'WHITESPACE_ONLY', //'ADVANCED',
|
||||
createSourceMap: true,
|
||||
env: 'BROWSER',
|
||||
languageIn: 'ES6',
|
||||
languageIn: 'ECMASCRIPT_2018',
|
||||
languageOut: 'ES5'
|
||||
})
|
||||
];
|
||||
|
@ -145,6 +145,40 @@ trait AnilistTrait {
|
||||
]);
|
||||
}
|
||||
|
||||
public function mutateRequest (string $name, array $variables = []): Request
|
||||
{
|
||||
$file = realpath(__DIR__ . "/GraphQL/Mutations/{$name}.graphql");
|
||||
if (!file_exists($file)) {
|
||||
throw new \LogicException('GraphQL mutation file does not exist.');
|
||||
}
|
||||
|
||||
// $query = str_replace(["\t", "\n"], ' ', file_get_contents($file));
|
||||
$query = file_get_contents($file);
|
||||
|
||||
$body = [
|
||||
'query' => $query
|
||||
];
|
||||
|
||||
if (!empty($variables)) {
|
||||
$body['variables'] = [];
|
||||
foreach ($variables as $key => $val) {
|
||||
$body['variables'][$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->setUpRequest(Anilist::BASE_URL, [
|
||||
'body' => $body,
|
||||
]);
|
||||
}
|
||||
|
||||
public function mutate (string $name, array $variables = []): array
|
||||
{
|
||||
$request = $this->mutateRequest($name, $variables);
|
||||
$response = $this->getResponseFromRequest($request);
|
||||
|
||||
return Json::decode(wait($response->getBody()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a request
|
||||
*
|
||||
@ -174,6 +208,26 @@ trait AnilistTrait {
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getResponseFromRequest(Request $request): Response
|
||||
{
|
||||
$logger = NULL;
|
||||
if ($this->getContainer()) {
|
||||
$logger = $this->container->getLogger('anilist-request');
|
||||
}
|
||||
|
||||
$response = wait((new HummingbirdClient)->request($request));
|
||||
|
||||
$logger->debug('Anilist response', [
|
||||
'status' => $response->getStatus(),
|
||||
'reason' => $response->getReason(),
|
||||
'body' => $response->getBody(),
|
||||
'headers' => $response->getHeaders(),
|
||||
'requestHeaders' => $request->getHeaders(),
|
||||
]);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove some boilerplate for post requests
|
||||
*
|
||||
|
@ -0,0 +1,9 @@
|
||||
mutation (
|
||||
$id: Int,
|
||||
$status: MediaListStatus,
|
||||
) {
|
||||
SaveMediaListEntry (
|
||||
mediaId: $id
|
||||
status: $status
|
||||
)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
mutation (
|
||||
$id: Int
|
||||
) {
|
||||
DeleteMediaListEntry (
|
||||
id: $id
|
||||
)
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
mutation (
|
||||
$id: Int,
|
||||
$progress: Int,
|
||||
) {
|
||||
SaveMediaListEntry (
|
||||
id: $id,
|
||||
progress: $progress,
|
||||
) {
|
||||
id
|
||||
progress
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
mutation (
|
||||
$id: Int,
|
||||
$status: String,
|
||||
$score: Int,
|
||||
$progress: Int,
|
||||
$repeat: Int
|
||||
) {
|
||||
SaveMediaListEntry (
|
||||
id: $id
|
||||
status: $status
|
||||
scoreRaw: $score
|
||||
progress: $progress
|
||||
repeat: $repeat
|
||||
)
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
mutation (
|
||||
$id: Int,
|
||||
$status: MediaListStatus,
|
||||
$score: Int,
|
||||
$progress: Int,
|
||||
$repeat: Int,
|
||||
$private: Boolean,
|
||||
$notes: String
|
||||
) {
|
||||
SaveMediaListEntry (
|
||||
id: $id,
|
||||
status: $status,
|
||||
scoreRaw: $score,
|
||||
progress: $progress,
|
||||
repeat: $repeat,
|
||||
private: $private,
|
||||
notes: $notes
|
||||
) {
|
||||
id
|
||||
status
|
||||
score
|
||||
progress
|
||||
repeat
|
||||
private
|
||||
notes
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
query ($id: Int) {
|
||||
Media (type: ANIME, malId: $id) {
|
||||
id
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
query ($id: Int) {
|
||||
Media (idMal: $id) {
|
||||
mediaListEntry {
|
||||
id
|
||||
userId
|
||||
mediaId
|
||||
}
|
||||
}
|
||||
}
|
7
src/API/Anilist/GraphQL/Queries/MediaIdByMalId.graphql
Normal file
7
src/API/Anilist/GraphQL/Queries/MediaIdByMalId.graphql
Normal file
@ -0,0 +1,7 @@
|
||||
query ($id: Int, $type: MediaType) {
|
||||
Media (type: $type, idMal: $id) {
|
||||
id
|
||||
userId
|
||||
mediaId
|
||||
}
|
||||
}
|
14
src/API/Anilist/GraphQL/Queries/MediaListItem.graphql
Normal file
14
src/API/Anilist/GraphQL/Queries/MediaListItem.graphql
Normal file
@ -0,0 +1,14 @@
|
||||
query ($id: Int) {
|
||||
MediaList (id: $id) {
|
||||
id
|
||||
userId
|
||||
mediaId
|
||||
status
|
||||
score(format: POINT_10)
|
||||
progress
|
||||
progressVolumes
|
||||
repeat
|
||||
private
|
||||
notes
|
||||
}
|
||||
}
|
@ -16,27 +16,27 @@
|
||||
|
||||
namespace Aviat\AnimeClient\API\Anilist;
|
||||
|
||||
use Amp\Artax\{FormBody, Request};
|
||||
use Aviat\AnimeClient\Types\AbstractType;
|
||||
use Aviat\Ion\Di\ContainerAware;
|
||||
use Amp\Artax\Request;
|
||||
|
||||
use Aviat\AnimeClient\API\ListItemInterface;
|
||||
use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
|
||||
use Aviat\AnimeClient\Types\FormItemData;
|
||||
|
||||
/**
|
||||
* CRUD operations for MAL list items
|
||||
*/
|
||||
final class ListItem {
|
||||
final class ListItem implements ListItemInterface{
|
||||
use AnilistTrait;
|
||||
use ContainerAware;
|
||||
|
||||
/**
|
||||
* Create a list item
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $type
|
||||
* @return Request
|
||||
*/
|
||||
public function create(array $data, string $type = 'anime'): Request
|
||||
public function create(array $data): Request
|
||||
{
|
||||
// @TODO: implement
|
||||
return $this->mutateRequest('CreateMediaListEntry', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,21 +51,50 @@ final class ListItem {
|
||||
// @TODO: implement
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for a list item
|
||||
*
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function get(string $id): array
|
||||
{
|
||||
// @TODO: implement
|
||||
return $this->runQuery('MediaListItem', ['id' => $id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the progress on the medium by 1
|
||||
*
|
||||
* @param string $id
|
||||
* @param FormItemData $data
|
||||
* @return Request
|
||||
*/
|
||||
public function increment(string $id, FormItemData $data): Request
|
||||
{
|
||||
return $this->mutateRequest('IncrementMediaListEntry', [
|
||||
'id' => $id,
|
||||
'progress' => $data['progress'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a list item
|
||||
*
|
||||
* @param string $id
|
||||
* @param AbstractType $data
|
||||
* @param string $type
|
||||
* @param FormItemData $data
|
||||
* @return Request
|
||||
*/
|
||||
public function update(string $id, AbstractType $data, string $type = 'anime'): Request
|
||||
public function update(string $id, FormItemData $data): Request
|
||||
{
|
||||
// @TODO: implement
|
||||
// @TODO Handle weirdness with reWatching
|
||||
return $this->mutateRequest('UpdateMediaListEntry', [
|
||||
'id' => $id,
|
||||
'status' => AnimeWatchingStatus::KITSU_TO_ANILIST[$data['status']],
|
||||
'score' => $data['rating'] * 20,
|
||||
'progress' => $data['progress'],
|
||||
'repeat' => (int)$data['reconsumeCount'],
|
||||
'private' => (bool)$data['private'],
|
||||
'notes' => $data['notes'],
|
||||
]);
|
||||
}
|
||||
}
|
@ -39,7 +39,6 @@ final class Model
|
||||
public function __construct(ListItem $listItem)
|
||||
{
|
||||
$this->listItem = $listItem;
|
||||
|
||||
}
|
||||
|
||||
public function getAnimeList(): array
|
||||
@ -67,19 +66,17 @@ final class Model
|
||||
{
|
||||
$createData = [];
|
||||
|
||||
$mediaId = $this->getMediaIdFromMalId($data['malId'], strtoupper($type));
|
||||
|
||||
if ($type === 'anime') {
|
||||
$createData = [
|
||||
'id' => $data['id'],
|
||||
'data' => [
|
||||
'status' => AnimeWatchingStatus::KITSU_TO_ANILIST[$data['status']]
|
||||
]
|
||||
'id' => $mediaId,
|
||||
'status' => AnimeWatchingStatus::KITSU_TO_ANILIST[$data['status']],
|
||||
];
|
||||
} elseif ($type === 'manga') {
|
||||
$createData = [
|
||||
'id' => $data['id'],
|
||||
'data' => [
|
||||
'status' => MangaReadingStatus::KITSU_TO_ANILIST[$data['status']]
|
||||
]
|
||||
'id' => $mediaId,
|
||||
'status' => MangaReadingStatus::KITSU_TO_ANILIST[$data['status']],
|
||||
];
|
||||
}
|
||||
|
||||
@ -89,12 +86,26 @@ final class Model
|
||||
/**
|
||||
* Get the data for a specific list item, generally for editing
|
||||
*
|
||||
* @param string $listId - The unique identifier of that list item
|
||||
* @param string $malId - The unique identifier of that list item
|
||||
* @return mixed
|
||||
*/
|
||||
public function getListItem(string $listId)
|
||||
public function getListItem(string $malId): array
|
||||
{
|
||||
// @TODO: implement
|
||||
$id = $this->getListIdFromMalId($malId);
|
||||
return $this->listItem->get($id)['data']['MediaList'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the watch count for the current list item
|
||||
*
|
||||
* @param FormItem $data
|
||||
* @return Request
|
||||
*/
|
||||
public function incrementListItem(FormItem $data): Request
|
||||
{
|
||||
$id = $this->getListIdFromMalId($data['mal_id']);
|
||||
|
||||
return $this->listItem->increment($id, $data['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,7 +116,9 @@ final class Model
|
||||
*/
|
||||
public function updateListItem(FormItem $data): Request
|
||||
{
|
||||
return $this->listItem->update($data['id'], $data['data']);
|
||||
$id = $this->getListIdFromMalId($data['mal_id']);
|
||||
|
||||
return $this->listItem->update($id, $data['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,4 +131,31 @@ final class Model
|
||||
{
|
||||
return $this->listItem->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the specific list entry from the malId
|
||||
*
|
||||
* @param string $malId
|
||||
* @return string
|
||||
*/
|
||||
public function getListIdFromMalId(string $malId): string
|
||||
{
|
||||
$info = $this->runQuery('ListItemIdByMalId', ['id' => $malId]);
|
||||
return (string)$info['data']['Media']['mediaListEntry']['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Anilist media id from the malId
|
||||
*
|
||||
* @param string $malId
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
private function getMediaIdFromMalId(string $malId, string $type = 'ANIME'): array
|
||||
{
|
||||
return $this->runQuery('MediaIdByMalId', [
|
||||
'id' => $malId,
|
||||
'type' => $type
|
||||
]);
|
||||
}
|
||||
}
|
@ -16,14 +16,18 @@
|
||||
|
||||
namespace Aviat\AnimeClient\API\Anilist\Transformer;
|
||||
|
||||
use Aviat\AnimeClient\Types\AnimeFormItem;
|
||||
use Aviat\AnimeClient\Types\{AnimeListItem, AnimeFormItem};
|
||||
use Aviat\Ion\Transformer\AbstractTransformer;
|
||||
|
||||
class AnimeListTransformer extends AbstractTransformer {
|
||||
|
||||
public function transform($item)
|
||||
public function transform($item): AnimeListItem
|
||||
{
|
||||
dump($item); die();
|
||||
|
||||
return new AnimeListItem([
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
public function untransform(array $item): AnimeFormItem
|
||||
|
@ -112,6 +112,11 @@ final class ListItem implements ListItemInterface {
|
||||
return Json::decode(wait($response->getBody()));
|
||||
}
|
||||
|
||||
public function increment(string $id, FormItemData $data): Request
|
||||
{
|
||||
return $this->update($id, $data);
|
||||
}
|
||||
|
||||
public function update(string $id, FormItemData $data): Request
|
||||
{
|
||||
$authHeader = $this->getAuthHeader();
|
||||
|
@ -837,6 +837,17 @@ final class Model {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the progress count for a list item
|
||||
*
|
||||
* @param FormItem $data
|
||||
* @return Request
|
||||
*/
|
||||
public function incrementListItem(FormItem $data): Request
|
||||
{
|
||||
return $this->listItem->increment($data['id'], $data['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a list item
|
||||
*
|
||||
|
@ -20,7 +20,6 @@ use Aviat\AnimeClient\API\Kitsu;
|
||||
use Aviat\AnimeClient\Types\{
|
||||
Anime,
|
||||
AnimeFormItem,
|
||||
AnimeFormItemData,
|
||||
AnimeListItem
|
||||
};
|
||||
use Aviat\Ion\Transformer\AbstractTransformer;
|
||||
@ -124,6 +123,7 @@ final class AnimeListTransformer extends AbstractTransformer {
|
||||
|
||||
$untransformed = new AnimeFormItem([
|
||||
'id' => $item['id'],
|
||||
'anilist_item_id' => $item['anilist_item_id'] ?? NULL,
|
||||
'mal_id' => $item['mal_id'] ?? NULL,
|
||||
'data' => [
|
||||
'status' => $item['watching_status'],
|
||||
|
@ -40,6 +40,15 @@ interface ListItemInterface {
|
||||
*/
|
||||
public function get(string $id): array;
|
||||
|
||||
/**
|
||||
* Increase progress on a list item
|
||||
*
|
||||
* @param string $id
|
||||
* @param FormItemData $data
|
||||
* @return Request
|
||||
*/
|
||||
public function increment(string $id, FormItemData $data): Request;
|
||||
|
||||
/**
|
||||
* Update a list item
|
||||
*
|
||||
|
@ -229,7 +229,7 @@ class Controller {
|
||||
throw new InvalidArgumentException("Invalid template : {$template}");
|
||||
}
|
||||
|
||||
return $view->renderTemplate($templatePath, (array)$data);
|
||||
return $view->renderTemplate($templatePath, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -345,7 +345,7 @@ class Controller {
|
||||
/**
|
||||
* Helper for consistent page titles
|
||||
*
|
||||
* @param string[] ...$parts Title segments
|
||||
* @param string[] $parts Title segments
|
||||
* @return string
|
||||
*/
|
||||
public function formatTitle(string ...$parts) : string
|
||||
|
@ -150,14 +150,10 @@ final class Anime extends BaseController {
|
||||
/**
|
||||
* Form to edit details about a series
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $id
|
||||
* @param string $status
|
||||
* @throws \Aviat\Ion\Di\ContainerException
|
||||
* @throws \Aviat\Ion\Di\NotFoundException
|
||||
* @throws \InvalidArgumentException
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id, $status = 'all'): void
|
||||
public function edit(string $id, $status = 'all'): void
|
||||
{
|
||||
$item = $this->model->getLibraryItem($id);
|
||||
$this->setSessionRedirect();
|
||||
@ -217,6 +213,28 @@ final class Anime extends BaseController {
|
||||
$this->sessionRedirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the watched count for an anime item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function increment(): void
|
||||
{
|
||||
if (stripos($this->request->getHeader('content-type')[0], 'application/json') !== FALSE)
|
||||
{
|
||||
$data = Json::decode((string)$this->request->getBody());
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $this->request->getParsedBody();
|
||||
}
|
||||
|
||||
$response = $this->model->incrementLibraryItem(new AnimeFormItem($data));
|
||||
|
||||
$this->cache->clear();
|
||||
$this->outputJSON($response['body'], $response['statusCode']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an anime item
|
||||
*
|
||||
|
@ -62,7 +62,7 @@ final class MenuGenerator extends UrlGenerator {
|
||||
* @param array $menus
|
||||
* @return array
|
||||
*/
|
||||
protected function parseConfig(array $menus)
|
||||
protected function parseConfig(array $menus) : array
|
||||
{
|
||||
$parsed = [];
|
||||
|
||||
@ -86,7 +86,7 @@ final class MenuGenerator extends UrlGenerator {
|
||||
* @throws ConfigException
|
||||
* @return string
|
||||
*/
|
||||
public function generate($menu)
|
||||
public function generate($menu) : string
|
||||
{
|
||||
$menus = $this->config->get('menus');
|
||||
$parsedConfig = $this->parseConfig($menus);
|
||||
@ -114,7 +114,7 @@ final class MenuGenerator extends UrlGenerator {
|
||||
}
|
||||
|
||||
// Create the menu html
|
||||
return $this->helper->ul();
|
||||
return (string) $this->helper->ul();
|
||||
}
|
||||
}
|
||||
// End of MenuGenerator.php
|
@ -30,6 +30,14 @@ use Aviat\Ion\Json;
|
||||
* Model for handling requests dealing with the anime list
|
||||
*/
|
||||
class Anime extends API {
|
||||
|
||||
/**
|
||||
* Model for making requests to Anilist API
|
||||
*
|
||||
* @var \Aviat\AnimeClient\API\Anilist\Model
|
||||
*/
|
||||
protected $anilistModel;
|
||||
|
||||
/**
|
||||
* Model for making requests to Kitsu API
|
||||
*
|
||||
@ -44,6 +52,7 @@ class Anime extends API {
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->anilistModel = $container->get('anilist-model');
|
||||
$this->kitsuModel = $container->get('kitsu-model');
|
||||
}
|
||||
|
||||
@ -125,7 +134,16 @@ class Anime extends API {
|
||||
*/
|
||||
public function getLibraryItem(string $itemId): AnimeListItem
|
||||
{
|
||||
return $this->kitsuModel->getListItem($itemId);
|
||||
$item = $this->kitsuModel->getListItem($itemId);
|
||||
$array = $item->toArray();
|
||||
|
||||
if ($item->mal_id !== NULL)
|
||||
{
|
||||
$anilistInfo = $this->anilistModel->getListItem($item['mal_id']);
|
||||
$array['anilist_item_id'] = $anilistInfo['id'];
|
||||
}
|
||||
|
||||
return new AnimeListItem($array);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,6 +162,35 @@ class Anime extends API {
|
||||
return count($results) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment progress for the specified anime
|
||||
*
|
||||
* @param AnimeFormItem $data
|
||||
* @return array
|
||||
*/
|
||||
public function incrementLibraryItem(AnimeFormItem $data): array
|
||||
{
|
||||
$requester = new ParallelAPIRequest();
|
||||
$requester->addRequest($this->kitsuModel->incrementListItem($data), 'kitsu');
|
||||
|
||||
$array = $data->toArray();
|
||||
|
||||
// @TODO Make sure Anilist integration is optional
|
||||
if (array_key_exists('mal_id', $array)) {
|
||||
$requester->addRequest($this->anilistModel->incrementListItem($data), 'anilist');
|
||||
}
|
||||
|
||||
$results = $requester->makeRequests();
|
||||
|
||||
$body = Json::decode($results['kitsu']);
|
||||
$statusCode = array_key_exists('error', $body) ? 400 : 200;
|
||||
|
||||
return [
|
||||
'body' => Json::decode($results['kitsu']),
|
||||
'statusCode' => $statusCode
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a list entry
|
||||
*
|
||||
@ -155,7 +202,16 @@ class Anime extends API {
|
||||
$requester = new ParallelAPIRequest();
|
||||
$requester->addRequest($this->kitsuModel->updateListItem($data), 'kitsu');
|
||||
|
||||
$array = $data->toArray();
|
||||
|
||||
// @TODO Make sure Anilist integration is optional
|
||||
if (array_key_exists('mal_id', $array))
|
||||
{
|
||||
$requester->addRequest($this->anilistModel->updateListItem($data), 'anilist');
|
||||
}
|
||||
|
||||
$results = $requester->makeRequests();
|
||||
|
||||
$body = Json::decode($results['kitsu']);
|
||||
$statusCode = array_key_exists('error', $body) ? 400: 200;
|
||||
|
||||
|
@ -22,6 +22,7 @@ namespace Aviat\AnimeClient\Types;
|
||||
final class AnimeListItem extends AbstractType {
|
||||
public $id;
|
||||
public $mal_id;
|
||||
public $anilist_item_id;
|
||||
public $episodes = [
|
||||
'length' => 0,
|
||||
'total' => 0,
|
||||
@ -33,10 +34,10 @@ final class AnimeListItem extends AbstractType {
|
||||
'ended' => '',
|
||||
];
|
||||
public $anime;
|
||||
public $watching_status;
|
||||
public $notes;
|
||||
public $private;
|
||||
public $rewatching;
|
||||
public $rewatched;
|
||||
public $user_rating;
|
||||
public $private;
|
||||
public $watching_status;
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ class Config extends AbstractType {
|
||||
public function setAnilist ($data): void
|
||||
{
|
||||
$this->anilist = new class($data) extends AbstractType {
|
||||
public $enabled;
|
||||
|
||||
public $client_id;
|
||||
public $client_secret;
|
||||
public $redirect_uri;
|
||||
|
@ -21,6 +21,7 @@ namespace Aviat\AnimeClient\Types;
|
||||
*/
|
||||
abstract class FormItem extends AbstractType {
|
||||
public $id;
|
||||
public $anilist_item_id;
|
||||
public $mal_id;
|
||||
public $data;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user