Back to Deck
УСТАНОВИТЬ
[userscript]
YouTube Quick Not Interested
ИСХОДНИК YouTube
ВЕРСИЯ 2.0
АВТОР Cododel
Target Match:
- https://www.youtube.com/
- https://www.youtube.com/?*
Убирает трение при обучении алгоритмов YouTube. Этот скрипт добавляет кнопку в один клик для моментального удаления нежелательного контента из ленты.
Возможности
- Только главная: Работает исключительно на главной странице YouTube
- Действие в один клик: Мгновенно помечает контент как “Не интересует”
- Мультиязычность: Использует определение SVG path, работает на любом языке
- Умное обнаружение: Автоматически находит кнопки меню через MutationObserver
- Нативный вид: Стилизован под интерфейс YouTube
Как это работает
При нажатии кнопка автоматически:
- Открывает меню видео (три точки)
- Находит опцию “Не интересует” через SVG путь иконки
- Кликает по ней для удаления видео
Это делает скрипт совместимым с любым языком интерфейса без текстового сопоставления.
Установка
- Установите расширение для UserScripts (Tampermonkey/Violentmonkey)
- Установить скрипт
- Посетите главную YouTube и наслаждайтесь чистой лентой!
Исходный код
// ==UserScript==// @name YouTube Quick Not Interested// @namespace https://cododel.dev/// @version 2.0// @description Adds "Not interested" button (Only Homepage)// @author Cododel// @match https://www.youtube.com/// @match https://www.youtube.com/?*// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com// @updateURL https://cododel.dev/mods/youtube-quick-not-interested/install.user.js// @downloadURL https://cododel.dev/mods/youtube-quick-not-interested/install.user.js// @grant none// ==/UserScript==
;(function () { 'use strict'
const CONFIG = { sel: { container: '.yt-lockup-metadata-view-model__menu-button', menuItem: 'ytd-menu-service-item-renderer, tp-yt-paper-item, yt-list-item-view-model', threeDotsIcon: 'path[d^="M12 4a2"]', targetIconSelector: 'path[d*="L4.755 6.661"]', popupContainer: 'ytd-popup-container', }, keywords: ['Не интересует', 'Not interested'], customSvgPath: 'M 12 1C5.925 1 1 5.925 1 12s4.925 11 11 11 11-4.925 11-11S18.075 1 12 1Zm0 2a9 9 0 018.246 12.605L4.755 6.661A8.99 8.99 0 0112 3ZM3.754 8.393l15.491 8.944A9 9 0 013.754 8.393Z', cls: 'custom-ni-btn', }
const isHomePage = () => window.location.pathname === '/'
const h = (tag, props = {}, ...children) => { const el = document.createElementNS(props.xmlns || 'http://www.w3.org/1999/xhtml', tag) Object.entries(props).forEach(([k, v]) => k === 'style' ? Object.assign(el.style, v) : k.startsWith('on') ? el.addEventListener(k.slice(2).toLowerCase(), v) : el.setAttribute(k, v), ) children.forEach((c) => el.appendChild(c)) return el }
const performAction = async (container) => { const dotsIcon = container.querySelector(CONFIG.sel.threeDotsIcon) const menuBtn = dotsIcon ? dotsIcon.closest('button') : null
if (!menuBtn) { console.warn('YouTube Quick Not Interested: Menu button not found') return }
menuBtn.click() await new Promise((r) => setTimeout(r, 150))
const popup = document.querySelector(CONFIG.sel.popupContainer) if (!popup) return
const items = Array.from(popup.querySelectorAll(CONFIG.sel.menuItem)) const target = items.find( (item) => item.querySelector(CONFIG.sel.targetIconSelector) || CONFIG.keywords.some((txt) => (item.textContent || '').includes(txt)), )
target?.click() }
const createButton = (container) => h( 'button', { class: CONFIG.cls, title: 'Не интересует / Not interested', onClick: (e) => { e.preventDefault() e.stopPropagation() performAction(container) }, style: { background: 'transparent', border: 'none', cursor: 'pointer', padding: 0, borderRadius: '50%', width: '40px', height: '40px', color: 'var(--yt-spec-text-secondary)', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'background 0.2s', }, onMouseEnter: (e) => (e.target.style.background = 'rgba(255,255,255,0.1)'), onMouseLeave: (e) => (e.target.style.background = 'transparent'), }, h( 'svg', { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', width: '24', height: '24', style: { pointerEvents: 'none', fill: 'currentColor', display: 'block' }, }, h('path', { xmlns: 'http://www.w3.org/2000/svg', d: CONFIG.customSvgPath }), ), )
const inject = (node) => { if (!isHomePage()) return if (!node || node.nodeType !== 1) return const containers = node.matches?.(CONFIG.sel.container) ? [node] : node.querySelectorAll(CONFIG.sel.container)
containers.forEach((c) => { if (!c.querySelector('.' + CONFIG.cls)) c.prepend(createButton(c)) }) }
const start = () => { const observer = new MutationObserver((mutations) => mutations.forEach((m) => m.addedNodes.forEach(inject)), )
observer.observe(document.body, { childList: true, subtree: true }) inject(document.body) }
if (document.body) { start() } else { document.addEventListener('DOMContentLoaded', start) }})()