Aniscripts

Change stuff on Anilist.co

As of 30.09.2018. See апошняя версія.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Aniscripts
// @namespace    http://tampermonkey.net/
// @version      0.86
// @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;
}
.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 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(false){//imp later, config
	};
};
var activeScripts = {
	notifications : false,
	socialTab : false,
	favourites : false,
	forumComments : false,
	staffPages : 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);
console.log("Aniscripts 0.86");
})();