// ==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.`);
})();