YouTube Video Selector and Hider (Language Independent)

Quickly select and hide multiple videos on YouTube, works in any language

// ==UserScript==
// @name         YouTube Video Selector and Hider (Language Independent)
// @namespace    http://tampermonkey.net/
// @version      0.9
// @description  Quickly select and hide multiple videos on YouTube, works in any language
// @match        https://www.youtube.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let isSelecting = false;
    let startX, startY;
    let selectedVideos = new Set();

    // Create hide button
    const hideButton = document.createElement('button');
    hideButton.textContent = 'Hide Selected (0)';
    hideButton.style.position = 'fixed';
    hideButton.style.top = '10px';
    hideButton.style.right = '10px';
    hideButton.style.zIndex = '9999';
    hideButton.style.display = 'none';
    hideButton.style.padding = '10px';
    hideButton.style.backgroundColor = '#ff0000';
    hideButton.style.color = '#ffffff';
    hideButton.style.border = 'none';
    hideButton.style.borderRadius = '5px';
    hideButton.style.cursor = 'pointer';
    document.body.appendChild(hideButton);

    // Event listeners
    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);
    document.addEventListener('mousedown', handleMouseDown);
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
    hideButton.addEventListener('click', hideSelectedVideos);

    function handleKeyDown(e) {
        if (e.key.toLowerCase() === 'x' && !isSelecting) {
            isSelecting = true;
            document.body.style.userSelect = 'none';
        }
    }

    function handleKeyUp(e) {
        if (e.key.toLowerCase() === 'x') {
            isSelecting = false;
            document.body.style.userSelect = '';
            removeSelectionBox();
        }
    }

    function handleMouseDown(e) {
        if (isSelecting) {
            startX = e.clientX;
            startY = e.clientY;
            createSelectionBox(startX, startY);
        }
    }

    function handleMouseMove(e) {
        if (isSelecting) {
            const selectionBox = document.getElementById('selection-box');
            if (selectionBox) {
                const width = e.clientX - startX;
                const height = e.clientY - startY;
                selectionBox.style.width = Math.abs(width) + 'px';
                selectionBox.style.height = Math.abs(height) + 'px';
                selectionBox.style.left = (width < 0 ? e.clientX : startX) + 'px';
                selectionBox.style.top = (height < 0 ? e.clientY : startY) + 'px';
            }
        }
    }

    function handleMouseUp() {
        if (isSelecting) {
            const selectionBox = document.getElementById('selection-box');
            if (selectionBox) {
                selectVideos(selectionBox);
                removeSelectionBox();
            }
        }
    }

    function createSelectionBox(x, y) {
        removeSelectionBox();
        const selectionBox = document.createElement('div');
        selectionBox.id = 'selection-box';
        selectionBox.style.position = 'fixed';
        selectionBox.style.border = '2px solid blue';
        selectionBox.style.backgroundColor = 'rgba(0, 0, 255, 0.1)';
        selectionBox.style.left = x + 'px';
        selectionBox.style.top = y + 'px';
        selectionBox.style.zIndex = '9998';
        document.body.appendChild(selectionBox);
    }

    function removeSelectionBox() {
        const existingBox = document.getElementById('selection-box');
        if (existingBox) {
            existingBox.remove();
        }
    }

    function selectVideos(selectionBox) {
        const videos = document.querySelectorAll('ytd-rich-item-renderer');
        const boxRect = selectionBox.getBoundingClientRect();

        videos.forEach(video => {
            const videoRect = video.getBoundingClientRect();
            if (!(videoRect.right < boxRect.left ||
                  videoRect.left > boxRect.right ||
                  videoRect.bottom < boxRect.top ||
                  videoRect.top > boxRect.bottom)) {
                if (selectedVideos.has(video)) {
                    selectedVideos.delete(video);
                    video.style.outline = '';
                } else {
                    selectedVideos.add(video);
                    video.style.outline = '2px solid red';
                }
            }
        });

        updateHideButton();
    }

    function updateHideButton() {
        hideButton.textContent = `Hide Selected (${selectedVideos.size})`;
        hideButton.style.display = selectedVideos.size > 0 ? 'block' : 'none';
    }

    async function hideSelectedVideos() {
        const totalVideos = selectedVideos.size;
        let hiddenVideos = 0;

        hideButton.disabled = true;
        hideButton.style.backgroundColor = '#888888';

        for (const video of selectedVideos) {
            await hideVideo(video);
            video.style.outline = '';
            hiddenVideos++;
            hideButton.textContent = `Hiding... (${hiddenVideos}/${totalVideos})`;
        }

        selectedVideos.clear();
        hideButton.textContent = `Hidden ${hiddenVideos} videos`;
        hideButton.disabled = false;
        hideButton.style.backgroundColor = '#ff0000';

        // Hide the button after 2 seconds
        setTimeout(() => {
            hideButton.style.display = 'none';
        }, 2000);
    }

    function hideVideo(video) {
        return new Promise((resolve) => {
            // Look for the menu button using a more generic selector
            const menuButton = video.querySelector('button[aria-label]');
            if (menuButton && menuButton.click) {
                menuButton.click();
                setTimeout(() => {
                    // Look for the hide option based on its position and icon
                    const menuItems = document.querySelectorAll('ytd-menu-service-item-renderer');
                    let hideOption = null;

                    for (const item of menuItems) {
                        // Check if the item has the "hide" icon
                        const icon = item.querySelector('yt-icon');
                        if (icon) {
                            const svg = icon.querySelector('svg');
                            if (svg && svg.innerHTML.includes('M12 2c5.52 0 10 4.48 10 10s-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2zM3 12c0 2.31.87 4.41 2.29 6L18 5.29C16.41 3.87 14.31 3 12 3c-4.97 0-9 4.03-9 9zm15.71-6L6 18.71C7.59 20.13 9.69 21 12 21c4.97 0 9-4.03 9-9 0-2.31-.87-4.41-2.29-6z')) {
                                hideOption = item;
                                break;
                            }
                        }
                    }

                    if (hideOption && hideOption.click) {
                        hideOption.click();
                        setTimeout(resolve, 100);
                    } else {
                        resolve();
                    }
                }, 100);
            } else {
                resolve();
            }
        });
    }
})();