Aniscripts

Change stuff on Anilist.co

目前為 2018-08-22 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Aniscripts
// @namespace    http://tampermonkey.net/
// @version      0.43
// @description  Change stuff on Anilist.co
// @author       hoh
// @match        https://anilist.co/*
// @grant        none
// ==/UserScript==
(function(){
document.APIcallsUsed = 0;
var pending = {};
var APIcounter = setTimeout(function(){
	document.APIcallsUsed = 0;
},60*1000);


Element.prototype.remove = function() {
    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 activityCache = {};//reduce API calls

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';

var listActivityCall = function(query,variables,callback,vars){
	var handleData = function(data){
		pending[variables.id] = false;
		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(activityCache.hasOwnProperty(variables.id)){
		callback(activityCache[variables.id],vars);
		console.log("cache hit");
	}
	else{
		fetch(url,options).then(handleResponse).then(handleData).catch(handleError);
		++document.APIcallsUsed;
	};
};

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++){
			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.style.minWidth = "400px";
				elements[0].style.verticalAlign = "bottom";
				elements[0].style.marginTop = "0px";
				elements[1].style.verticalAlign = "middle";
				elements[1].style.marginLeft = "3px";
				elements[2].style.verticalAlign = "middle";
				elements[2].style.paddingBottom = "7px";
				listOfActs[i].style.marginBottom = "10px";
			};
		};
		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 && listOfFollowers[i].children[3].nodeName != "svg"){
				var followScore = listOfFollowers[i].children[3].innerText.match(/\d+/g);
				if(followScore && followScore.length == 2){
					averageScore += followScore[0]/followScore[1];
					averageCount++;
				};
			};
		};
		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";
		};
	};
	var tryAgain = function(){
		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 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");
		document.getElementsByClassName("reset-btn")[0].onclick = function(){
			var notf = document.getElementById("hohNotifications");
			for(var i=0;i<notf.children.length;i++){
				notf.children[i].style.borderRightStyle = "none";
			};
		};
		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){
				active.unread = true;
			}
			else{
				active.unread = false;
			};
			active.type = "special";
			active.link = "aaa";//fixme
			if(
				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
				&& notifications[i].children[1].children[0].children[0].children[0].textContent == " liked your activity."
			){
				active.type = "likeActivity";
				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];
			}
			else if(
				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
				&& notifications[i].children[1].children[0].children[0].children[0].textContent == " replied to your activity."
			){
				active.type = "replyActivity";
				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];
			}
			else if(
				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
				&& notifications[i].children[1].children[0].children[0].children[0].textContent == " sent you a message."
			){
				active.type = "messageActivity";
				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];
			}
			else if(
				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
				&& notifications[i].children[1].children[0].children[0].children[0].textContent == " liked your activity reply."
			){
				active.type = "likeReplyActivity";
				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];
			}
			else if(
				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
				&& notifications[i].children[1].children[0].children[0].children[0].textContent == " mentioned you in their activity."
			){
				active.type = "mentionActivity";
				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];
			}
			else 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.style.borderRightStyle = "none";
			};
			if(activities[i].unread){
				newNotification.style.borderRight = "8px";
				newNotification.style.borderColor = "red";
				newNotification.style.borderRightStyle = "solid";
			};
			newNotification.style.marginBottom = "10px";
			newNotification.style.background = "rgb(var(--color-foreground))";
			newNotification.style.borderRadius = "4px";
			var notImage = document.createElement("a");
			notImage.href = activities[i].href;
			notImage.style.backgroundImage = activities[i].image;
			notImage.style.height = "70px";
			notImage.style.width = "60px";
			notImage.style.display = "inline-block";
			notImage.style.backgroundPosition = "50%";
			notImage.style.backgroundRepeat = "no-repeat";
			notImage.style.backgroundSize = "cover";

			var notNotImageContainer = document.createElement("span");
			notNotImageContainer.style.verticalAlign = "bottom";
			notNotImageContainer.style.marginLeft = "400px";
			notNotImageContainer.style.position = "absolute";	

			var text = document.createElement("a");
			text.style.position = "absolute";
			text.style.marginTop = "30px";
			text.style.marginLeft = "10px";
			text.style.maxWidth = "330px";
			//text.style.display = "inline-block";

			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++
				){
					var notNotImage = document.createElement("img");
					notNotImage.classList.add(activities[i + counter].link);
					notNotImage.style.height = "70px";
					notNotImage.style.marginRight = "5px";
					notNotImageContainer.appendChild(notNotImage);
				};
				var activityCounter = counter;
				if(counter == 1){
					while(
						i + counter < activities.length
						&& activities[i + counter].type == "likeActivity"
						&& activities[i + counter].link == activities[i].link
					){
						var miniImageWidth = 40;
						var miniImage = document.createElement("a");
						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.display = "inline-block";
						miniImage.style.backgroundPosition = "50%";
						miniImage.style.backgroundRepeat = "no-repeat";
						miniImage.style.backgroundSize = "cover";
						miniImage.style.position = "absolute";
						miniImage.style.marginLeft = (60 + (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);
				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(activities[i].link);
				notNotImage.style.height = "70px";
				notNotImage.style.marginRight = "5px";
				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.href = activities[i + counter].href;
					miniImage.style.backgroundImage = activities[i + counter].image;
					miniImage.style.height = miniImageWidth + "px";
					miniImage.style.width = miniImageWidth + "px";
					miniImage.style.display = "inline-block";
					miniImage.style.backgroundPosition = "50%";
					miniImage.style.backgroundRepeat = "no-repeat";
					miniImage.style.backgroundSize = "cover";
					miniImage.style.position = "absolute";
					miniImage.style.marginLeft = (60 + (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"){
				var notNotImage = document.createElement("img");
				notNotImage.classList.add(activities[i].link);
				notNotImage.style.height = "70px";
				notNotImage.style.marginRight = "5px";
				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 == "likeReplyActivity"){
				var notNotImage = document.createElement("img");
				notNotImage.classList.add(activities[i].link);
				notNotImage.style.height = "70px";
				notNotImage.style.marginRight = "5px";
				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 == "mentionActivity"){
				var notNotImage = document.createElement("img");
				notNotImage.classList.add(activities[i].link);
				notNotImage.style.height = "70px";
				notNotImage.style.marginRight = "5px";
				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{
				var textSpan = document.createElement("span");
				textSpan.innerHTML = activities[i].text;
				text.appendChild(textSpan);
			};

			newNotification.appendChild(notImage);
			newNotification.appendChild(notNotImageContainer);
			newNotification.appendChild(text);
			var time = document.createElement("div");
			time.innerHTML = activities[i].time;
			time.style.position = "static";
			time.style.float = "right";
			time.style.marginRight = "20px";
			time.style.marginTop = "10px";
			newNotification.appendChild(time);
			newContainer.appendChild(newNotification);
		};
		for(var i=0;document.APIcallsUsed < 90;i++){//heavy
            if(!activities.length || i >= activities.length){
                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].src = data.data.Activity.media.coverImage.large;
					};
				}
				else if(type == "TEXT"){
					var listOfStuff = document.getElementsByClassName(data.data.Activity.id);
					for(var k=0;k<listOfStuff.length;k++){
						listOfStuff[k].src = data.data.Activity.user.avatar.large;
					};
				};
			};
			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"){
				if(activities.length){
					var variables = {
						id: +activities[i].link
					};
					if(activityCache.hasOwnProperty(activities[i].link) || !pending.hasOwnProperty(activities[i].link)){
						listActivityCall(query,variables,imageCallBack,vars);
						pending[activities[i].link] = true;
					};
				};
			};
		};
		return notifications.length;
	};
	var tryAgain = function(){
		setTimeout(function(){
			perform();
			if(document.URL == "https://anilist.co/notifications"){
				tryAgain()
			}
			else{
				activeScripts.notifications = false;
			}
		},300);
	};
	activeScripts.notifications = 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(false){//imp later, config
	};
};
var activeScripts = {
	notifications : false,
	socialTab : false
};
var current = "";
setInterval(function(){
	if(document.URL != current){
		current = document.URL;
		handleScripts(current);
	};
},200);
console.log("Aniscripts 0.43 initiated");
})();