YouTube Downloader & Thumbnail Hider & Shorts Remover

Hide video thumbnails on YouTube and remove Shorts sections with configurable options download Videos or mp3.

安装此脚本?
作者推荐脚本

您可能也喜欢Twitter/X Timeline Sync

安装此脚本
// ==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();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址