Greasy Fork is available in English.

YouTube Auto Dislike

Because YouTube no longer displays the number of dislikes, the scripts automatically dislike all videos. Wait 15 seconds to see the effect.

// ==UserScript==
// @name  YouTube Auto Dislike
// @namespace  gqqnbig
// @match  https://www.youtube.com/*
// @grant  none
// @version  1.5
// @author  gqqnbig
// @description  Because YouTube no longer displays the number of dislikes, the scripts automatically dislike all videos. Wait 15 seconds to see the effect.
// @license  GNU General Public License v3.0
// ==/UserScript==


(function () {
    "use strict";

    //from https://github.com/Anarios/return-youtube-dislike/blob/main/Extensions/UserScript/Return%20Youtube%20Dislike.user.js
    const LIKED_STATE = "LIKED_STATE";
    const DISLIKED_STATE = "DISLIKED_STATE";
    const NEUTRAL_STATE = "NEUTRAL_STATE";

    let isShorts = () => location.pathname.startsWith("/shorts");


    function isInViewport(element) {
        const rect = element.getBoundingClientRect();
        const height = innerHeight || document.documentElement.clientHeight;
        const width = innerWidth || document.documentElement.clientWidth;
        return (
            // When short (channel) is ignored, the element (like/dislike AND short itself) is
            // hidden with a 0 DOMRect. In this case, consider it outside of Viewport
            !(rect.top == 0 && rect.left == 0 && rect.bottom == 0 && rect.right == 0) &&
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= height &&
            rect.right <= width
        );
    }

    function getButtons() {
        if (isShorts()) {
            let elements = document.querySelectorAll("#like-button > ytd-like-button-renderer");
            for (let element of elements) {
                if (isInViewport(element)) {
                    return element;
                }
            }
        }
        if (document.getElementById("menu-container")?.offsetParent === null) {
            return (
                document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div") ??
                document.querySelector("ytd-menu-renderer.ytd-video-primary-info-renderer > div")
            );
        } else {
            return document
                .getElementById("menu-container")
                ?.querySelector("#top-level-buttons-computed");
        }
    }

    function getDislikeButton() {
        if (getButtons().children[0].tagName ===
            "YTD-SEGMENTED-LIKE-DISLIKE-BUTTON-RENDERER") {
            if (getButtons().children[0].children[1] === undefined) {
                return document.querySelector("#segmented-dislike-button");
            } else {
                return getButtons().children[0].children[1];
            }
        } else {
            if (getButtons().querySelector("segmented-like-dislike-button-view-model")) {
                const dislikeViewModel = getButtons().querySelector("dislike-button-view-model");
                return dislikeViewModel;
            } else {
                return getButtons().children[1];
            }
        }
    }

    function getLikeButton() {
        return getButtons().children[0].tagName ===
        "YTD-SEGMENTED-LIKE-DISLIKE-BUTTON-RENDERER"
            ? document.querySelector("#segmented-like-button") !== null ? document.querySelector("#segmented-like-button") : getButtons().children[0].children[0]
            : getButtons().querySelector("like-button-view-model") ?? getButtons().children[0];
    }

    function isVideoLiked() {
        return getLikeButton().querySelector('button').getAttribute('aria-pressed') === 'true';
    }

    function isVideoDisliked() {
        return getDislikeButton().querySelector('button').getAttribute('aria-pressed') === 'true';
    }

    function getState() {
        if (isVideoLiked()) {
            return LIKED_STATE;
        }
        if (isVideoDisliked()) {
            return DISLIKED_STATE;
        }
        return NEUTRAL_STATE;
    }


    function isWatchPage() {
        return window.location.pathname.startsWith('/watch');
    }

    const observer = new MutationObserver((mutations) => {
        if (mutations.length > 0 && mutations[0].addedNodes.length > 0 && mutations[0].addedNodes[0].wholeText !== 'YouTube' &&
            isWatchPage()) {
            console.log('start unlike');
            // observer.disconnect(); // Stop observing temporarily

            setTimeout(() => {
                if (getState() === NEUTRAL_STATE) {
                    getDislikeButton().querySelector('button').click();
                }
            }, 15000);

            // observer.observe(head, config);
        }
    });

    // only watch the direct children
    const config = {childList: true};

    let head;
    let getTitleHandle = setInterval(() => {
        head = document.head.querySelector('title');
        if (head) {
            observer.observe(head, config);
            clearInterval(getTitleHandle);
        }
    }, 200);
})();