您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Change stuff on Anilist.co
当前为
// ==UserScript== // @name Aniscripts // @namespace http://tampermonkey.net/ // @version 0.91 // @description Change stuff on Anilist.co // @author hoh // @match https://anilist.co/* // @grant none // ==/UserScript== (function(){ var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = ` .hohTime{ position : static; float : right; margin-right : 20px; margin-top : 10px; margin-left: auto; } .hohUnread{ border-right : 8px; border-color: rgba(var(--color-blue)); border-right-style : solid; } .hohNotification{ margin-bottom : 10px; background : rgb(var(--color-foreground)); border-radius : 4px; justify-content: space-between; line-height: 0; min-height: 70px; } .hohNotification *{ line-height: 1.15; } .hohUserImageSmall{ display : inline-block; background-position : 50%; background-repeat : no-repeat; background-size : cover; position : absolute; } .hohUserImage{ height : 72px; width : 72px; display : inline-block; background-position : 50%; background-repeat : no-repeat; background-size : cover; position:absolute; } .hohMediaImage{ height : 70px; margin-right : 5px; } .hohMessageText{ position : absolute; margin-top : 30px; margin-left : 80px; max-width : 330px; } .hohMediaImageContainer{ vertical-align : bottom; margin-left : 400px; display : inline; position: relative; display: inline-block; min-height: 70px; } .hohMediaImageContainer > a{ line-height: 0!important; } span.hohMediaImageContainer{ line-height: 0!important; } .hohCommentsContainer{ margin-top: 5px; } .hohCommentsArea{ margin : 10px; display : none; padding-bottom : 2px; margin-top: 5px; width: 95%; } .hohComments{ float : right; display : none; margin-top: -30px; margin-right: 15px; cursor : pointer; margin-left: 600px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .hohCombined .hohComments{ display : none!important; } .hohQuickCom{ padding : 5px; background-color : rgb(var(--color-background)); margin-bottom : 5px; } .hohQuickComName{ margin-right : 15px; color : rgb(var(--color-blue)); } .hohQuickComName::after{ content : ":"; } .hohQuickComContent{ margin-right: 40px; } .hohQuickComLikes{ float : right; display: inline-block; } .hohSpoiler::before{ color : rgb(var(--color-blue)); cursor : pointer; background : rgb(var(--color-background)); border-radius : 3px; content : "Spoiler, click to view"; font-size : 1.3rem; padding : 0 5px; } .hohSpoiler.hohClicked::before{ display : none; } .hohSpoiler > span{ display : none; } .hohMessageText > span > div.time{ display : none; } .hohUnhandledSpecial > div{ margin-top : -20px; } .hohMonospace{ font-family: monospace; } .hohSocialTabActivityCompressedContainer{ min-width:480px; } .hohSocialTabActivityCompressedStatus{ vertical-align: middle; padding-bottom: 7px; } .hohSocialTabActivityCompressedName{ vertical-align: middle; margin-left: 3px; } .hohForumHider{ margin-right: 3px; cursor: pointer; font-family: monospace; } .hohForumHider:hover{ color: rgb(var(--color-blue)); } .hohBackgroundCover{ height: 70px; width: 50px; display: inline-block; background-position: 50%; background-repeat: no-repeat; background-size: cover; margin-top: 1px; margin-bottom: 1px; } #hohDescription{ width: 280px; height: 150px; float: left; color: rgb(var(--color-blue)); } .hohBackgroundUserCover{ height: 70px; width: 70px; display: inline-block; background-position: 50%; background-repeat: no-repeat; background-size: cover; margin-top: 1px; margin-bottom: 1px; }; `; document.getElementsByTagName('head')[0].appendChild(style); document.APIcallsUsed = 0; var pending = {}; var APIcounter = setTimeout(function(){ document.APIcallsUsed = 0; },60*1000);//keep track of approximately how many more api calls we can use function lsTest(){//localStorage is great for not having to fetch the api data every time var test = "test"; try{ localStorage.setItem(test,test); localStorage.removeItem(test); return true; }catch(e) { return false; } } if(lsTest() === true){ var localStorageAvailable = true; var aniscriptsUsed = localStorage.getItem("aniscriptsUsed"); if(aniscriptsUsed === null){ aniscriptsUsed = { keys : [] }; } else{ aniscriptsUsed = JSON.parse(aniscriptsUsed); }; localStorage.setItem("aniscriptsUsed",JSON.stringify(aniscriptsUsed)); } else{ var localStorageAvailable = false; }; try{//looks at the nav var whoAmI = document.getElementById("nav").children[0].children[1].children[1].href.match(/[a-zA-Z0-9-]*\/$/)[0].slice(0,-1); } catch(err){ var whoAmI = ""; };//use later for some scripts Element.prototype.remove = function(){//more comfy way to remove DOM elements this.parentElement.removeChild(this); } NodeList.prototype.remove = HTMLCollection.prototype.remove = function() { for(var i = this.length - 1; i >= 0; i--) { if(this[i] && this[i].parentElement) { this[i].parentElement.removeChild(this[i]); } } } var badMarkupParser = function(string){//attempt to render some elements, like images and spoilers string = string.replace(/\n/g,"<br>"); var imageRegexp = /img[0-9]*\((.*?)\)/; var imageMatches = imageRegexp.exec(string); while(imageMatches){ string = string.replace(imageRegexp,"<img width=\"220\" src=\"" + imageMatches[1] + "\">"); imageMatches = imageRegexp.exec(string); }; var youEx = /youtube\((https?\:\/\/www\.youtube\.com\/watch\?v\=(.+?))\)/;//catch subgroup with url and one with the id var videoMatches = youEx.exec(string); while(videoMatches){ string = string.replace(youEx,"<a href=\"" + videoMatches[1] + "\">youtube " + videoMatches[2] + "</a>"); /* visible: youtube(https://www.youtube.com/watch?v=MzEinM660h4) becomes youtube MzEinM660h4 as a clickable link */ videoMatches = youEx.exec(string); }; var matchPings = /\@([a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]+)/;//at least three characters in user names var pingMatches = matchPings.exec(string); while(pingMatches){ if(whoAmI.toUpperCase() === pingMatches[1].toUpperCase()){ string = string.replace( matchPings, "<span style=\"color:rgb(var(--color-green))\">@<a href=\"https://anilist.co/user/" + pingMatches[1] +"/\">" + pingMatches[1] + "</a></span>" ); } else{ string = string.replace( matchPings, "@<a href=\"https://anilist.co/user/" + pingMatches[1] +"/\">" + pingMatches[1] + "</a>" ); }; pingMatches = matchPings.exec(string); }; var matchLinks = /\[(.+?)\]\((.+?)\)/; var linkMatches = matchLinks.exec(string); while(linkMatches){ string = string.replace(matchLinks,"<a href=\"" + linkMatches[2] + "\">" + linkMatches[1] + "</a>"); linkMatches = matchLinks.exec(string); }; var matchBold = /__(.+?)__/; var boldMatches = matchBold.exec(string); while(boldMatches){ string = string.replace(matchBold,"<b>" + boldMatches[1] + "</b>"); boldMatches = matchBold.exec(string); }; //https://anilist.co/manga/98889/Maikosan-Chi-no-Makanaisan/ var matchMediaLinks = /https?\:\/\/anilist.co\/(anime|manga)\/(\d+?)\/(.*?)\/(\ |\<br\>)/; var mediaLinkMatches = matchMediaLinks.exec(string); while(mediaLinkMatches){ string = string.replace( matchMediaLinks, "[<a href=\"https://anilist.co/" + mediaLinkMatches[1] + "/" + mediaLinkMatches[2] + "\">" + mediaLinkMatches[1] + "/" + mediaLinkMatches[3] + "</a>]" + mediaLinkMatches[4] ); mediaLinkMatches = matchMediaLinks.exec(string); }; var matchSpoiler = /\~\!(.*?)\!\~/; var spoilerMatches = matchSpoiler.exec(string); while(spoilerMatches){ string = string.replace( matchSpoiler, "<span class=\"hohSpoiler\" onclick=\"this.classList.add('hohClicked');this.children[0].style.display='inline'\"><span>" + spoilerMatches[1] + "</span></span>" ); spoilerMatches = matchSpoiler.exec(string); }; return string; }; var activityCache = {};//reduce API calls even if localStorage is not available. var handleResponse = function(response){ return response.json().then(function(json){ return response.ok ? json : Promise.reject(json); }); }; var handleError = function(error){ //alert("Error, check console"); //fixme console.error(error); }; var url = 'https://graphql.anilist.co';//Current Anilist API location var listActivityCall = function(query,variables,callback,vars,cache){ /* query=graphql request vars=just values to pass on to the callback function cache::true use cached data if available cache::false allways fetch new data */ var handleData = function(data){ pending[variables.id] = false; if(localStorageAvailable){ localStorage.setItem(variables.id + "",JSON.stringify(data)); aniscriptsUsed.keys.push(variables.id); if(aniscriptsUsed.keys.length > 1000){//don't hog to much of localStorage for(var i=0;i<10;i++){ localStorage.removeItem(aniscriptsUsed.keys[0]); aniscriptsUsed.keys.shift(); }; }; localStorage.setItem("aniscriptsUsed",JSON.stringify(aniscriptsUsed)); } else{ activityCache[variables.id] = data; }; callback(data,vars); }; var options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ query: query, variables: variables }) }; if(localStorageAvailable && cache){ var localStorageItem = localStorage.getItem(variables.id + ""); if(!(localStorageItem === null)){ callback(JSON.parse(localStorageItem),vars); console.log("localStorage cache hit"); return; }; } else if(activityCache.hasOwnProperty(variables.id) && cache){ callback(activityCache[variables.id],vars); console.log("cache hit"); return; }; fetch(url,options).then(handleResponse).then(handleData).catch(handleError); ++document.APIcallsUsed; console.log("fetching new data"); }; var generalAPIcall = function(query,variables,callback){ var handleData = function(data){ callback(data); }; var options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ query: query, variables: variables }) }; fetch(url,options).then(handleResponse).then(handleData).catch(handleError); ++document.APIcallsUsed; console.log("fetching new data"); }; var enhanceSocialTab = function(){ var perform = function(){ if(!document.URL.match(/https:\/\/anilist\.co\/(anime|manga)\/\d*\/[0-9a-zA-Z-]*\/social/)){ return; }; var listOfActs = document.getElementsByClassName("activity-entry"); for(var i=0;i<listOfActs.length;i++){//compress activities without comments if( !listOfActs[i].hasOwnProperty("marked") && !(listOfActs[i].children[0].children[2].children[0].children.length > 1) ){ listOfActs[i].marked = true; listOfActs[i].children[0].children[0].children[0].remove();//remove cover image var elements = listOfActs[i].children[0].children[0].children[0].children; elements[2].parentNode.insertBefore(elements[2],elements[0]);//move profile picture to the beginning of the line elements[0].parentNode.parentNode.style.minHeight = "70px"; elements[0].parentNode.classList.add("hohSocialTabActivityCompressedContainer"); elements[0].style.verticalAlign = "bottom"; elements[0].style.marginTop = "0px"; elements[1].classList.add("hohSocialTabActivityCompressedName"); elements[2].classList.add("hohSocialTabActivityCompressedStatus"); listOfActs[i].style.marginBottom = "10px"; }; }; /*add average score to social tab*/ var listOfFollowers = document.getElementsByClassName("follow"); var averageScore = 0; var averageCount = 0; for(var i=0;i<listOfFollowers.length;i++){ if( listOfFollowers[i].children.length == 4 ){ if(listOfFollowers[i].children[3].nodeName != "svg"){ var followScore = listOfFollowers[i].children[3].innerText.match(/\d+\.?\d*/g); if(followScore && followScore.length == 2){ averageScore += followScore[0]/followScore[1]; averageCount++; } else if(followScore && followScore.length == 1){//star rating averageScore += (followScore[0]*20 - 10)/100; averageCount++; }; } else{//do count smiley scores, but with lower confidence var smileyScore = listOfFollowers[i].children[3].dataset.icon; if(smileyScore == "frown"){ averageScore += (40/100)*0.5; averageCount += 0.5; } else if(smileyScore == "meh"){ averageScore += (60/100)*0.5; averageCount += 0.5; } else if(smileyScore == "smile"){ averageScore += (90/100)*0.5; averageCount += 0.5; }; }; }; }; if(averageCount){ var locationForIt = document.getElementById("averageScore"); if(!locationForIt){ var locationForIt = document.createElement("span"); locationForIt.id = "averageScore"; document.getElementsByClassName("following")[0].insertBefore( locationForIt, document.getElementsByClassName("following")[0].children[0] ); }; locationForIt.innerHTML = "average: " + (100 * averageScore/averageCount).toFixed(1) + "/100"; }; /*end average score*/ }; var tryAgain = function(){//loop the notification script until we leave that page setTimeout(function(){ perform(); if(document.URL.match(/https:\/\/anilist\.co\/(anime|manga)\/\d*\/[0-9a-zA-Z-]*\/social/)){ tryAgain() } else{ activeScripts.socialTab = false; } },100); }; activeScripts.socialTab = true; perform(); tryAgain(); }; var enhanceForum = function(){ var perform = function(){ if(!document.URL.match(/https:\/\/anilist\.co\/forum\/thread\/.*/)){ return; }; var comments = document.getElementsByClassName("comment-wrap"); for(var i=0;i<comments.length;i++){ if(comments[i].hasOwnProperty("hohVisited")){ } else{ comments[i].hohVisited = true; var hider = document.createElement("span"); hider.innerHTML = "[-]"; hider.classList.add("hohForumHider"); hider.onclick = function(){ if(this.innerHTML == "[-]"){ this.innerHTML = "[+]"; this.parentNode.parentNode.children[1].style.display = "none"; if(this.parentNode.parentNode.parentNode.children.length > 1){ this.parentNode.parentNode.parentNode.children[1].style.display = "none"; }; } else{ this.innerHTML = "[-]"; this.parentNode.parentNode.children[1].style.display = "block"; if(this.parentNode.parentNode.parentNode.children.length > 1){ this.parentNode.parentNode.parentNode.children[1].style.display = "block"; }; }; }; comments[i].children[0].children[0].insertBefore(hider,comments[i].children[0].children[0].children[0]); }; //comments[i].remove(); }; }; var tryAgain = function(){//loop the notification script until we leave that page setTimeout(function(){ perform(); if(document.URL.match(/https:\/\/anilist\.co\/forum\/thread\/.*/)){ tryAgain() } else{ activeScripts.forumComments = false; } },100); }; activeScripts.forumComments = true; perform(); tryAgain(); }; var enhanceStaff = function(){ var perform = function(){ if(!document.URL.match(/https:\/\/anilist\.co\/staff\/.*/)){ return; }; var roleCards = document.getElementsByClassName("role-card"); for(var i=0;i<roleCards.length;i++){ if(roleCards[i].hasOwnProperty("hohVisited")){ } else{ roleCards[i].hohVisited = true; //entryInfoCard(); }; }; }; var tryAgain = function(){//loop the notification script until we leave that page setTimeout(function(){ perform(); if(document.URL.match(/https:\/\/anilist\.co\/staff\/.*/)){ tryAgain() } else{ activeScripts.staffPages = false; } },400); }; activeScripts.staffPages = true; perform(); tryAgain(); }; var addCompletedScores = function(){ var perform = function(){ if(!document.URL.match(/https:\/\/anilist\.co\/home\/?/)){ return; }; var status = document.getElementsByClassName("status"); for(var i=0;i<status.length;i++){ if(status[i].innerText.match(/^(c|C)ompleted/)){ if(!status[i].hasOwnProperty("hohScoreMatched")){ status[i].hohScoreMatched = true; var scoreInfo = document.createElement("span"); var userName = status[i].parentNode.children[0].innerText; var mediaId = /\/(\d+)\//.exec(status[i].children[0].href); if(!mediaId || !mediaId.length){ continue; }; mediaId = mediaId[1]; scoreInfo.classList.add("hohCS" + userName + mediaId); status[i].appendChild(scoreInfo); var callback = function(data){ var statusFind = document.getElementsByClassName("hohCS" + data.data.MediaList.user.name + data.data.MediaList.mediaId); var suffix = "";//comma was a bad idea if(data.data.MediaList.user.mediaListOptions.scoreFormat == "POINT_100"){ suffix = " " + data.data.MediaList.score + "/100"; } else if( data.data.MediaList.user.mediaListOptions.scoreFormat == "POINT_10_DECIMAL" || data.data.MediaList.user.mediaListOptions.scoreFormat == "POINT_10" ){ suffix = " " + data.data.MediaList.score + "/10"; } else if(data.data.MediaList.user.mediaListOptions.scoreFormat == "POINT_3"){ if(data.data.MediaList.score == 3){ suffix = "<svg data-v-ca4e7a3a=\"\" aria-hidden=\"true\" data-prefix=\"far\" data-icon=\"smile\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 496 512\" class=\"svg-inline--fa fa-smile fa-w-16 fa-lg\"><path data-v-ca4e7a3a=\"\" fill=\"currentColor\" d=\"M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm84-143.4c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.6-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.2-8.4-25.3-7.1-33.8 3.1zM168 240c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32z\" class=\"\"></path></svg>"; } else if(data.data.MediaList.score == 2){ suffix = "<svg data-v-ca4e7a3a=\"\" aria-hidden=\"true\" data-prefix=\"far\" data-icon=\"meh\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 496 512\" class=\"svg-inline--fa fa-meh fa-w-16 fa-lg\"><path data-v-ca4e7a3a=\"\" fill=\"currentColor\" d=\"M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z\" class=\"\"></path></svg>"; } else if(data.data.MediaList.score == 1){ suffix = "<svg data-v-ca4e7a3a=\"\" aria-hidden=\"true\" data-prefix=\"far\" data-icon=\"frown\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 496 512\" class=\"svg-inline--fa fa-frown fa-w-16 fa-lg\"><path data-v-ca4e7a3a=\"\" fill=\"currentColor\" d=\"M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.5 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c4.8 5.7 11.6 8.6 18.5 8.6 5.4 0 10.9-1.8 15.4-5.6 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z\" class=\"\"></path></svg>"; }; } else if( data.data.MediaList.user.mediaListOptions.scoreFormat == "POINT_5" ){ suffix = " " + data.data.MediaList.score + "<svg data-v-ca4e7a3a=\"\" aria-hidden=\"true\" data-prefix=\"fas\" data-icon=\"star\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 576 512\" class=\"icon svg-inline--fa fa-star fa-w-18\"><path data-v-ca4e7a3a=\"\" fill=\"currentColor\" d=\"M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z\" class=\"\"></path></svg>"; } for(var j=0;j<statusFind.length;j++){ if(data.data.MediaList.score != 0){ statusFind[j].innerHTML = suffix; }; }; }; var variables = { userName: userName, mediaId: mediaId }; var query = ` query ( $userName: String, $mediaId: Int ) { MediaList ( userName: $userName, mediaId: $mediaId ) { score mediaId user { name mediaListOptions { scoreFormat } } } } `; generalAPIcall(query,variables,callback) }; }; }; }; var tryAgain = function(){//loop the notification script until we leave that page setTimeout(function(){ perform(); if(document.URL.match(/https:\/\/anilist\.co\/home\/?/)){ tryAgain() } else{ activeScripts.completedScore = false; } },1000); }; activeScripts.completedScore = true; perform(); tryAgain(); }; var enhanceTags = function(){ var perform = function(){ if(!document.URL.match(/https:\/\/anilist\.co\/(anime|manga)\/.*/)){ return; }; var possibleTagContainers = document.getElementsByClassName("el-select-dropdown__list"); var bestGuess = false; for(var i=0;i<possibleTagContainers.length;i++){ if(possibleTagContainers[i].children.length > 100){//horrible test, but we have not markup to go from bestGuess = i; }; }; if(bestGuess == false){ return; }; if(possibleTagContainers[bestGuess].hasOwnProperty("hohMarked")){ return; } else{ possibleTagContainers[bestGuess].hohMarked = true; }; var superBody = document.getElementsByClassName("el-dialog__body")[0]; var descriptionTarget = document.createElement("span"); descriptionTarget.id = "hohDescription"; superBody.insertBefore(descriptionTarget,superBody.children[2]); for(var i=0;i<possibleTagContainers[bestGuess].children.length;i++){ possibleTagContainers[bestGuess].children[i].onmouseover = function(){ if(tagDescriptions[this.children[0].innerText]){ document.getElementById("hohDescription").innerText = tagDescriptions[this.children[0].innerText]; } else{ document.getElementById("hohDescription").innerText = "Message hoh to get this description added"; }; }; possibleTagContainers[bestGuess].children[i].onmouseout = function(){ document.getElementById("hohDescription").innerText = ""; }; }; }; var tryAgain = function(){//loop the notification script until we leave that page setTimeout(function(){ perform(); if(document.URL.match(/https:\/\/anilist\.co\/(anime|manga)\/.*/)){ tryAgain() } else{ activeScripts.tagDescriptions = false; } },400); }; activeScripts.tagDescriptions = true; perform(); tryAgain(); }; var enhanceNotifications = function(){ var retries = 3;//workaround var prevLength = 0; var perform = function(){ if(document.URL != "https://anilist.co/notifications"){ return; }; var notifications = document.getElementsByClassName("notification"); var possibleButton = document.getElementsByClassName("reset-btn"); if(possibleButton.length){ possibleButton[0].onclick = function(){ var notf = document.getElementById("hohNotifications"); for(var i=0;i<notf.children.length;i++){ notf.children[i].classList.remove("hohUnread"); }; }; }; var activities = []; for(var i=0;i<notifications.length;i++){ notifications[i].already = true; notifications[i].style.display = "none"; var active = {}; if( notifications[i].classList.length > 1 && notifications[i].classList[1] != "hasMedia" ){ //"notification unread" classlist active.unread = true; } else{ active.unread = false; }; active.type = "special"; //by default every activity is some weird thing we are displaying as-is active.link = "aaa";//fixme if(//check if we can query that notifications[i].children.length >= 1 && notifications[i].children[1].children.length && notifications[i].children[1].children[0].children.length && notifications[i].children[1].children[0].children[0].children.length ){ // active.directLink = notifications[i].children[1].children[0].children[0].href active.text = notifications[i].children[1].children[0].children[0].innerHTML; active.textName = notifications[i].children[1].children[0].children[0].childNodes[0].textContent; active.textSpan = notifications[i].children[1].children[0].children[0].childNodes[1].textContent; active.link = notifications[i].children[1].children[0].children[0].href.match(/[0-9]+/)[0]; var testType = notifications[i].children[1].children[0].children[0].children[0].textContent; if(testType == " liked your activity."){ active.type = "likeActivity"; } else if(testType == " replied to your activity."){ active.type = "replyActivity"; } else if(testType == " sent you a message."){ active.type = "messageActivity"; } else if(testType == " liked your activity reply."){ active.type = "likeReplyActivity"; } else if(testType == " mentioned you in their activity."){ active.type = "mentionActivity"; } // }; if(active.type == "special"){ if( notifications[i].children.length >= 1 && notifications[i].children[1].children.length && notifications[i].children[1].children[0].children.length >= 2 && notifications[i].children[1].children[0].children[1].textContent == " started following you." ){ active.type = "followActivity"; active.directLink = notifications[i].children[1].children[0].children[0].href active.text = notifications[i].children[1].children[0].children[0].innerHTML; active.textName = notifications[i].children[1].children[0].children[0].textContent; active.textSpan = notifications[i].children[1].children[0].children[1].textContent; } else if( notifications[i].children.length >= 1 && notifications[i].children[1].children.length && notifications[i].children[1].children[0].children.length >= 4 && notifications[i].children[1].children[0].children[3].textContent == " aired." ){ active.type = "airingActivity"; active.directLink = notifications[i].children[1].children[0].children[0].href active.text = notifications[i].children[1].children[0].innerHTML; } else{ active.text = notifications[i].children[1].innerHTML; }; }; if( notifications[i].children.length > 1 && notifications[i].children[1].children.length > 1 ){ active.time = notifications[i].children[1].children[1].innerHTML; } else{ active.time = document.createElement("span"); }; active.image = notifications[i].children[0].style.backgroundImage; active.href = notifications[i].children[0].href; activities.push(active); }; if(activities.length == prevLength){ if(retries == 0){ return 0; } else{ retries--; }; } else{ prevLength = activities.length; retries = 3; }; if(document.getElementById("hohNotifications")){ document.getElementById("hohNotifications").remove(); }; var newContainer = document.createElement("div"); newContainer.id = "hohNotifications"; var notificationsContainer = document.getElementsByClassName("notifications"); if(!notificationsContainer.length){ return; } else{ notificationsContainer = notificationsContainer[0]; }; notificationsContainer.insertBefore(newContainer,notificationsContainer.firstChild); for(var i=0;i<activities.length;i++){ var newNotification = document.createElement("div"); newNotification.onclick = function(){ this.classList.remove("hohUnread"); var notiCount = document.getElementsByClassName("notification-dot"); if(notiCount.length){ var actualCount = parseInt(notiCount[0].innerHTML); if(actualCount < 2){ var possibleButton = document.getElementsByClassName("reset-btn"); if(possibleButton.length){ possibleButton[0].click(); }; } else{ notiCount[0].innerHTML = (actualCount - 1); }; }; }; if(activities[i].unread){ newNotification.classList.add("hohUnread"); }; newNotification.classList.add("hohNotification"); var notImage = document.createElement("a"); //container for profile images notImage.href = activities[i].href; notImage.classList.add("hohUserImage"); notImage.style.backgroundImage = activities[i].image; var notNotImageContainer = document.createElement("span"); //container for series images notNotImageContainer.classList.add("hohMediaImageContainer"); var text = document.createElement("a"); text.classList.add("hohMessageText"); var timeHideFlag = false; if(activities[i].type == "likeActivity"){ for( var counter = 0; i + counter < activities.length && activities[i + counter].type == "likeActivity" && activities[i + counter].href == activities[i].href; counter++ ){//one person likes several of your media activities var fakeNotNotImage = document.createElement("a"); var notNotImage = document.createElement("a"); notNotImage.href = activities[i + counter].directLink; fakeNotNotImage.classList.add("hohMediaImage"); fakeNotNotImage.classList.add(activities[i + counter].link); notNotImage.appendChild(fakeNotNotImage); notNotImageContainer.appendChild(notNotImage); }; var activityCounter = counter; if(counter > 5){ timeHideFlag = true; }; if(counter == 1){ while( i + counter < activities.length && activities[i + counter].type == "likeActivity" && activities[i + counter].link == activities[i].link ){//several people likes one of your activities var miniImageWidth = 40; var miniImage = document.createElement("a"); miniImage.classList.add("hohUserImageSmall"); miniImage.href = activities[i + counter].href; miniImage.style.backgroundImage = activities[i + counter].image; miniImage.style.height = miniImageWidth + "px"; miniImage.style.width = miniImageWidth + "px"; miniImage.style.marginLeft = (72 + (counter-1)*miniImageWidth) + "px"; newNotification.appendChild(miniImage); counter++; }; if(counter > 1){ text.style.marginTop = "45px"; activities[i].textName += " +"; }; } else{ newNotification.classList.add("hohCombined"); }; text.href = activities[i].directLink; var textName = document.createElement("span"); var textSpan = document.createElement("span"); textName.innerHTML = activities[i].textName; textSpan.innerHTML = activities[i].textSpan; textName.style.color = "rgb(var(--color-blue))"; text.appendChild(textName); if(activityCounter > 1){ textSpan.innerHTML = " liked your activities."; }; text.appendChild(textSpan); i += counter -1; } else if(activities[i].type == "replyActivity"){ var notNotImage = document.createElement("img"); notNotImage.classList.add("hohMediaImage"); notNotImage.classList.add(activities[i].link); notNotImageContainer.appendChild(notNotImage); var counter = 1; while( i + counter < activities.length && activities[i + counter].type == "replyActivity" && activities[i + counter].link == activities[i].link ){ var miniImageWidth = 40; var miniImage = document.createElement("a"); miniImage.classList.add("hohUserImageSmall"); miniImage.href = activities[i + counter].href; miniImage.style.backgroundImage = activities[i + counter].image; miniImage.style.height = miniImageWidth + "px"; miniImage.style.width = miniImageWidth + "px"; miniImage.style.marginLeft = (72 + (counter-1)*miniImageWidth) + "px"; newNotification.appendChild(miniImage); counter++; }; if(counter > 1){ text.style.marginTop = "45px"; activities[i].textName += " +"; }; text.href = activities[i].directLink; var textName = document.createElement("span"); var textSpan = document.createElement("span"); textName.innerHTML = activities[i].textName; textSpan.innerHTML = activities[i].textSpan; textName.style.color = "rgb(var(--color-blue))"; text.appendChild(textName); text.appendChild(textSpan); i += counter -1; } else if( activities[i].type == "messageActivity" || activities[i].type == "likeReplyActivity" || activities[i].type == "mentionActivity" ){ var notNotImage = document.createElement("img"); notNotImage.classList.add("hohMediaImage"); notNotImage.classList.add(activities[i].link); notNotImageContainer.appendChild(notNotImage); text.href = activities[i].directLink; var textName = document.createElement("span"); var textSpan = document.createElement("span"); textName.innerHTML = activities[i].textName; textSpan.innerHTML = activities[i].textSpan; textName.style.color = "rgb(var(--color-blue))"; text.appendChild(textName); text.appendChild(textSpan); } else if(activities[i].type == "airingActivity"){ //text.href = activities[i].directLink; var textSpan = document.createElement("span"); textSpan.innerHTML = activities[i].text; text.appendChild(textSpan); } else if(activities[i].type == "followActivity"){ text.href = activities[i].directLink; var textName = document.createElement("span"); var textSpan = document.createElement("span"); textName.innerHTML = activities[i].textName; textSpan.innerHTML = activities[i].textSpan; textName.style.color = "rgb(var(--color-blue))"; text.appendChild(textName); text.appendChild(textSpan); } else{//display as-is var textSpan = document.createElement("span"); textSpan.classList.add("hohUnhandledSpecial"); textSpan.innerHTML = activities[i].text; text.appendChild(textSpan); }; var time = document.createElement("div"); time.classList.add("hohTime"); time.innerHTML = activities[i].time; var commentsContainer = document.createElement("div"); commentsContainer.classList.add("hohCommentsContainer"); commentsContainer.classList.add("b" + activities[i].link);//possible replies var comments = document.createElement("a"); comments.classList.add("hohComments"); comments.innerHTML = "comments<span class=\"hohMonospace\">+</span>"; comments.onclick = function(){ if(this.innerText == "comments+"){ this.innerHTML = "comments<span class=\"hohMonospace\">-</span>"; this.parentNode.children[1].style.display = "inline-block"; var query = "query ($id: Int!) { Activity(id: $id) { ... on TextActivity { id userId type replyCount text createdAt user { id name avatar { large } } likes { id name avatar { large } } replies { id text createdAt user { id name avatar { large } } likes { id name avatar { large } } } } ... on ListActivity { id userId type status progress replyCount createdAt user { id name avatar { large } } media { coverImage { large } id title { userPreferred } } likes { id name avatar { large } } replies { id text createdAt user { id name avatar { large } } likes { id name avatar { large } } } } ... on MessageActivity { id type replyCount createdAt messenger { id name avatar { large } } likes { id name avatar { large } } replies { id text createdAt user { id name avatar { large } } likes { id name avatar { large } } } } } }"; var variables = { id: +this.parentNode.classList[1].substring(1) }; var vars = {}; var commentCallback = function(data,vars){ var listOfComments = document.getElementsByClassName("b" + data.data.Activity.id); for(var k=0;k<listOfComments.length;k++){ while(listOfComments[k].children[1].childElementCount ){ listOfComments[k].children[1].removeChild(listOfComments[k].children[1].lastChild); }; for(var l=0;l<data.data.Activity.replyCount;l++){ var quickCom = document.createElement("div"); quickCom.classList.add("hohQuickCom"); var quickComName = document.createElement("span"); quickComName.classList.add("hohQuickComName"); quickComName.innerHTML = data.data.Activity.replies[l].user.name; if(data.data.Activity.replies[l].user.name === whoAmI){//replace with class later quickComName.style.color = "rgb(var(--color-green))"; }; var quickComContent = document.createElement("span"); quickComContent.classList.add("hohQuickComContent"); quickComContent.innerHTML = badMarkupParser(data.data.Activity.replies[l].text); var quickComLikes = document.createElement("span"); quickComLikes.classList.add("hohQuickComLikes"); if(data.data.Activity.replies[l].likes.length > 1){ quickComLikes.innerHTML = data.data.Activity.replies[l].likes.length + "♥"; } else if(data.data.Activity.replies[l].likes.length){ quickComLikes.innerHTML = "♥"; }; for(var m=0;m<data.data.Activity.replies[l].likes.length;m++){ if(data.data.Activity.replies[l].likes[m].name == whoAmI){//replace with class later quickComLikes.style.color = "rgb(var(--color-red))"; }; }; quickCom.appendChild(quickComName); quickCom.appendChild(quickComContent); quickCom.appendChild(quickComLikes); listOfComments[k].children[1].appendChild(quickCom); }; }; }; listActivityCall(query,variables,commentCallback,vars,false); } else{ this.innerHTML = "comments<span class=\"hohMonospace\">+</span>"; this.parentNode.children[1].style.display = "none"; }; }; comments.classList.add("link"); var commentsArea = document.createElement("div"); commentsArea.classList.add("hohCommentsArea"); commentsContainer.appendChild(comments); commentsContainer.appendChild(commentsArea); newNotification.appendChild(notImage); newNotification.appendChild(text); newNotification.appendChild(notNotImageContainer); if(!timeHideFlag){ newNotification.appendChild(time); }; newNotification.appendChild(commentsContainer); newContainer.appendChild(newNotification); }; for(var i=0;document.APIcallsUsed < 90;i++){//heavy if(!activities.length || i >= activities.length){//loading is difficult to predict. There may be nothing there when this runs break; }; var imageCallBack = function(data,vars){ var type = data.data.Activity.type; var extra = 0; for(var j=0;j<notifications.length;j++){ extra = j; if(notifications[j].hasOwnProperty("already")){ break; }; }; if(type == "ANIME_LIST" || type == "MANGA_LIST"){ var listOfStuff = document.getElementsByClassName(data.data.Activity.id); for(var k=0;k<listOfStuff.length;k++){ listOfStuff[k].style.backgroundImage = "url(" + data.data.Activity.media.coverImage.large + ")"; listOfStuff[k].classList.add("hohBackgroundCover"); }; } else if(type == "TEXT"){ var listOfStuff = document.getElementsByClassName(data.data.Activity.id); for(var k=0;k<listOfStuff.length;k++){ listOfStuff[k].style.backgroundImage = "url(" + data.data.Activity.user.avatar.large + ")"; listOfStuff[k].classList.add("hohBackgroundUserCover"); }; }; if(data.data.Activity.replyCount){ var listOfComments = document.getElementsByClassName("b" + data.data.Activity.id); for(var k=0;k<listOfComments.length;k++){ if(listOfComments[k].children[0].style.display != "block"){ listOfComments[k].children[0].style.display = "block"; for(var l=0;l<data.data.Activity.replyCount;l++){ var quickCom = document.createElement("div"); quickCom.classList.add("hohQuickCom"); var quickComName = document.createElement("span"); quickComName.classList.add("hohQuickComName"); quickComName.innerHTML = data.data.Activity.replies[l].user.name; if(data.data.Activity.replies[l].user.name === whoAmI){ quickComName.style.color = "rgb(var(--color-green))"; }; var quickComContent = document.createElement("span"); quickComContent.classList.add("hohQuickComContent"); quickComContent.innerHTML = badMarkupParser(data.data.Activity.replies[l].text); var quickComLikes = document.createElement("span"); quickComLikes.classList.add("hohQuickComLikes"); if(data.data.Activity.replies[l].likes.length > 1){ quickComLikes.innerHTML = data.data.Activity.replies[l].likes.length + "♥"; } else if(data.data.Activity.replies[l].likes.length){ quickComLikes.innerHTML = "♥"; }; for(var m=0;m<data.data.Activity.replies[l].likes.length;m++){ if(data.data.Activity.replies[l].likes[m].name == whoAmI){ quickComLikes.style.color = "rgb(var(--color-red))"; }; }; quickCom.appendChild(quickComName); quickCom.appendChild(quickComContent); quickCom.appendChild(quickComLikes); listOfComments[k].children[1].appendChild(quickCom); }; }; }; }; }; var vars = { find: i }; var query = "query ($id: Int!) { Activity(id: $id) { ... on TextActivity { id userId type replyCount text createdAt user { id name avatar { large } } likes { id name avatar { large } } replies { id text createdAt user { id name avatar { large } } likes { id name avatar { large } } } } ... on ListActivity { id userId type status progress replyCount createdAt user { id name avatar { large } } media { coverImage { large } id title { userPreferred } } likes { id name avatar { large } } replies { id text createdAt user { id name avatar { large } } likes { id name avatar { large } } } } ... on MessageActivity { id type replyCount createdAt messenger { id name avatar { large } } likes { id name avatar { large } } replies { id text createdAt user { id name avatar { large } } likes { id name avatar { large } } } } } }"; if(activities[i].link[0] != "a"){//activities with post link if(activities.length){ var variables = { id: +activities[i].link }; if(localStorageAvailable){ var localStorageItem = localStorage.getItem(variables.id + ""); if( !(localStorageItem === null) || !pending.hasOwnProperty(activities[i].link) ){ listActivityCall(query,variables,imageCallBack,vars,true); pending[activities[i].link] = true; }; } else if( activityCache.hasOwnProperty(activities[i].link) || !pending.hasOwnProperty(activities[i].link) ){ listActivityCall(query,variables,imageCallBack,vars,true); pending[activities[i].link] = true; }; }; }; }; return notifications.length; }; var tryAgain = function(){//run the function again and again until we leave that page setTimeout(function(){ perform(); if(document.URL == "https://anilist.co/notifications"){ tryAgain() } else{ activeScripts.notifications = false; } },300); }; activeScripts.notifications = true; perform(); tryAgain(); };//end enhanceNotifications var enhanceFavourites = function(){ var matched = false; var pending = false; var perform = function(){ if(!document.URL.match(/https:\/\/anilist\.co\/user\/[0-9a-zA-Z-]+\/?$/)){ return; }; var favSection = document.getElementsByClassName("favourites"); if(!favSection || favSection.length == 0){ return; }; var listLocation = 0; if(favSection[0].children.length){ if( favSection[0].children[0].classList.length && favSection[0].children[0].classList[0] == "reorder-btn" ){ listLocation = 1; }; } else{ return; }; if( favSection[0].children[listLocation].children.length > 1 ){ matched = true; if(favSection[0].children[listLocation].children[1].children.length == 25){ var addMoreFavs = function(data){ if(data.data.User.favourites.anime.edges.length == 0){//user only has exactly 25 favs return; }; for(var i=0;i<data.data.User.favourites.anime.edges.length;i++){ var newFav = document.createElement("div"); newFav.classList.add("media-preview-card"); newFav.classList.add("small"); newFav.setAttribute("data-v-711636d7", "");//to allow native Anilist selectors to take effect. Not sure how rigid it is. newFav.setAttribute("data-v-0f38b704", "");/*replace with extra class later*/ newFav.style.display = "none"; var newFavCover = document.createElement("a"); newFavCover.classList.add("cover"); newFavCover.style.backgroundImage = "url(" + data.data.User.favourites.anime.edges[i].node.coverImage.large + ")"; newFavCover.setAttribute("data-v-711636d7", ""); newFavCover.href = "https://anilist.co/anime/" + data.data.User.favourites.anime.edges[i].node.id; var newFavContent = document.createElement("div"); newFavContent.classList.add("content"); //newFavContent.innerHTML = "test" + i; newFav.appendChild(newFavCover); newFav.appendChild(newFavContent); favSection[0].children[listLocation].children[1].appendChild(newFav); }; var expandButton = document.createElement("button"); expandButton.innerHTML = "+"; expandButton.onclick = function(){ for(var j=0;j<this.parentNode.children.length;j++){ this.parentNode.children[j].style.display = "inline-grid"; }; this.style.display = "none"; }; favSection[0].children[listLocation].children[1].appendChild(expandButton); }; var nameMatch = /https:\/\/anilist\.co\/user\/([0-9a-zA-Z-]+)\/?$/; var variables = { name: nameMatch.exec(document.URL)[1] }; var query = ` query ($name: String!) { User (name: $name) { favourites { anime (page: 2, perPage: 25){ edges { favouriteOrder node { id title { userPreferred } coverImage { large } } } } } } } `; if(!pending){ pending = true; generalAPIcall(query,variables,addMoreFavs); }; }; }; }; var tryAgain = function(){//run the function again and again until we leave that page setTimeout(function(){ perform(); if(document.URL.match(/https:\/\/anilist\.co\/user\/[0-9a-zA-Z-]*\/?$/) && matched == false){ tryAgain() } else{ activeScripts.favourites = false; } },1000);//no problem with this being slow }; activeScripts.favourites = true; perform(); tryAgain(); }; var handleScripts = function(url){ if(url == "https://anilist.co/notifications" && activeScripts.notifications == false){ enhanceNotifications(); } else if( url.match(/https:\/\/anilist\.co\/(anime|manga)\/\d*\/[0-9a-zA-Z-]*\/social/) && activeScripts.socialTab == false ){ enhanceSocialTab(); } else if( url.match(/https:\/\/anilist\.co\/user\/[0-9a-zA-Z-]+\/?$/) && activeScripts.favourites == false ){ enhanceFavourites(); } else if( url.match(/https:\/\/anilist\.co\/forum\/thread\/.*/) && activeScripts.forumComments == false ){ enhanceForum(); } else if( url.match(/https:\/\/anilist\.co\/staff\/.*/) && activeScripts.staffPages == false ){ enhanceStaff(); } else if( url.match(/https:\/\/anilist\.co\/(anime|manga)\/.*/) && activeScripts.tagDescriptions == false ){ enhanceTags(); } else if( url.match(/https:\/\/anilist\.co\/home\/?/) && activeScripts.completedScore == false ){ addCompletedScores(); } else if(false){//imp later, config }; }; var activeScripts = { notifications : false, socialTab : false, favourites : false, forumComments : false, staffPages : false, tagDescriptions : false, completedScore : false }; var current = ""; setInterval(function(){ if(document.URL != current){ current = document.URL; handleScripts(current); }; var expandPossible = document.getElementsByClassName("description-length-toggle"); if(expandPossible.length){ expandPossible[0].click(); }; },200); var tagDescriptions = { "4-koma" : "A manga in the 'yonkoma' format, which consists of four equal-sized panels arranged in a vertical strip.", "Achronological Order" : "Chapters/episodes do not occur in chronological order.", "Afterlife" : "Partly or completely set in the afterlife.", "Age Gap" : "Prominently features romantic relations between people with a significant age difference.", "Ahegao" : "Features a character making an exaggerated orgasm face.", "Airsoft" : "Centers around the sport of airsoft.", "Aliens" : "Prominently features extraterrestrial lifeforms.", "Alternate Universe" : "Features multiple alternate universes in the same series.", "American Football" : "Centers around the sport of American football.", "Amnesia" : "Prominently features a character(s) with memory loss.", "Anal Sex" : "Features sexual penetration of the anal cavity.", "Animals" : "Prominently features animal characters in a leading role.", "Anti-Hero" : "Features a protagonist who lacks conventional heroic attributes and may be considered a borderline villain.", "Archery" : "Centers around the sport of archery, or prominently features the use of archery in combat.", "Ashikoki" : "Footjob; features stimulation of genitalia by feet.", "Assassins" : "Centers around characters who murder people as a profession.", "Athletics" : "Centers around sporting events that involve competitive running, jumping, throwing, or walking.", "Augmented Reality" : "Prominently features events with augmented reality as the main setting.", "Aviation" : "Regarding the flying or operation of aircraft.", "Badminton" : "Centers around the sport of badminton.", "Band" : "Main cast is a group of musicians.", "Bar" : "Partly or completely set in a bar.", "Baseball" : "Centers around the sport of baseball.", "Basketball" : "Centers around the sport of basketball.", "Battle Royale" : "Centers around a fierce group competition, often violent and with only one winner.", "Biographical" : "Based on true stories of real persons living or dead.", "Bisexual" : "Features a character who is romantically and/or sexually attracted to people of more than one sex and/or gender.", "Blackmail" : "Features a character blackmailing another into performing sexual acts.", "Body Swapping" : "Centers around individuals swapping bodies with one another.", "Bondage" : "Features BDSM, with or without the use of accessories.", "Boxing" : "Centers around the sport of boxing.", "Bullying" : "Prominently features the use of force for intimidation, often in a school setting.", "Calligraphy" : "Centers around the art of calligraphy.", "Card Battle" : "Centers around individuals competing in card games.", "Cars" : "Centers around the use of automotive vehicles.", "CGI" : "Prominently features scenes created with computer-generated imagery.", "Chibi" : "Features \"super deformed\" character designs with smaller, rounder proportions and a cute look.", "Chuunibyou" : "Prominently features a character with \"Middle School 2nd Year Syndrome\", who either acts like a know-it-all adult or falsely believes they have special powers.", "Classic Literature" : "Adapted from a work of classic world literature.", "College" : "Partly or completely set in a college or university.", "Coming of Age" : "Centers around a character's transition from childhood to adulthood.", "Conspiracy" : "Contains one or more factions controlling or attempting to control the world from the shadows.", "Cosplay" : "Features dressing up as a different character or profession.", "Crossdressing" : "Prominently features a character dressing up as the opposite sex.", "Crossover" : "Centers around the placement of two or more otherwise discrete fictional characters, settings, or universes into the context of a single story.", "Cultivation" : "Features characters using training, often martial arts-related, and other special methods to cultivate life force and gain strength or immortality.", "Cunnilingus" : "Features oral sex performed on female genitalia.", "Cute Girls Doing Cute Things" : "Centers around, well, cute girls doing cute things.", "Cyberpunk" : "Set in a future of advanced technological and scientific achievements that have resulted in social disorder.", "Cycling" : "Centers around the sport of cycling.", "Dancing" : "Centers around the art of dance.", "Dark Skin" : "Features dark-skinned characters in a sexual context.", "Deflowering" : "There is already a \"Virgin\" tag", "Delinquents" : "Features characters with a notorious image and attitude, sometimes referred to as \"yankees\".", "Demons" : "Prominently features malevolent otherworldly creatures.", "Development" : "Centers around characters developing or programming a piece of technology, software, gaming, etc.", "Dragons" : "Prominently features mythical reptiles which generally have wings and can breathe fire.", "Drawing" : "Centers around the art of drawing, including manga and doujinshi.", "Dystopian" : "Partly or completely set in a society characterized by poverty, squalor or oppression", "Economics" : "Centers around the field of economics.", "Educational" : "Primary aim is to educate the audience.", "Ensemble Cast" : "Features a large cast of characters with (almost) equal screen time and importance to the plot.", "Environmental" : "concern with the state of the natural world and how humans interact with it.", "Episodic" : "Features story arcs that are loosely tied or lack an overarching plot.", "Espionage" : "Prominently features characters infiltrating an organization in order to steal sensitive information.", "Facial" : "Features sexual ejaculation onto an individual's face.", "Fairy Tale" : "This show tells a fairy tale, centers around fairy tales, or is based on a classic fairy tale.", "Family Life" : "Centers around the activities of a family unit.", "Fashion" : "Centers around the fashion industry.", "Fellatio" : "Features oral sex performed on male genitalia.", "Female Protagonist" : "Main character is female.", "Fishing" : "Centers around the sport of fishing.", "Fitness" : "Centers around exercise with the aim of improving physical health.", "Flash" : "Created using Flash animation techniques.", "Flat Chest" : "Features a female character with smaller-than-average breasts.", "Food" : "Centers around cooking or food appraisal.", "Football" : "Centers around the sport of football (known in the USA as \"soccer\").", "Foreign" : "Partly or completely set in a country outside of Japan.", "Fugitive" : "Prominently features a character evading capture by an individual or organization.", "Full CGI" : "Almost entirely created with computer-generated imagery.", "Full Colour" : "Fully coloured or drawn in colour.", "Futanari" : "Features female characters with male genitalia.", "Gambling" : "Centers around the act of gambling.", "Gangs" : "Centers around gang organizations.", "Gender Bending" : "Prominently features a character who dresses and behaves in a way characteristic of the opposite sex, or has been transformed into a person of the opposite sex.", "Gender Neutral" : "Prominently features agender characters.", "Ghost" : "Prominently features a character who is a ghost.", "Go" : "Centered around the game of Go.", "Gods" : "Prominently features a character of divine or religious nature.", "Gore" : "Prominently features graphic bloodshed and violence.", "Guns" : "Prominently features the use of guns in combat.", "Gyaru" : "Prominently features a female character who has a distinct American-emulated fashion style, such as tanned skin, bleached hair, and excessive makeup. Also known as gal.", "Harem" : "Main cast features one male character plus several female characters who are romantically interested in him.", "Henshin" : "Prominently features character or costume transformations which often grant special abilities.", "Hikikomori" : "Prominently features a character who withdraws from social life, often seeking extreme isolation.", "Historical" : "Partly or completely set during a real period of world history.", "Human Pet" : "Features characters in a master-slave relationship where one is the \"owner\" and the other is a \"pet.\"", "Ice Skating" : "Centers around the sport of ice skating.", "Idol" : "Centers around the life and activities of an idol.", "Incest" : "Features sexual relations between characters who are related by blood.", "Irrumatio" : "Oral rape; features a character thrusting their genitalia into the mouth of another character.", "Isekai" : "Features characters being transported into an alternate world setting and having to adapt to their new surroundings.", "Iyashikei" : "Primary aim is to heal the audience through serene depictions of characters' daily lives.", "Josei" : "Target demographic is adult females.", "Kaiju" : "Prominently features giant monsters.", "Karuta" : "Centers around the game of karuta.", "Kemonomimi" : "Prominently features humanoid characters with animal ears.", "Kids" : "Target demographic is young children.", "Lacrosse" : "A team game played with a ball and lacrosse sticks.", "Large Breasts" : "Features a character with larger-than-average breasts.", "Lost Civilisation" : "Featuring a civilisation with few ruins or records that exist in present day knowledge.", "Love Triangle" : "Centered around romantic feelings between more than two people. Includes all love polygons.", "Mafia" : "Centered around Italian organised crime syndicates.", "Magic" : "Prominently features magical elements or the use of magic.", "Mahjong" : "Centered around the game of mahjong.", "Maids" : "Prominently features a character who is a maid.", "Male Protagonist" : "Main character is male.", "Martial Arts" : "Centers around the use of traditional hand-to-hand combat.", "Masturbation" : "Features erotic stimulation of one's own genitalia or other erogenous regions.", "Memory Manipulation" : "Prominently features a character(s) who has had their memories altered.", "Meta" : "Features fourth wall-breaking references to itself or genre tropes.", "MILF" : "Features sexual intercourse with older women.", "Military" : "Centered around the life and activities of military personnel.", "Monster Girl" : "Prominently features a female character who is part-monster.", "Mopeds" : "Prominently features mopeds.", "Motorcycles" : "Prominently features the use of motorcycles.", "Musical" : "Features a performance that combines songs, spoken dialogue, acting, and dance.", "Mythology" : "Prominently features mythological elements, especially those from religious or cultural tradition.", "Nakadashi" : "Creampie; features sexual ejaculation inside of a character.", "Nekomimi" : "Humanoid characters with cat-like features such as cat ears and a tail.", "Netorare" : "NTR; features a character with a partner shown being intimate with someone else.", "Netorase" : "Features characters in a romantic relationship who agree to be sexually intimate with others.", "Netori" : "Features a character shown being intimate with the partner of another character. The opposite of netorare.", "Ninja" : "Prominently features Japanese warriors traditionally trained in espionage, sabotage and assasination.", "No Dialogue" : "This anime contains no dialogue.", "Noir" : "Stylized as a cynical crime drama with low-key visuals.", "Nudity" : "Features a character wearing no clothing or exposing intimate body parts.", "Otaku Culture" : "Centers around the culture of a fanatical fan-base.", "Outdoor" : "Centers around hiking, camping or other outdoor activities.", "Paizuri" : "Features the stimulation of male genitalia by breasts.", "Parody" : "Features deliberate exaggeration of popular tropes or a particular genre to comedic effect.", "Philosophy" : "Relating or devoted to the study of the fundamental nature of knowledge, reality, and existence.", "Photography" : "Centers around the use of cameras to capture photos.", "Pirates" : "Prominently features sea-faring adventurers branded as criminals by the law.", "Poker" : "Centers around the game of poker or its variations.", "Police" : "Centers around the life and activities of law enforcement officers.", "Politics" : "Centers around politics, politicians, or government activities.", "Post-Apocalyptic" : "Partly or completely set in a world or civilization after a global disaster.", "POV" : "Point of View; features sexual scenes shown from the perspective of the series protagonist.", "Pregnant" : "Features pregnant female characters in a sexual context.", "Primarily Adult Cast" : "Main cast is mostly composed of characters above a high school age.", "Primarily Child Cast" : "Main cast is mostly composed of characters below a high school age.", "Primarily Female Cast" : "Main cast is mostly composed of female characters.", "Primarily Male Cast" : "Main cast is mostly composed of male characters.", "Prostitution" : "Features characters who are paid for sexual favors.", "Public Sex" : "Features sexual acts performed in public settings.", "Puppetry" : "Animation style involving the manipulation of puppets to act out scenes.", "Rape" : "Features non-consensual sexual penetration.", "Real Robot" : "Prominently features mechanical designs loosely influenced by real-world robotics.", "Rehabilitation" : "Prominently features the recovery of a character who became incapable of social life or work.", "Reincarnation" : "Features a character being born again after death, typically as another person or in another world.", "Revenge" : "Prominently features a character who aims to exact punishment in a resentful or vindictive manner.", "Reverse Harem" : "Main cast features one female character plus several male characters who are romantically interested in her.", "Robots" : "Prominently features humanoid machines.", "Rugby" : "Centers around the sport of rugby.", "Rural" : "Partly or completely set in the countryside.", "Samurai" : "Prominently features warriors of medieval Japanese nobility bound by a code of honor.", "Satire" : "Prominently features the use of comedy or ridicule to expose and criticise social phenomena.", "Scat" : "Lots of feces.", "School" : "Partly or completely set in a primary or secondary educational institution.", "School Club" : "Partly or completely set in a school club scene.", "Seinen" : "Target demographic is adult males.", "Sex Toys" : "Features objects that are designed to stimulate sexual pleasure.", "Ships" : "Prominently features the use of sea-based transportation vessels.", "Shogi" : "Centers around the game of shogi.", "Shoujo" : "Target demographic is teenage and young adult females.", "Shoujo Ai" : "Prominently features romance between two females.", "Shounen" : "Target demographic is teenage and young adult males.", "Shounen Ai" : "Prominently features romance between two males.", "Slapstick" : "Prominently features comedy based on deliberately clumsy actions or embarrassing events.", "Slavery" : "Prominently features slaves, slavery, or slave trade.", "Space" : "Partly or completely set in outer space.", "Space Opera" : "Centers around space warfare, advanced technology, chivalric romance and adventure.", "Steampunk" : "Prominently features technology and designs inspired by 19th-century industrial steam-powered machinery.", "Stop Motion" : "Animation style characterized by physical objects being moved incrementally between frames to create the illusion of movement.", "Sumata" : "Pussyjob; features the stimulation of male genitalia by the thighs and labia majora of a female character.", "Super Power" : "Prominently features characters with special abilities that allow them to do what would normally be physically or logically impossible.", "Super Robot" : "Prominently features large robots often piloted by hot-blooded protagonists.", "Superhero" : "Prominently features super-powered humans who aim to serve the greater good.", "Surreal Comedy" : "Prominently features comedic moments that defy casual reasoning, resulting in illogical events.", "Survival" : "Centers around the struggle to live in spite of extreme obstacles.", "Swimming" : "Centers around the sport of swimming.", "Swordplay" : "Prominently features the use of swords in combat.", "Table Tennis" : "Centers around the sport of table tennis (also known as \"ping pong\").", "Tanks" : "Prominently features the use of tanks or other armoured vehicles.", "Teacher" : "Protagonist is an educator, usually in a school setting.", "Tekoki" : "Handjob; features the stimulation of genitalia by another's hands.", "Tennis" : "Centers around the sport of tennis.", "Tentacles" : "Features the long appendages most commonly associated with octopuses or squid, often sexually penetrating a character.", "Terrorism" : "Centers around the activities of a terrorist or terrorist organization.", "Threesome" : "Features sexual acts between three people.", "Time Manipulation" : "Prominently features time-traveling or other time-warping phenomena.", "Time Skip" : "Features a gap in time used to advance the story.", "Tragedy" : "Centers around tragic events and unhappy endings.", "Trains" : "Prominently features trains.", "Triads" : "Centered around Chinese organised crime syndicates.", "Tsundere" : "Prominently features a character who acts cold and hostile in order to mask warmer emotions.", "Urban Fantasy" : "Set in a world similar to the real world, but with the existence of magic or other supernatural elements.", "Urination" : "Features one character urinating on another. Also know as a \"golden shower.\"", "Vampire" : "Prominently features a character who is a vampire.", "Video Games" : "Centers around characters playing video games.", "Virgin" : "Features a character who has never had sexual relations (until now).", "Virtual World" : "Partly or completely set in the world inside a video game.", "Volleyball" : "Centers around the sport of volleyball.", "Voyeur" : "Features a character who enjoys seeing the sex acts or sex organs of others.", "War" : "Partly or completely set during wartime.", "Witch" : "Prominently features a character who is a witch.", "Work" : "Centers around the activities of a certain occupation.", "Wrestling" : "Centers around the sport of wrestling.", "Writing" : "Centers around the profession of writing books or novels.", "Wuxia" : "Chinese fiction concerning the adventures of martial artists in Ancient China.", "Yakuza" : "Centered around Japanese organised crime syndicates.", "Yandere" : "Prominently features a character who is obsessively in love with another, to the point of acting deranged or violent.", "Yaoi" : "Features sexual intercourse between two males.", "Youkai" : "Prominently features supernatural creatures from Japanese folklore.", "Yuri" : "Features sexual intercourse between two females.", "Zombie" : "Prominently features reanimated corpses which often prey on live humans and turn them into zombies." }; console.log("Aniscripts 0.91"); })();