Greasy Fork is available in English.
Adds Anisongs to anime entries on AniList
当前为
// ==UserScript==
// @name Anisongs
// @namespace Morimasa
// @author Morimasa
// @description Adds Anisongs to anime entries on AniList
// @match https://anilist.co/*
// @version 1.01
// @grant GM_xmlhttpRequest
// ==/UserScript==
const options = {
cacheName: 'anison',
cacheSize: 100,
cacheLife: 604800000, // 1 week in ms
class: 'anisongs'
}
let last = {id:0};
let target;
const insert = (list, parent) => {
if (list===undefined || list.length===0){
console.info("OP/ED is empty");
return;
}
list.forEach((title, i)=>{
let node = document.createElement('p');
node.innerText = `${i+1}. ${title}`;
node.setAttribute('data-v-4e418c9e','');
node.classList = "tag";
parent.appendChild(node);
})
}
const createTargetDiv = (text, target, pos) => {
let el = document.createElement('div');
el.appendChild(document.createElement('h2'));
el.children[0].innerText = text;
el.classList = options.class;
target.insertBefore(el, target.children[pos]);
return el;
}
const placeData = data => {
let op = createTargetDiv('Openings', target, 2)
let ed = createTargetDiv('Endings', target, 3)
insert(data.opening_themes, op);
insert(data.ending_themes, ed);
}
const handleData = data => {
let resp = JSON.parse(data.responseText);
placeData(resp);
if (Object.keys(JSON.parse(localStorage[options.cacheName])).length>options.cacheSize) clearCache();
addCache(last.id, {opening_themes: resp.opening_themes, ending_themes: resp.ending_themes, time: +new Date()});
}
const getMal = id => {
if (id===null) return console.info("No MAL id in API")
GM_xmlhttpRequest({
method: "GET",
url: `https://api.jikan.moe/v3/anime/${id}/`,
headers: {
"Accept": "application/json"
},
onload: handleData
})
}
const getMalId = () => {
const query = `query($id:Int){Media(id:$id){idMal}}`
let vars = {id: parseInt(window.location.pathname.split("/")[2])};
const options = {
method: 'POST',
body: JSON.stringify({query: query, variables: vars}),
headers: new Headers({
'Content-Type': 'application/json'
})
};
return fetch('https://graphql.anilist.co/', options)
.then(res => res.json())
.then(res => getMal(res.data.Media.idMal))
.catch(error => console.error(`Error: ${error}`));
}
const addCache = (id, data) => {
let cache = JSON.parse(localStorage.getItem(options.cacheName)) || {};
cache[id] = data
localStorage.setItem(options.cacheName, JSON.stringify(cache));
}
const getCache = id => {
let cache = localStorage.getItem(options.cacheName);
if (cache===null)
return {time:0}
else
return JSON.parse(cache)[id] || {time:0};
}
const clearCache = () => {
delete localStorage[options.cacheName]
}
const cleaner = (target) => {
let el = target.querySelectorAll(`.${options.class}`);
el.forEach((e)=>{
target.removeChild(e)
})
}
var observer = new MutationObserver(() => {
if (window.location.href.includes('/anime/', 18)) {
let currentid = window.location.href.split("/")[4];
let location = window.location.pathname.split("/").pop();
if (location!=='') last.id=0;
target = document.querySelectorAll('.grid-section-wrap')[1];
if(last.id!==currentid && location==='' && target!==undefined){
last.id = currentid;
cleaner(target)
let cache = getCache(currentid);
let TTLpassed = (cache.time + options.cacheLife)<+new Date();
if (TTLpassed){
getMalId();
console.info("OP/ED loaded from API");
}
else{
placeData(cache);
console.info("OP/ED loaded from Cache");
}
}
}
else
last.id = 0;
});
observer.observe(document.getElementById('app'), {childList: true, subtree: true});