YouTube Keyword Blocker (Whole‑Word Mode)

Hide YouTube homepage videos by blacklisted words in title or channel name

2025-05-22 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

// ==UserScript==
// @name         YouTube Keyword Blocker (Whole‑Word Mode)
// @description  Hide YouTube homepage videos by blacklisted words in title or channel name
// @match        https://www.youtube.com/*
// @run-at       document-end
// @version 0.0.1.20250522140812
// @namespace https://greasyfork.org/users/1435046
// ==/UserScript==

(function () {
  'use strict';

  // skip “results” and “@channel” pages
  if (location.pathname.startsWith('/results') || location.pathname.startsWith('/@')) return;

  // 1) List words
  const terms = [
 
  ];

  // 2) Convert to RegExp objects with \b boundaries, case‑insensitive
  const blacklist = terms.map(term => {
    const esc = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    return new RegExp(`\\b${esc}\\b`, 'i');
  });

  const ITEM_SELECTOR = 'ytd-rich-item-renderer'; /*, ytd-rich-grid-media, ytd-video-renderer*/
  const TITLE_SELECTOR = '#video-title';
  const CHANNEL_SELECTOR = 'ytd-channel-name a';

  function filterItem(item) {

    // skip “results” and “@channel” pages on dynamic loads
    if (location.pathname.startsWith('/results') ||
      location.pathname.startsWith('/@')) return;

    // skip if we've already seen this node
    if (item.dataset.keywordBlocked) return;
    item.dataset.keywordBlocked = '1';

    const linkEl = item.querySelector('a#video-title-link');
    const title = linkEl
      ? linkEl.getAttribute('aria-label').trim()
      : '‹no title›';
    console.log('› filterItem saw:', item.tagName, title);

    const channelEl = item.querySelector(CHANNEL_SELECTOR);
    const channel = channelEl ? channelEl.textContent.trim() : '';

    for (const re of blacklist) {
      if (re.test(title) || re.test(channel)) {
        console.log(
          `Blocking video:\n` +
          `  title:   "${title}"\n` +
          `  channel: "${channel}"\n` +
          `  matched: ${re}`
        );
        item.style.display = 'none';
        return;
      }
    }
  }

  function scanPage() {
    // skip “results” and “@channel” pages on every scan
    if (location.pathname.startsWith('/results') ||
      location.pathname.startsWith('/@')) return;
    document.querySelectorAll(ITEM_SELECTOR).forEach(filterItem);
  }

  new MutationObserver(mutations => {

    for (const { addedNodes } of mutations) {
      for (const node of addedNodes) {
        if (!(node instanceof HTMLElement)) continue;
        if (node.matches(ITEM_SELECTOR)) filterItem(node);
        else node.querySelectorAll && node.querySelectorAll(ITEM_SELECTOR).forEach(filterItem);
      }
    }
  }).observe(document.body, { childList: true, subtree: true });

  scanPage();

  window.addEventListener('yt-navigate-finish', scanPage);
})();