// ==UserScript==
// @name YouTube Downloader & Thumbnail Hider & Shorts Remover
// @namespace http://tampermonkey.net/
// @version 2025-04-15.1
// @description Hide video thumbnails on YouTube and remove Shorts sections with configurable options download Videos or mp3.
// @description:de Blende Video-Thumbnails auf YouTube aus und entferne Shorts-Bereiche mit konfigurierbaren Optionen.
// @description:es Oculta miniaturas de video en YouTube y elimina secciones de Shorts con opciones configurables.
// @description:fr Masquer les miniatures de vidéos sur YouTube et supprimer les sections Shorts avec des options configurables.
// @author Copiis
// @match https://www.youtube.com/feed/subscriptions
// @match https://www.youtube.com/watch?v=*
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @license MIT
// @icon https://www.youtube.com/favicon.ico
// ==/UserScript==
(function() {
'use strict';
const LANGUAGES = {
en: {
'settingsUpdated': 'Settings updated. Refresh the page to apply changes.',
'show': 'visible',
'hide': 'hidden',
'language': 'Select Language',
'showShorts': 'Show Shorts',
'hideShorts': 'Hide Shorts'
},
de: {
'settingsUpdated': 'Einstellungen aktualisiert. Seite neu laden, um Änderungen anzuwenden.',
'show': 'sichtbar',
'hide': 'versteckt',
'language': 'Sprache wählen',
'showShorts': 'Shorts einblenden',
'hideShorts': 'Shorts ausblenden'
},
es: {
'settingsUpdated': 'Configuración actualizada. Recarga la página para aplicar los cambios.',
'show': 'visibles',
'hide': 'ocultos',
'language': 'Seleccionar idioma',
'showShorts': 'Mostrar Shorts',
'hideShorts': 'Ocultar Shorts'
},
fr: {
'settingsUpdated': 'Paramètres mis à jour. Rafraîchissez la page pour appliquer les changements.',
'show': 'visibles',
'hide': 'cachés',
'language': 'Sélectionner la langue',
'showShorts': 'Afficher les Shorts',
'hideShorts': 'Masquer les Shorts'
}
};
let settings = JSON.parse(localStorage.getItem('ytHiderSettings') || '{"hideShorts": true, "language": "auto"}');
let userLang = settings.language === 'auto' ? (navigator.language.split('-')[0] || 'en') : settings.language;
if (!LANGUAGES[userLang]) userLang = 'en';
function registerShortsMenu() {
GM_registerMenuCommand(LANGUAGES[userLang].hideShorts, () => {
settings.hideShorts = true;
localStorage.setItem('ytHiderSettings', JSON.stringify(settings));
manageShortsVisibility();
});
GM_registerMenuCommand(LANGUAGES[userLang].showShorts, () => {
settings.hideShorts = false;
localStorage.setItem('ytHiderSettings', JSON.stringify(settings));
manageShortsVisibility();
});
}
registerShortsMenu();
GM_registerMenuCommand(LANGUAGES[userLang].language, selectLanguage);
const observer = new MutationObserver(addIcons);
const targetNode = document.querySelector('#contents') || document.body;
observer.observe(targetNode, { childList: true, subtree: true });
const hiddenVideos = JSON.parse(localStorage.getItem('hiddenVideos') || '{}');
function addIcons() {
const isSubscriptionPage = window.location.pathname === '/feed/subscriptions';
const isVideoPage = window.location.pathname.startsWith('/watch');
if (isSubscriptionPage) {
document.querySelectorAll('ytd-video-renderer, ytd-rich-item-renderer, ytd-grid-video-renderer').forEach(item => {
// Finde das Thumbnail-Element, um die Video-ID zu extrahieren
const thumbnailLink = item.querySelector('a#thumbnail') ||
item.querySelector('a[href*="/watch?v="]') ||
item.querySelector('ytd-thumbnail a');
if (!thumbnailLink) return;
// Extrahiere die Video-ID aus dem href
const videoIdMatch = thumbnailLink.href?.match(/v=([^&]+)/);
const videoId = videoIdMatch ? videoIdMatch[1] : null;
if (!videoId) return;
// Verstecke das Video, wenn es in hiddenVideos gespeichert ist
if (hiddenVideos[videoId]) {
item.style.display = 'none';
return;
}
// Finde den avatar-container, um den Button darunter zu platzieren
const avatarContainer = item.querySelector('#avatar-container');
if (!avatarContainer) return;
// Prüfe, ob der Button bereits existiert
if (avatarContainer.parentElement.querySelector('.eye-icon')) return;
// Erstelle den Verstecken-Button
const eye = document.createElement('div');
eye.textContent = '📛';
eye.classList.add('eye-icon');
eye.style.display = 'block'; // Sorgt dafür, dass der Button eine neue Zeile einnimmt
eye.style.marginTop = '4px'; // Abstand zum Avatar
eye.style.float = 'left'; // Positioniert den Button links neben den Metadaten
eye.style.fontSize = '24px';
eye.style.cursor = 'pointer';
eye.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
eye.style.borderRadius = '50%';
eye.style.padding = '2px';
eye.style.lineHeight = '24px'; // Zentriert das Emoji vertikal
eye.dataset.persistent = 'true';
eye.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
triggerHideVideo(item);
});
// Füge den Button direkt nach dem avatar-container ein
avatarContainer.parentElement.insertBefore(eye, avatarContainer.nextSibling);
});
}
if (isVideoPage) {
const titleElement = document.querySelector('h1.style-scope.ytd-watch-metadata');
if (!titleElement || document.querySelector('.download-icon')) return;
const videoId = new URLSearchParams(window.location.search).get('v');
if (!videoId) return;
const downloadIcon = document.createElement('div');
downloadIcon.textContent = '💾';
downloadIcon.classList.add('download-icon');
downloadIcon.style.display = 'inline-block';
downloadIcon.style.marginLeft = '8px';
downloadIcon.style.fontSize = '24px';
downloadIcon.style.cursor = 'pointer';
downloadIcon.style.verticalAlign = 'middle';
downloadIcon.dataset.persistent = 'true';
downloadIcon.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
triggerDownload(videoId);
});
titleElement.appendChild(downloadIcon);
}
document.querySelectorAll('.eye-icon, .download-icon').forEach(icon => {
if (!icon.dataset.persistent) {
icon.remove();
}
});
if (isSubscriptionPage) manageShortsVisibility();
}
function triggerHideVideo(item) {
const menuIcon = item.querySelector('ytd-menu-renderer .yt-icon-shape');
if (!menuIcon) return;
menuIcon.click();
setTimeout(() => {
const popup = document.querySelector('ytd-menu-popup-renderer');
if (popup) {
const hideItem = Array.from(popup.querySelectorAll('ytd-menu-service-item-renderer'))
.find(item => item.querySelector('yt-formatted-string')?.textContent.trim() === 'Ausblenden');
if (hideItem) {
hideItem.click();
} else {
const thumbnailLink = item.querySelector('a#thumbnail') ||
item.querySelector('a[href*="/watch?v="]');
const videoIdMatch = thumbnailLink?.href?.match(/v=([^&]+)/);
const videoId = videoIdMatch ? videoIdMatch[1] : null;
if (videoId) {
hiddenVideos[videoId] = true;
localStorage.setItem('hiddenVideos', JSON.stringify(hiddenVideos));
item.style.display = 'none';
}
}
}
}, 150);
}
function triggerDownload(videoId) {
const currentUrl = window.location.href;
const newUrl = currentUrl.replace('www.youtube.com', 'www.ssyoutube.com');
window.location.href = newUrl;
}
function manageShortsVisibility() {
const shortsTitles = ['Shorts', 'Kurzvideos', 'Clips', 'Short Videos', 'Reels'];
document.querySelectorAll('ytd-reel-shelf-renderer, ytd-rich-shelf-renderer, ytd-rich-section-renderer').forEach(section => {
const titleElement = section.querySelector('#title, h2, [title]');
const hasShortsTitle = titleElement && shortsTitles.some(title =>
titleElement.textContent?.trim().toLowerCase().includes(title.toLowerCase()) ||
titleElement.getAttribute('title')?.toLowerCase().includes(title.toLowerCase())
);
const hasShortsContent = section.querySelector('ytm-shorts-lockup-view-model') ||
section.querySelector('a[href*="/shorts/"]') ||
section.querySelector('[reel-shelf-items]');
if (hasShortsTitle || hasShortsContent) {
section.style.display = settings.hideShorts ? 'none' : 'block';
}
});
}
function selectLanguage() {
const langChoice = prompt(LANGUAGES[userLang].language + '\n\n' + Object.keys(LANGUAGES).join(', ').toUpperCase(), userLang.toUpperCase());
if (langChoice && LANGUAGES[langChoice.toLowerCase()]) {
settings.language = langChoice.toLowerCase();
localStorage.setItem('ytHiderSettings', JSON.stringify(settings));
userLang = settings.language;
alert(LANGUAGES[userLang].settingsUpdated);
registerShortsMenu();
} else {
alert('Invalid language choice.');
}
}
addIcons();
})();