VoidVerified

Display a verified sign next to user's name in AniList.

当前为 2023-10-31 提交的版本,查看 最新版本

// ==UserScript==
// @name         VoidVerified
// @namespace    http://tampermonkey.net/
// @version      0.4.1
// @description  Display a verified sign next to user's name in AniList.
// @author       voidnyan
// @match        https://anilist.co/*
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
	"use strict";
	const version = "0.4.1";
	const evaluationIntervalInSeconds = 1;
	const localStorageColors = "void-verified-colors";

	const verified = {
		copyColorFromProfile: true,
		moveSubscribeButtons: true,
		hideLikeCount: false,
		username: {
			enabled: true,
			enabledForReplies: true,
			enabledForProfileName: true,
			color: "white",
			sign: "✔",
		},
		highlight: {
			enabled: true,
			enabledForReplies: true,
			enabledForSmallCards: false,
			color: undefined,
			size: "5px",
		},
	};

	const shouldIntervalBeUsed =
		verified.username.enabledForProfileName || verified.highlight.enabled;

	let verifiedUsers = [
		{
			username: "voidnyan",
			sign: "💻",
		},
	].map((u) => (typeof u === "string" ? { username: u } : u));

	const colorsInLocalStorage = JSON.parse(
		localStorage.getItem(localStorageColors)
	);

	if (colorsInLocalStorage !== null) {
		verifiedUsers = verifiedUsers.map((u) =>
			colorsInLocalStorage !== null && u.color
				? u
				: {
						...u,
						color: colorsInLocalStorage.find(
							(c) => c.username === u.username
						)?.color,
				  }
		);
	}

	let usernameStyles = "";
	let highlightStyles = "";
	let otherStyles = "";

	createStyles();

	function createStyles() {
		usernameStyles = "";
		highlightStyles = "";
		for (const user of verifiedUsers) {
			if (verified.username.enabled) {
				createUsernameCSS(user);
			}

			if (verified.highlight.enabled) {
				createHighlightCSS(
					user,
					`div.wrap:has( div.header > a.name[href*="${user.username}"] )`
				);
				createHighlightCSS(
					user,
					`div.wrap:has( div.details > a.name[href*="${user.username}"] )`
				);
			}

			if (verified.highlight.enabledForReplies) {
				createHighlightCSS(
					user,
					`div.reply:has( a.name[href*="${user.username}"] )`
				);
			}
		}

		if (
			verified.highlight.enabled &&
			!verified.highlight.enabledForSmallCards
		) {
			disableHighlightOnSmallCards();
		}

		if (verified.moveSubscribeButtons) {
			otherStyles += `
            .has-label::before {
            top: -30px !important;
            left: unset !important;
            right: -10px;
            }

            .has-label[label="Unsubscribe"],
            .has-label[label="Subscribe"] {
            font-size: 0.875em !important;
            }

            .has-label[label="Unsubscribe"] {
            color: rgba(var(--color-green),.8);
            }
            `;
		}

		if (verified.hideLikeCount) {
			otherStyles += `
                .like-wrap .count {
                    display: none;
            }
            `;
		}
	}

	function createUsernameCSS(user) {
		usernameStyles += `
            a.name[href*="${user.username}"]::after {
                content: "${user.sign ?? verified.username.sign}";
                color: ${
					user.color ??
					verified.username.color ??
					"rgb(var(--color-blue))"
				}
            }
            `;
	}

	function createHighlightCSS(user, selector) {
		highlightStyles += `
            ${selector} {
                margin-right: -${verified.highlight.size};
                border-right: ${verified.highlight.size} solid ${
			user.color ?? verified.highlight.color ?? "rgb(var(--color-blue))"
		};
                border-radius: 5px;
            }
            `;
	}

	function moveAndDisplaySubscribeButton() {
		if (!verified.moveSubscribeButtons) {
			return;
		}

		const subscribeButtons = document.querySelectorAll(
			"span[label='Unsubscribe'], span[label='Subscribe']"
		);
		for (const subscribeButton of subscribeButtons) {
			if (subscribeButton.parentNode.classList.contains("actions")) {
				continue;
			}

			if (verified.autoLikeOnSubscribe) {
				subscribeButton.addEventListener("click", likeActivity);
			}

			const container = subscribeButton.parentNode.parentNode;
			const actions = container.querySelector(".actions");
			actions.append(subscribeButton);
		}
	}

	function likeActivity() {
		// const container = this.parentNode;
		// const likeButton = container.querySelector(".like-wrap .button");
		// if (likeButton.classList.contains("liked")) {
		//     return;
		//
		// // likeButton.click();
		// likeButton.dispatchEvent(new Event("click"));
	}

	function disableHighlightOnSmallCards() {
		highlightStyles += `
            div.wrap:has(div.small) {
            margin-right: 0px !important;
            border-right: 0px solid black !important;
            }
            `;
	}

	const usernameLink = createStyleLink(usernameStyles, "username");
	const highlightLink = createStyleLink(highlightStyles, "highlight");
	const profileLink = createStyleLink("", "profile");
	const otherLink = createStyleLink(otherStyles, "other");

	function refreshHomePage() {
		if (!verified.highlight.enabled) {
			return;
		}

		const oldHighlightLink = document.getElementById(
			"void-verified-highlight-styles"
		);
		const newHighlightLink = createStyleLink(highlightStyles, "highlight");
		oldHighlightLink.remove();
	}

	function verifyProfile() {
		if (!verified.username.enabledForProfileName) {
			return;
		}

		const usernameHeader = document.querySelector("h1.name");
		const username = usernameHeader.innerHTML.trim();

		const user = verifiedUsers.find((u) => u.username === username);
		if (!user) {
			profileLink.href =
				"data:text/css;charset=UTF-8," + encodeURIComponent("");
			return;
		}

		const profileStyle = `
                h1.name::after {
                content: "${user.sign ?? verified.username.sign}"
                }
            `;
		profileLink.href =
			"data:text/css;charset=UTF-8," + encodeURIComponent(profileStyle);
	}

	function copyUserColor() {
		const usernameHeader = document.querySelector("h1.name");
		const username = usernameHeader.innerHTML.trim();
		const user = verifiedUsers.find((u) => u.username === username);

		if (
			user.copyColorFromProfile === false ||
			(!user.copyColorFromProfile && !verified.copyColorFromProfile)
		) {
			return;
		}

		const color =
			getComputedStyle(usernameHeader).getPropertyValue("--color-blue");
		user.color = `rgb(${color})`;
		verifiedUsers = verifiedUsers.map((u) =>
			u.username !== user.username ? u : user
		);

		createStyles();

		const oldHighlightLink = document.getElementById(
			"void-verified-highlight-styles"
		);
		const newHighlightLink = createStyleLink(highlightStyles, "highlight");
		oldHighlightLink.remove();

		const oldUsernameLink = document.getElementById(
			"void-verified-username-styles"
		);
		const newUsernameLink = createStyleLink(usernameStyles, "username");
		oldUsernameLink.remove();

		addOrUpdateColorToLocalStorage(user);
	}

	function addOrUpdateColorToLocalStorage(user) {
		let localColors = JSON.parse(localStorage.getItem(localStorageColors));

		if (localColors === null) {
			localStorage.setItem(
				localStorageColors,
				JSON.stringify([{ username: user.username, color: user.color }])
			);
			return;
		}

		let localStorageUser = localColors.find(
			(u) => u.username === user.username
		);
		if (localStorageUser) {
			localStorageUser.color = user.color;
			localColors = localColors.map((u) =>
				u.username === localStorageUser.username ? localStorageUser : u
			);
		} else {
			localColors.push({ username: user.username, color: user.color });
		}

		localStorage.setItem(localStorageColors, JSON.stringify(localColors));
	}

	function createStyleLink(styles, id) {
		const link = document.createElement("link");
		link.setAttribute("id", `void-verified-${id}-styles`);
		link.setAttribute("rel", "stylesheet");
		link.setAttribute("type", "text/css");
		link.setAttribute(
			"href",
			"data:text/css;charset=UTF-8," + encodeURIComponent(styles)
		);
		document.head?.append(link);
		return link;
	}

	let currentPath = "";
	function hasPathChanged(path) {
		if (path === currentPath) {
			return false;
		}
		currentPath = path;
		return true;
	}

	function handleIntervalScripts() {
		const path = window.location.pathname;

		moveAndDisplaySubscribeButton();

		if (path === "/home") {
			refreshHomePage();
			return;
		}

		if (!hasPathChanged(path)) {
			return;
		}

		if (path.startsWith("/user/")) {
			verifyProfile();
			copyUserColor();
		}
	}

	if (shouldIntervalBeUsed) {
		setInterval(handleIntervalScripts, evaluationIntervalInSeconds * 1000);
	}

	console.log(`VoidVerified ${version} loaded.`);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址