// ==UserScript== // @name Anilist // @namespace https://github.com/Makhloufbel/AnilistLiker // @homepage https://github.com/Makhloufbel // @version 0.3.7a // @description Allows users to quickly like posts on Anilist just by one click ,this version allow you to blacklist or whitelist any user for ease of use // @author Makhloufbel // @match https://anilist.co/* // @icon https://www.google.com/s2/favicons?sz=64&domain=anilist.co // @charset UTF-8 // @downloadURL none // ==/UserScript== (function () { "use strict"; const svgns = "http://www.w3.org/2000/svg"; const BLACKLIST_BUTTON_CLASSNAMES = ["btn", "btn-primary", "mmd1"]; /******** CSS of buttons divs uls ... ect ********/ const css = [ ` .btn-primary { color: rgb(var(--color-text)); background-color: rgb(var(--color-foreground-blue)); } .btn { display: inline-block; width: max-content; font-weight: bold; line-height: 1.5; color: rgb(var(--color-text)); text-align: center; text-decoration: none; vertical-align: middle; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; user-select: none; padding: 0.275rem 0.5rem; font-size: 1rem; border-radius: 0.25rem; transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; } .btn.mmd1 { box-sizing: border-box; font-size: 1.2rem; border: none; opacity: 0; position: absolute; top: .7em; left: 58%; } .btn:hover { background-color: rgb(var(--color-foreground-blue-dark)); color: rgb(var(--color-blue)); transition: .02s; } div.details:hover > .mmd1 { opacity: 1!important; transition: inherit; transform-origin: center; } .POPUP { padding: 5px; margin: 5px; background: #eee; border: 1px solid #aaa; } .mackDisplayBox { position: fixed; top: 80px; left: 200px; z-index: 999; min-width: 300px; min-height: 200px; padding: 20px; background-color: rgb(var(--color-foreground)); border: solid 1px; border-radius: 4px; box-shadow: black 2px 2px 20px; overflow: hidden; filter: brightness(110%); } .mackDisplayBox .scrollableContent { overflow: auto; height: 100%; scrollbar-width: thin; margin-top: 5px; padding: 30px; padding-top: 35px; padding-left: 15px; } .mackDisplayBoxClose { position: absolute; right: 15px; top: 15px; cursor: pointer; background-color: red; border: solid; border-width: 1px; border-radius: 2px; color: white; border-color: rgb(var(--color-text)); filter: drop-shadow(0 0 0.2rem crimson); z-index: 20; } .mackDisplayBoxClose:hover { filter: drop-shadow(0 0 0.75rem crimson); } .mackNewChapter .mackDisplayBoxClose { display: none; top: 7px; } .mackNewChapter:hover .mackDisplayBoxClose { display: inline; } .mackDisplayBoxTitle { position: absolute; top: 5px; left: 5px; padding: 1rem; font-weight: bold; font-size: 1.2em; background-color: inherit; z-index: 9999; } .mackResizePearl { position: absolute; right: 2px; bottom: 2px; width: 20px; height: 20px; border: solid; border-radius: 10px; background: rgb(var(--color-foreground)); cursor: se-resize; } .mackGuideHeading, .mackGuideHeading:visited { color: rgb(var(--color-blue)); } * { scrollbar-color: rgb(var(--color-blue)) rgba(0, 0, 0, 0); scrollbar-width: thin; } ::-webkit-scrollbar { width: 4px; height: 8px; } ::-webkit-scrollbar-button { display: none; } ::-webkit-scrollbar-track { background-color: #1110; width: 0px; } ::-webkit-scrollbar-track-piece { display: none; } ::-webkit-scrollbar-thumb { background-color: rgb(var(--color-blue)); } #myContainer { position: fixed; left: 5px; align-items: center; height: 7rem; width: 100px; } .mmd2{ border: 2px solid rgb(var(--color-foreground-blue-dark)); width: 9em; height: 2.125em; cursor: pointer; display: inline-block; font-weight: bold; font-size: inherit; padding: 0 5px; line-height: 1.2em; text-align: center; text-decoration: none; user-select: none; -webkit-user-select: none; touch-action: manipulation; } .mmd2.btntop{ border-radius: 10px 10px 0 0; } .mmd2.btnbottom{ border-radius: 0 0 10px 10px; } .mmd2:active { box-shadow: rgb(var(--color-foreground-blue)) 2px 2px 0 0; transform: translate(2px, 2px); } .scrollableContent >p{ display: flex; flex-direction: column; justify-content: center; width: 100%; height: 2em; margin: 0; font-weight: bold; font-size: inherit; padding: 10px 50px; } .scrollableContent >p{ font-size: 1.8rem; } .scrollableContent p:nth-child(2n) { background-color: rgba(var(--color-foreground-blue),.0); } .scrollableContent p:nth-child(2n-1) { background-color: rgba(var(--color-foreground-blue-dark),.2); } p >.mackDisplayBoxClose{ display: inline-block; right: 30px; font-weight: normal; background-color: red; transform: translateY(30%) } .mackDisplayBox .scrollableContent{ padding: 30px 0 0 0; margin: 0 -20px 0 -20px; } div.scrollableContent { counter-reset: section1; } p.mackNewChapter::before { position: absolute; left: 1.4em; counter-increment: section1; content: counter(section1) " - "; transform: translateX(-5%); } .profile-btn{ display: flex; transform: translate(0px, -40%); place-content: flex-start center; background: rgba(var(--color-blue),.8); border-radius: 4px; color: rgb(var(--color-white)); cursor: pointer; display: inline-block; margin-left: 10px; margin-right: 10px; padding: 10px 12px; text-align: center; transition: .4s; border: none; } `, ]; /*********** verify if logged in**********/ let userObject; let whoAmI = ""; let whoAmIid = 0; try { userObject = JSON.parse(localStorage.getItem("auth")); } catch (err) { console.warn("could not get userObject"); } if (userObject) { whoAmI = userObject.name; whoAmIid = userObject.id; } else { try { whoAmI = document .querySelector(".nav .links .link[href^='/user/']") .href.match(/\/user\/(.*)\//)[1]; //looks at the navbar } catch (e) { console.warn("could not get username"); alert("Please login before to use this script!!!"); return; } } /********* add CSS ********/ document.head.insertAdjacentHTML("beforeend", ""); let username = String("https://anilist.co/user/" + whoAmI + "/"); //document.querySelector(".nav .links .link[href^='/user/']").href; /********* functions to store data *********/ const setObj = function (key, obj) { localStorage.setItem(key, JSON.stringify(obj)); }; const getObj = function (key) { return JSON.parse(localStorage.getItem(key)); }; if (getObj("blacklist") === null || getObj("blacklist").length == 0) { setObj("blacklist", [username]); } /****** the Main function *******/ (function main() { let div = create( "div", "#myContainer", false, document.querySelector("#nav > div.wrap") ); let blacklistbtn = create( "button", ["btn", "btn-primary", "mmd2", "btntop"], "Show blacklist", div ); var likeAllbtn = create( "button", ["btn", "btn-primary", "mmd2", "btnbottom"], "Like all posts", div ); blacklistbtn.onclick = () => { POPUP(); }; likeAllbtn.onclick = () => { likeBtnHandler(); }; })(); /******** Utilities functions *********/ function homePageHandler() { let divs = document.querySelectorAll("div.details:not(.ided)"); for (let e of divs) { createbtn(e); } } function createbtn(e) { if (e.closest(".wrap").getElementsByClassName("name")[0].href === username) return; addAttribute(e); let btn = create( "button", ["btn", "btn-primary", "mmd1"], String(e.getAttribute("data-status")) === "blacklisted" ? "whitelist" : "blacklist", false, "position : absolute;" ); btn.onclick = () => { switch (String(e.getAttribute("data-status"))) { case "whitelisted": blacklistbtn(e); btn.remove(); addAttribute(e); createbtn(e); break; case "blacklisted": whitelistbtn(e); btn.remove(); addAttribute(e); createbtn(e); break; } deleteAllBtn(); }; e.children[0].after(btn); e.classList.add("ided"); } function userProfileHandler() { let div = document.querySelector(".name-wrapper"); createProfilebtn(div); } function createProfilebtn(e) { if (String("https://anilist.co/user/" + e.innerText + "/") === username) return; addAttributeToProfile(e); let btn = create( "button", ["nav-btn", "profile-btn"], String(e.getAttribute("data-status")) === "blacklisted" ? "whitelist" : "blacklist", false, false ); btn.onclick = () => { switch (String(e.getAttribute("data-status"))) { case "whitelisted": blacklistbtn(e); break; case "blacklisted": whitelistbtn(e); break; default: console.log("Error"); break; } deleteAllBtn(); userProfileHandler(e); }; e.after(btn); } function addAttributeToProfile(b) { let blacklist = getObj("blacklist"); if (String("https://anilist.co/user/" + b.innerText + "/") == username) return; if ( blacklist.includes(String("https://anilist.co/user/" + b.innerText + "/")) ) { b.setAttribute("data-status", "blacklisted"); } else { b.setAttribute("data-status", "whitelisted"); } } function deleteAllBtn() { document.querySelectorAll("button.btn.btn-primary.mmd1").forEach((e) => { e.remove(); }); document.querySelectorAll("div.details").forEach((e) => { e.classList.remove("ided"); }); document.querySelectorAll(".profile-btn").forEach((e) => { e.remove(); }); } function POPUP() { let blacklist = getObj("blacklist"); let box = createDisplayBox( "width:600px;height:500px;top:100px;left:220px;", "Blacklisted" ); for (let e of blacklist) { let listing = create( "p", "mackNewChapter", false, false, "position:relative;" ); create("a", ["link", "newTab"], getName(e), listing).href = "/user/" + getName(e) + "/"; let listClose = create( "span", "mackDisplayBoxClose", "✕", listing, "top:0 !important;" ); listClose.onclick = function () { whitelistbtn(listing); listing.remove(); blacklist.filter((item) => item !== e); deleteAllBtn(); userProfileHandler(); }; box.appendChild(listing); } } function addAttribute(b) { let blacklist = getObj("blacklist"); if (b.firstChild.href == username) return; if (blacklist.includes(b.firstChild.href)) { b.setAttribute("data-status", "blacklisted"); } else { b.setAttribute("data-status", "whitelisted"); } } /********* Create a DOMElement *********/ function create(HTMLtag, classes, text, appendLocation, cssText) { let element = document.createElement(HTMLtag); if (Array.isArray(classes)) { element.classList.add(...classes); if (classes.includes("newTab")) { element.setAttribute("target", "_blank"); } } else if (classes) { if (classes[0] === "#") { element.id = classes.substring(1); } else { element.classList.add(classes); if (classes === "newTab") { element.setAttribute("target", "_blank"); } } } if (text || text === 0) { element.innerText = text; } if (appendLocation && appendLocation.appendChild) { appendLocation.appendChild(element); } if (cssText) { element.style.cssText = cssText; } return element; } /********* Create hovering box *********/ function createDisplayBox(cssProperties, windowTitle) { let displayBox = create( "div", "mackDisplayBox", false, document.querySelector("#app") || document.querySelector(".termsFeed") || document.body, cssProperties ); if (windowTitle) { create("span", "mackDisplayBoxTitle", windowTitle, displayBox); } let mousePosition; let offset = [0, 0]; let isDown = false; let isDownResize = false; let displayBoxClose = create( "span", "mackDisplayBoxClose", "✕", displayBox ); displayBoxClose.onclick = function () { displayBox.remove(); }; let resizePearl = create("span", "mackResizePearl", false, displayBox); displayBox.addEventListener( "mousedown", function (e) { if (!["P", "PRE"].includes(e.target.tagName)) { //don't annoy people trying to copy-paste isDown = true; offset = [ displayBox.offsetLeft - e.clientX, displayBox.offsetTop - e.clientY, ]; } }, true ); resizePearl.addEventListener( "mousedown", function (event) { event.stopPropagation(); event.preventDefault(); isDownResize = true; offset = [displayBox.offsetLeft, displayBox.offsetTop]; }, true ); document.addEventListener( "mouseup", function () { isDown = false; isDownResize = false; }, true ); document.addEventListener( "mousemove", function (event) { if (isDownResize) { mousePosition = { x: event.clientX, y: event.clientY, }; displayBox.style.width = mousePosition.x - offset[0] + 5 + "px"; displayBox.style.height = mousePosition.y - offset[1] + 5 + "px"; return; } if (isDown) { mousePosition = { x: event.clientX, y: event.clientY, }; displayBox.style.left = mousePosition.x + offset[0] + "px"; displayBox.style.top = mousePosition.y + offset[1] + "px"; } }, true ); let innerSpace = create("div", "scrollableContent", false, displayBox); return innerSpace; } function getName(link) { if (link === null) return; return link.split("/")[4]; } function whitelistbtn(b) { let blacklist = getObj("blacklist"); var value = String( "https://anilist.co/user/" + b.children[0].innerText + "/" ); var val = b.children[0].innerText; if (blacklist.includes(value)) { blacklist.splice(blacklist.indexOf(value), 1); blacklist = setObj("blacklist", blacklist); //alert(val +' has been whitelisted !'); //console.log(blacklist); } else { //alert(val +' is not blacklisted !'); } } function blacklistbtn(b) { let blacklist = getObj("blacklist"); var value = (value = String( "https://anilist.co/user/" + b.children[0].innerText + "/" )); var val = b.children[0].innerText; if (!blacklist.includes(value)) { blacklist.push(value); setObj("blacklist", blacklist); // alert(val +' has been blacklisted !'); //console.log(blacklist); } else { // alert(val +' is already blacklisted !'); } } function eventFire(el, etype) { if (el.fireEvent) { el.fireEvent("on" + etype); } else { var evObj = document.createEvent("Events"); evObj.initEvent(etype, true, false); el.dispatchEvent(evObj); } } function likeBtnHandler() { let likes = document.querySelectorAll(".button:not(.liked)"); let notBlacklisted = blacklistedarray(likes); //console.log(likes, notBlacklisted); for (let e of notBlacklisted) { eventFire(e, "click"); } } function blacklistedarray(array) { let blacklist = getObj("blacklist"); if (!blacklist.includes(username)) { blacklist.push(username); } let notBlacklisted = new Array(); let isBlacklisted; for (let c of array) { isBlacklisted = false; for (let e of blacklist) { if (c.closest(".wrap").getElementsByClassName("name")[0].href == e) { isBlacklisted = true; break; } } if (isBlacklisted == false) { notBlacklisted.push(c); } } return notBlacklisted; } function profileBtnHandler() { let isAdded = document.querySelector("button.nav-btn.profile-btn"); //console.log([...isAdded].length); if (isAdded !== null) return; window.onload = userProfileHandler(); } const onMutate = function (mutationsList) { if (window.location.href == "https://anilist.co/home") { homePageHandler(); } if ( window.location.href.match( /(^https?:\/\/)?(www\.)?anilist.co\/user\/\w+/gi ) != null ) { profileBtnHandler(); } }; const observer = new MutationObserver(onMutate); observer.observe(document.body, { childList: true, subtree: true }); })();