AnilistLiker

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

// ==UserScript==
// @name         AnilistLiker
// @namespace    https://github.com/Makhloufbel/AnilistLiker
// @homepage     https://github.com/Makhloufbel
// @version      0.3.9a
// @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

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

.mmd2.btnbottom[disabled] {
  border: 1px solid #999;
  background-color: darkgrey;
  color: #fff;
  cursor: not-allowed;
}

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

.el-message.el-message--error {
  display: none !important;
}
	`,
    ];
    /*********** 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', '<style>' + css + '</style>');

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

    }


    let isAlerted = false;
    function countdownHandler(){
        const Alerted = document.querySelectorAll('.el-message.el-message--error')
        if(Alerted.length == 0){
            isAlerted = false;
            return;
        }
        isAlerted = true;
        console.log("please wait 1 min!");

        const countDownDate = (new Date().getTime())+60*1000;
        const count = document.querySelector(".btn.btn-primary.mmd2.btnbottom");
        count.disabled = true;
        const Int = setInterval(function() {

            let now = new Date().getTime();
            let distance = countDownDate - now;

            let seconds = Math.floor((distance % (1000 * 60)) / 1000);
            if(seconds>9){
                count.innerHTML = "wait 00 : " + seconds ;
            }else{
                count.innerHTML = "wait 00 : 0" + seconds ;
            }
            if (distance < 0) {
                clearInterval(Int);
                count.innerHTML = "Like all posts";
                count.disabled = false;
                isAlerted = false;
            }
        }, 1000);


    }

    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() }
        if( !isAlerted ) {countdownHandler()}

    };
    const observer = new MutationObserver(onMutate);
    observer.observe(document.body, { childList: true, subtree: true })
})();