AIO - Auto-Liker & Auto-Subscriber

Vytvoří tlačítko které po aktivaci automaticky lajkuje komentáře na YouTube

当前为 2025-04-22 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         AIO - Auto-Liker & Auto-Subscriber
// @namespace    AIO - YouTube Tool LeSubs
// @version      2.0
// @description  Vytvoří tlačítko které po aktivaci automaticky lajkuje komentáře na YouTube
// @author       Projekt Darkside - DevIT Brno - EU
// @license      Darkside; MIT;
// @match        https://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        none
// ==/UserScript==

/* eslint-disable */

(function () {
    'use strict';

    let isAutoLiking = false; // Indikátor běžícího auto-lajkování
    let likeStats = { liked: 0, total: 0 }; // Statistika lajků
    let activeTimeouts = []; // Seznam aktivních timeoutů pro zrušení
    let lastUrl = location.href; // Sledování aktuální URL

    let lastLikedCount = 0; // počet aktuálně likovaných
    let lastTotalCount = 0; // počet nalezených k olajkování
    let idleTimer = null; // resetujeme funkce

    // Volby pro aktivaci funkcí
    let NOTIF_GIF = false;  // Pokud je true, bude se spouštět GIF notifikace
    let NOTIF_SVG = true; // Pokud je true, bude se spouštět SVG zvoneček
    let DEBUG_MODE = false; // Pokud je true, bude se simulovat stisk každých 10 vteřin

    // Konstanty pro GIF URL a text notifikace
    const GIF_URL = 'https://cdn3.emoji.gg/emojis/4381-anouncements-animated.gif'; // URL pro GIF
    const NOTIF_TEXT = 'Toto je notifikace s GIF!'; // Text pro notifikaci u GIFu

    // Jazykové varianty tlačítka "Líbí se mi"
    const Wlang = [
        // líbí se komentář
        "Mark this comment as liked",
        "Označit tento komentář jako Líbí se mi",         // Angličtina
        "Označiť tento komentár ako Páči sa mi",          // Čeština
        "Marquer ce commentaire comme aimé",              // Slovenština
        "Marcar este comentario como Me gusta",           // Francouzština
        "Diesen Kommentar als Gefällt mir markieren",     // Španělština
        "Contrassegna questo commento come Mi piace",     // Němčina
        "Marcar este comentário como Gostei",             // Portugalština
        "Отметить этот комментарий как понравившийся",    // Ruština
        "このコメントを高評価としてマーク",                    // Japonština

        // Líbí se odpověď na komentář
        "Mark this answer as liked",                      // Angličtina
        "Označit tuto odpověď jako Líbí se mi",           // Čeština
        "Označiť túto odpoveď ako Páči sa mi",            // Slovenština
        "Marquer cette réponse comme aimée",              // Francouzština
        "Marcar esta respuesta como Me gusta",            // Španělština
        "Diese Antwort als Gefällt mir markieren",        // Němčina
        "Contrassegna questa risposta come Mi piace",     // Italština
        "Marcar esta resposta como Gostei",               // Portugalština
        "Отметить этот ответ как понравившийся",          // Ruština
        "この回答を高評価としてマーク",                       // Japonština
    ];

    // Překlady pro statistiky "Olajkováno"
    const likedTranslations = {
        'en': 'Liked',
        'cs': 'Olajkováno',
        'sk': 'Olajkované',
        'fr': 'Aimé',
        'es': 'Gustado',
        'de': 'Gemocht',
        'it': 'Apprezzato',
        'pt': 'Curtido',
        'ru': 'Понравилось',
        'ja': '高評価済み'
    };

    // Detekce jazyka (kompatibilní se všemi hlavními prohlížeči)
    function getLikedTranslation() {
        const lang = (navigator.languages && navigator.languages[0]) || navigator.language || 'en';
        const shortLang = lang.slice(0, 2);

        console.log(`Detected language: ${lang} (short: ${shortLang})`);

        return likedTranslations[shortLang] || likedTranslations['en'];
    }

    // Resetuje statistiky a zastaví všechny timeouty */
    function resetStats() {
        activeTimeouts.forEach(clearTimeout);
        activeTimeouts = [];
        likeStats = { liked: 0, total: 0 };
        //updateLikeStatus();
        console.log('🔄 Statistika byla resetována a všechny timeouty zastaveny.');
    }

    // Sleduje změnu URL a resetuje stav */
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            isAutoLiking = false;
            console.log('⏹️ Auto-liking byl zastaven kvůli změně URL.');
            resetStats();
        }
    }).observe(document, { subtree: true, childList: true });

    // Vytváří tlačítko pro spuštění auto-lajkování a zobrazení statistik */
    // Vytváří tlačítko pro spuštění auto-lajkování a zobrazení statistik */
    function createButton() {
        const container = document.querySelector('#info #top-row') || document.querySelector('.item.style-scope.ytd-watch-metadata');
        if (container && !document.querySelector('#auto-like-btn')) {
            const button = document.createElement('button');
            button.id = 'auto-like-btn';
            button.classList.add('auto-like-btn');
            button.title = 'Spustit olajkování načtených komentářů.';
            button.innerText = 'Auto-Like 👍';
            button.onclick = () => {
                startAutoLike();
            };
            container.appendChild(button);

            const status = document.createElement('div');
            status.id = 'like-status';
            status.classList.add('like-status', 'loading'); // Přidáme třídu 'loading' pro gif
            // status.innerHTML = `<strong>0/0</strong> &nbsp; ${getLikedTranslation()}`;
            status.innerHTML = ``;
            status.title = 'Odebírat !všechna! videa tohoto kanálu.';
            status.onclick = () => {
                startNotificationSystem();
                autoSubscribe()
            };
            container.appendChild(status);

            console.log('✅ Tlačítko Auto-Like a statistika byly přidány.');
        }
    }

    // Přidává vlastní styly pro tlačítko a stavové pole */
    function addCustomStyles() {
        const style = document.createElement('style');
        style.innerHTML = `
    .auto-like-btn {
        margin-left: 10px !important;
        background-image: url('https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExMnloN3Q5Mjh1b2Z0MmlrMTltZGo4MWJ0aGh3cHZ1YTdiMmJoMTJiciZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/26xBRt3iLuAesGzQI/giphy.gif') !important;
        background-size: cover;
        background-position: center;
        color: #fff !important;
        border: none !important;
        border-radius: 18px !important;
        cursor: pointer !important;
        font-size: 14px !important;
        transition: background-color 0.3s ease !important;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2) !important;
        text-align: center !important;
        display: inline-flex !important;
        justify-content: center !important;
        align-items: center !important;
        font-weight: bold !important;
        box-sizing: border-box !important;
        min-width: 130px !important;
        min-height: 36px !important;
    }
    .auto-like-btn:hover {
        background-color: #cc0000 !important;
        border: solid white 2px !important;
    }

    .like-status {
        background-size: cover;
        background-position: center;
        display: inline-flex !important;
        justify-content: center !important;
        align-items: center !important;
        margin-left: 10px !important;
        background: #f1f1f1;
        border-radius: 18px !important;
        font-size: 14px !important;
        color: #333 !important;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1) !important;
        font-weight: bold !important;
        text-align: center !important;
        box-sizing: border-box !important;
        user-select: none !important;
        /*cursor: not-allowed !important;*/
        cursor: pointer !important;
        min-width: 130px !important;
        min-height: 36px !important;
        position: relative !important;
        overflow: hidden !important;
    }
    .like-status:hover {
        border: solid white 2px !important;
    }

    /* GIF pozadí při načtení */
    .like-status.loading {
        background-image: url('https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExZzhxZmtmdTNzbWh5Z3NjejRqemdpZXJyMzZrdXJjZGluNWpjbXIzYiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/byMmCtRgmb6XpQ6sod/giphy.gif') !important;
        background-size: cover !important;
        background-position: center !important;
    }
    `;
        document.head.appendChild(style);
    }

    ////////////////////////////////////

    // Funkce pro vytvoření notifikace s GIF a textem */
    function generateRandomGifAlert(gifUrl, message) {
        const notificationBox = document.createElement('div');
        notificationBox.style.position = 'fixed';
        notificationBox.style.left = '20px';
        notificationBox.style.bottom = '20px';
        notificationBox.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
        notificationBox.style.color = 'white';
        notificationBox.style.borderRadius = '10px';
        notificationBox.style.padding = '10px';
        notificationBox.style.display = 'flex';
        notificationBox.style.alignItems = 'center';
        notificationBox.style.zIndex = '9999';
        notificationBox.style.transition = 'all 0.3s ease-in-out';

        // Vloží GIF
        const gifImage = document.createElement('img');
        gifImage.src = gifUrl;
        gifImage.style.width = '50px';
        gifImage.style.height = '50px';
        gifImage.style.marginRight = '10px';

        // Vloží text
        const alertText = document.createElement('span');
        alertText.innerText = message;

        // Přidá GIF a text do notifikace
        notificationBox.appendChild(gifImage);
        notificationBox.appendChild(alertText);

        // Přidá notifikaci na stránku
        document.body.appendChild(notificationBox);

        // Po 3 sekundách notifikaci skryje
        setTimeout(() => {
            notificationBox.style.opacity = '0';
            setTimeout(() => {
                document.body.removeChild(notificationBox);
            }, 300); // Počkáme, až animace skončí
        }, 3000);
    }

    // Funkce pro vytvoření zvonečku s textem "SUBSCRIBED" */
    function generateRandomBellSubscription() {
        const bellSVG = `
    <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 24 24">
        <path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6V9c0-3.31-2.69-6-6-6S6 5.69 6 9v7l-1 1v1h14v-1l-1-1zm-2-1H8v-7c0-2.21 1.79-4 4-4s4 1.79 4 4v7z"/>
    </svg>
`;

        const bellNotification = document.createElement('div');
        bellNotification.style.position = 'fixed';
        bellNotification.style.left = '20px';
        bellNotification.style.bottom = '20px';
        bellNotification.style.backgroundColor = '#e63946'; // Červená barva pro menu
        bellNotification.style.color = 'white';
        bellNotification.style.borderRadius = '10px';
        bellNotification.style.padding = '10px 20px';
        bellNotification.style.display = 'flex';
        bellNotification.style.alignItems = 'center';
        bellNotification.style.justifyContent = 'space-between';
        bellNotification.style.zIndex = '9999';
        bellNotification.style.transition = 'all 0.3s ease-in-out';

        // Vloží SVG zvoneček
        const bellContainer = document.createElement('div');
        bellContainer.innerHTML = bellSVG;
        bellContainer.style.display = 'flex';
        bellContainer.style.alignItems = 'center';

        // Vloží text "SUBSCRIBED"
        const subscriptionText = document.createElement('span');
        subscriptionText.innerText = 'SUBSCRIBED';
        subscriptionText.style.fontWeight = 'bold';
        subscriptionText.style.fontSize = '20px';

        // Přidá SVG zvoneček a text do notifikace
        bellNotification.appendChild(bellContainer);
        bellNotification.appendChild(subscriptionText);

        // Přidá notifikaci na stránku
        document.body.appendChild(bellNotification);

        // Po 3 sekundách notifikaci skryje
        setTimeout(() => {
            bellNotification.style.opacity = '0';
            setTimeout(() => {
                document.body.removeChild(bellNotification);
            }, 300); // Počkáme, až animace skončí
        }, 3000);
    }

    // Funkce pro spuštění notifikace podle volby true/false */
    function startNotificationSystem() {
        if (NOTIF_GIF) {
            generateRandomGifAlert(GIF_URL, NOTIF_TEXT); // Použije hodnoty z konstant
        }

        if (NOTIF_SVG) {
            generateRandomBellSubscription();
        }
    }

    // Funkce čeká na prvek v DOM s daným selektorem (max. timeout sekund)
    function waitForElement(selector, timeout = 5000) {
        return new Promise((resolve, reject) => {
            const startTime = Date.now();

            function check() {
                const element = document.querySelector(selector);
                if (element) {
                    resolve(element);
                } else if (Date.now() - startTime > timeout) {
                    reject(new Error(`Prvek '${selector}' nebyl nalezen v časovém limitu.`));
                } else {
                    requestAnimationFrame(check);
                }
            }

            check();
        });
    }


    // .yt-spec-button-shape-next.yt-spec-button-shape-next--tonal.yt-spec-button-shape-next--mono.yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-leading-trailing
    // Funkce pro automatické přihlášení odběru kanálu
    function autoSubscribe() {
        waitForElement('ytd-subscribe-button-renderer button')
            .then(subButton => {
                console.log("✅ Tlačítko pro odběr nalezeno:", subButton.innerText);
                subButton.click(); // Klikne na tlačítko "Odebírat" nebo "Odebíráno"

                setTimeout(() => {
                    // Otevře menu kliknutím na tlačítko s danou třídou
                    waitForElement('.yt-spec-button-shape-next.yt-spec-button-shape-next--tonal.yt-spec-button-shape-next--mono.yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-leading-trailing')
                        .then(menuButton => {
                            console.log("✅ Tlačítko pro otevření menu nalezeno, klikám...");
                            menuButton.click();

                            setTimeout(() => {
                                // Jazykové varianty pro "Vše"
                                const allLabels = [
                                    "All",        // Angličtina
                                    "Vše",        // Čeština
                                    "Všetko",     // Slovenština
                                    "Tout",       // Francouzština
                                    "Todo",       // Španělština
                                    "Alle",       // Němčina
                                    "Tutto",      // Italština
                                    "Tudo",       // Portugalština
                                    "Все",        // Ruština
                                    "すべて"        // Japonština
                                ];

                                // Čeká na zobrazení menu s možnostmi odběru
                                waitForElement('yt-formatted-string.style-scope.ytd-menu-service-item-renderer')
                                    .then(() => {
                                        // Najde první položku v menu odpovídající jakékoli jazykové variantě "Vše"
                                        let menuOption = Array.from(document.querySelectorAll('yt-formatted-string.style-scope.ytd-menu-service-item-renderer'))
                                            .find(el => allLabels.some(label => el.innerText.trim() === label));

                                        if (menuOption) {
                                            console.log("✅ Položka 'Odebírat Vše' nalezena, klikám...");
                                            menuOption.click();
                                        } else {
                                            console.log("⚠️ Položka 'Odebírat Vše' nebyla nalezena.");
                                        }
                                    })
                                    .catch(() => console.log("❌ Nepodařilo se najít položku menu."));
                            }, 500); // Počkám na otevření menu
                        })
                        .catch(() => console.log("❌ Tlačítko pro otevření menu nenalezeno."));
                }, 500); // Počkám na otevření menu tlačítka
            })
            .catch(() => console.log("❌ Tlačítko pro odběr nenalezeno."));
    }

    // MutationObserver sleduje změny v DOM a spustí funkci autoSubscribe, když se objeví tlačítko
    const observer = new MutationObserver(() => {
        if (document.querySelector('ytd-subscribe-button-renderer button')) {
            observer.disconnect(); // Odpojíme, aby se funkce nespouštěla vícekrát
            // autoSubscribe();
        }
    });

    // Spustíme sledování změn v celém dokumentu
    observer.observe(document.body, { childList: true, subtree: true });



    // Pokud je DEBUG_MODE aktivní, simuluj stisknutí každých 10 vteřin
    if (DEBUG_MODE) {
        setInterval(() => {
            console.log('⚠️ DEBUG: Simulace stisknutí notifikace...');
            startNotificationSystem(); // Spustí notifikace podle aktuálního nastavení
        }, 10000); // Každých 10 vteřin
    }

    ////////////////////////////////////

    // Funkce, která spustí auto-like a změní styl statusu */
    function startAutoLike() {
        const statusElement = document.getElementById('like-status');
        if (statusElement) {
            statusElement.classList.remove('loading'); // Odebere GIF pozadí
        }

        // Spuštění hlavní funkce lajkování
        autoLikeThumbsUp();
    }

    // Aktualizuje vizuální zobrazení počtu lajků */
    function updateLikeStatus() {
        const statusElement = document.getElementById('like-status');
        if (statusElement) {
            statusElement.innerHTML = `<strong>${likeStats.liked}/${likeStats.total}</strong>&nbsp; ${getLikedTranslation()}`;

            //  Změní border na červený páč to jinak moc nejde :)
            document.querySelectorAll(".like-status").forEach(el => {
                el.addEventListener("mouseenter", () => {
                    el.style.setProperty("border", "solid red 2px", "important");
                });

                el.addEventListener("mouseleave", () => {
                    el.style.removeProperty("border"); // Vrátí border do původního stavu
                });
            });

            // Pokud se čísla změnila, restartuj časovač
            if (likeStats.liked !== lastLikedCount || likeStats.total !== lastTotalCount) {
                lastLikedCount = likeStats.liked;
                lastTotalCount = likeStats.total;
                resetIdleTimer();
            }
        }
    }

    // Restartuje časovač, který po 3 sekundách obnoví animaci a resetuje text */
    function resetIdleTimer() {
        clearTimeout(idleTimer); // Zastaví předchozí časovač
        idleTimer = setTimeout(() => {
            const statusElement = document.getElementById('like-status');
            if (statusElement) {
                statusElement.classList.add('loading'); // Po nečinnosti přidá GIF zpět
                // statusElement.innerHTML = `<strong>0/0</strong> &nbsp; ${getLikedTranslation()}`; // Resetuje text
                statusElement.innerHTML = ``;

                //  Změní border na červený páč to jinak moc nejde :)
                document.querySelectorAll(".like-status").forEach(el => {
                    el.addEventListener("mouseenter", () => {
                        el.style.setProperty("border", "solid white 2px", "important");
                    });

                    el.addEventListener("mouseleave", () => {
                        el.style.removeProperty("border"); // Vrátí border do původního stavu
                    });
                });
            }
            console.log('✅ Restartuji časovač');
        }, 3000); // 3 sekundy
    }

    // Hlavní funkce pro automatické lajkování komentářů */
    function autoLikeThumbsUp() {
        if (isAutoLiking) return;
        isAutoLiking = true;
        likeStats = { liked: 0, total: 0 };
        updateLikeStatus();

        const selector = Wlang.map(phrase => `button[aria-label^="${phrase}"]`).join(', ');
        const buttons = document.querySelectorAll(selector);
        likeStats.total = buttons.length;
        updateLikeStatus();

        // pokud tlačítko neexistuje
        if (buttons.length === 0) {
            console.warn('⚠️ Žádná tlačítka "Líbí se mi" nebyla nalezena.');
            isAutoLiking = false;
            return;
        }

        console.log(`🔹 Nalezeno ${buttons.length} komentářů k lajknutí.`);
        buttons.forEach((button, index) => {
            const timeoutId = setTimeout(() => {
                if (!button.classList.contains('style-default-active')) {
                    button.click();
                    likeStats.liked++;
                    updateLikeStatus();
                    console.log(`👍 Lajknut komentář #${index + 1}`);
                }
                if (index === buttons.length - 1) isAutoLiking = false;
            }, getRandomDelay(index));
            activeTimeouts.push(timeoutId);
        });
    }

    // Generuje náhodné zpoždění mezi lajky (v milisekundách) */
    function getRandomDelay(index) {
        const minDelay = 300;
        const maxDelay = 500;
        return minDelay + (Math.random() * (maxDelay - minDelay)) + (index * 500);
    }

    // Sleduje změny v DOM pro vykreslení tlačítka */
    function observeDOM() {
        const observer = new MutationObserver(() => {
            createButton();
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    // Spuštění skriptu
    observeDOM();
    addCustomStyles();
    getLikedTranslation();
    updateLikeStatus();
})();