VoidVerified

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

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)


// ==UserScript==
// @name         VoidVerified
// @namespace    http://tampermonkey.net/
// @version      0.3.4
// @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.3.4";
    const evaluationIntervalInSeconds = 1;
    const localStorageColors = "void-verified-colors";

    const verified = {
        copyColorFromProfile: 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 = "";

    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();
        }
    }

    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 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");

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

        copyUserColor(user, usernameHeader);

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

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

        const color = getComputedStyle(header).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(highlightStyles, "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;


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

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

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

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

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