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