您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hides all videos except those with Russian characters in the title, and also hides all Shorts content. Remembers toggle state. Updated for current YouTube layout.
// ==UserScript== // @name YouTube Russian Language and Shorts Filter (DEBUG) // @namespace http://tampermonkey.net/ // @version 7.3-debug // @description Hides all videos except those with Russian characters in the title, and also hides all Shorts content. Remembers toggle state. Updated for current YouTube layout. // @description:ru Скрывает все видео, кроме тех, в названии которых есть русские буквы, а также скрывает весь контент Shorts. Запоминает состояние кнопки. Обновлено для актуальной верстки YouTube. // @author torch // @match https://www.youtube.com/* // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com // @license MIT // ==/UserScript== (function() { 'use strict'; // --- НАСТРОЙКИ --- const DEBUG = true; // Включаем режим отладки. Все шаги будут выводиться в консоль (F12). const TRAIN_ALGORITHM = false; let isScriptEnabled = GM_getValue('isRussianFilterEnabled', true); const russianRegex = /[а-яА-ЯёЁ]/; let runCount = 0; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function clickNotInterested(videoElement, titleText) { if (!TRAIN_ALGORITHM) return; try { const menuButton = videoElement.querySelector('#menu button[aria-label="Ещё"], #menu button[aria-label="Action menu"]'); if (!menuButton) { if (DEBUG) console.log(`[YT Filter DEBUG] Кнопка меню "..." не найдена для видео: "${titleText}"`); return; } menuButton.click(); await sleep(250); const menuItems = document.querySelectorAll('ytd-menu-service-item-renderer, yt-list-item-view-model'); let found = false; for (const item of menuItems) { if (item.offsetParent === null) continue; const textElement = item.querySelector('yt-formatted-string, .yt-core-attributed-string'); if (textElement && (textElement.textContent.trim() === 'Не интересует' || textElement.textContent.trim() === 'Not interested')) { item.click(); console.log(`[Фильтр] Нажата кнопка "Не интересует" для: "${titleText}"`); found = true; break; } } if (!found) document.body.click(); } catch (error) { console.error(`[Фильтр] Ошибка при нажатии "Не интересует" для "${titleText}":`, error); document.body.click(); } } /** * Обрабатывает отдельный видеоэлемент, скрывая его, если заголовок не на русском языке. * @param {HTMLElement} videoElement - Элемент видео для обработки. */ function processVideo(videoElement) { if (videoElement.getAttribute('data-processed-russian-filter') === 'true' || !isScriptEnabled) { return; } videoElement.setAttribute('data-processed-russian-filter', 'true'); if (DEBUG) { console.log('[YT Filter DEBUG] Обработка видео:', videoElement); videoElement.style.outline = '2px solid yellow'; } // *** ИСПРАВЛЕНИЕ: Новый, более надежный селектор для заголовка *** const titleSelector = 'a#video-title, .yt-lockup-metadata-view-model__title, #video-title-link, #meta h3.ytd-playlist-panel-video-renderer'; const titleElement = videoElement.querySelector(titleSelector); if (!titleElement) { if (DEBUG) console.log(`%c[YT Filter DEBUG] Элемент заголовка НЕ НАЙДЕН по селектору: "${titleSelector}" в элементе:`, 'color: red;', videoElement); return; } const titleText = (titleElement.getAttribute('title') || titleElement.textContent || '').trim(); if (DEBUG) console.log(`[YT Filter DEBUG] Найден заголовок: "${titleText}"`); if (!titleText) { if (DEBUG) console.log('[YT Filter DEBUG] Заголовок пустой. Пропуск.'); return; } const hasRussianChars = russianRegex.test(titleText); if (DEBUG) console.log(`[YT Filter DEBUG] Русские символы найдены: ${hasRussianChars}`); if (hasRussianChars) { console.log(`[Фильтр] ОСТАВЛЕНО: "${titleText}"`); videoElement.style.outline = '2px solid limegreen'; } else { console.log(`[Фильтр] СКРЫТО: "${titleText}"`); videoElement.style.display = 'none'; clickNotInterested(videoElement, titleText); } } function hideShortsContent() { if (!isScriptEnabled) return; if (DEBUG) console.log('[YT Filter DEBUG] Запуск функции hideShortsContent...'); document.querySelectorAll('ytd-rich-shelf-renderer[is-shorts], ytd-reel-shelf-renderer').forEach(shelf => { if (shelf.style.display !== 'none') { console.log('[Фильтр] Скрыта полка Shorts'); shelf.style.display = 'none'; shelf.setAttribute('data-processed-shorts-filter', 'true'); } }); document.querySelectorAll('ytd-mini-guide-entry-renderer[aria-label="Shorts"], ytd-guide-entry-renderer[title="Shorts"]').forEach(navItem => { if (navItem.style.display !== 'none') { console.log('[Фильтр] Скрыт пункт навигации "Shorts"'); navItem.style.display = 'none'; navItem.setAttribute('data-processed-shorts-filter', 'true'); } }); if (window.location.pathname.startsWith('/shorts/')) { const shortsPlayer = document.querySelector('#page-manager > ytd-shorts'); if (shortsPlayer && shortsPlayer.style.display !== 'none') { console.log('[Фильтр] Скрыт плеер Shorts'); shortsPlayer.style.display = 'none'; shortsPlayer.setAttribute('data-processed-shorts-filter', 'true'); } } } function runFilter() { if (!isScriptEnabled) return; runCount++; if (DEBUG) console.log(`%c[YT Filter DEBUG] Запуск фильтра #${runCount}`, 'color: cyan; font-weight: bold;'); hideShortsContent(); const videoSelectors = 'ytd-rich-item-renderer, ytd-video-renderer, ytd-grid-video-renderer, ytd-compact-video-renderer, ytd-playlist-panel-video-renderer'; const videos = document.querySelectorAll(videoSelectors); if (DEBUG) console.log(`[YT Filter DEBUG] Найдено ${videos.length} потенциальных видео-элементов по селектору: "${videoSelectors}".`); videos.forEach(processVideo); } const observer = new MutationObserver(runFilter); // --- UI --- function createToggleButton() { let button = document.getElementById('russian-filter-toggle'); if (button) { updateButtonState(button); return; } button = document.createElement('button'); button.id = 'russian-filter-toggle'; document.body.appendChild(button); button.addEventListener('click', () => { isScriptEnabled = !isScriptEnabled; GM_setValue('isRussianFilterEnabled', isScriptEnabled); updateButtonState(button); if (isScriptEnabled) { console.log('[Фильтр] Фильтр ВКЛЮЧЕН.'); runFilter(); } else { console.log('[Фильтр] Фильтр ВЫКЛЮЧЕН. Восстановление всех элементов.'); document.querySelectorAll('[data-processed-russian-filter], [data-processed-shorts-filter]').forEach(el => { el.style.display = ''; el.style.outline = ''; }); } }); updateButtonState(button); } function updateButtonState(button) { button.textContent = isScriptEnabled ? 'Фильтр: ВКЛ' : 'Фильтр: ВЫКЛ'; button.className = isScriptEnabled ? 'enabled' : 'disabled'; } GM_addStyle(` #russian-filter-toggle { position: fixed; bottom: 20px; left: 20px; z-index: 99999; padding: 10px 15px; border-radius: 8px; border: none; color: white; font-size: 14px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 8px rgba(0,0,0,0.2); transition: background-color 0.3s, transform 0.2s; } #russian-filter-toggle.enabled { background-color: #1a73e8; } #russian-filter-toggle.disabled { background-color: #d93025; } #russian-filter-toggle:hover { transform: scale(1.05); } `); // --- ЗАПУСК --- function startObserver() { if (DEBUG) console.log('[YT Filter DEBUG] Попытка запуска observer...'); const targetNode = document.querySelector('ytd-app'); if (targetNode) { console.log('[Фильтр] Скрипт запущен. Observer активирован.'); observer.observe(targetNode, { childList: true, subtree: true }); createToggleButton(); if (isScriptEnabled) { if (DEBUG) console.log('[YT Filter DEBUG] Первоначальный запуск через 1.5 сек.'); setTimeout(runFilter, 1500); } } else { if (DEBUG) console.log('[YT Filter DEBUG] ytd-app не найден. Повторная попытка через 500мс.'); setTimeout(startObserver, 500); } } startObserver(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址