YouTube Instant Unsubscribe Button on Manage Subscriptions Page

Add a Single-click Unsubscribe button for each channel on the YouTube manage subscriptions page

// ==UserScript==
// @name         YouTube Instant Unsubscribe Button on Manage Subscriptions Page 
// @namespace    http://tampermonkey.net/
// @version      0.9
// @description  Add a Single-click Unsubscribe button for each channel on the YouTube manage subscriptions page
// @author       chrisnt
// @match        https://www.youtube.com/feed/channels
// @grant        none
// @license      GNU GPLv3
// ==/UserScript==

(function() {
    'use strict';

    /**
     * Simulate a mouse click event on a given element.
     * @param {HTMLElement} element - The element to be clicked.
     */
    function simulateClick(element) {
        const event = new MouseEvent('click', {
            view: window,
            bubbles: true,
            cancelable: true,
            buttons: 1
        });
        element.dispatchEvent(event);
    }

    /**
     * Hide certain YouTube elements to prevent popups during the unsubscribe process.
     */
    function hideElements() {
        const style = document.createElement('style');
        style.id = 'hide-yt-elements';
        style.innerHTML = `
            ytd-popup-container, ytd-popup-container *,
            ytd-menu-popup-renderer, ytd-menu-popup-renderer * {
                display: none !important;
            }
        `;
        document.head.appendChild(style);
    }

    /**
     * Show the hidden YouTube elements after the unsubscribe process is complete.
     */
    function showElements() {
        const style = document.getElementById('hide-yt-elements');
        if (style) {
            document.head.removeChild(style);
        }
    }

    /**
     * Add custom Unsubscribe buttons to each channel renderer on the page.
     */
    function addUnsubscribeButtons() {
        const channels = document.querySelectorAll('ytd-channel-renderer');

        channels.forEach(channel => {
            if (!channel.querySelector('.custom-unsubscribe-button')) {
                const unsubscribeButton = document.createElement('button');
                unsubscribeButton.className = 'custom-unsubscribe-button';
                unsubscribeButton.innerHTML = `
                    <span style="display: inline-flex; align-items: center; justify-content: center;">
                        <svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope yt-icon" style="width: 20px; height: 20px; margin-right: 8px; fill: currentColor;">
                            <g class="style-scope yt-icon">
                                <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z" class="style-scope yt-icon"></path>
                            </g>
                        </svg>Unsubscribe
                    </span>`;

                // Style the unsubscribe button
                unsubscribeButton.style.cssText = `
                    margin-left: 12px;
                    padding: 0 12px;
                    background-color: #FF0000;
                    color: #FFFFFF;
                    border: none;
                    border-radius: 2px;
                    height: 36px;
                    font-size: 14px;
                    font-weight: 500;
                    cursor: pointer;
                    transition: background-color 0.3s ease;
                    display: inline-flex;
                    align-items: center;
                    justify-content: center;
                    box-sizing: border-box;
                    line-height: 36px;
                    vertical-align: middle;
                `;

                // Change background color on hover
                unsubscribeButton.addEventListener('mouseover', () => {
                    unsubscribeButton.style.backgroundColor = '#CC0000';
                });

                unsubscribeButton.addEventListener('mouseout', () => {
                    unsubscribeButton.style.backgroundColor = '#FF0000';
                });

                // Unsubscribe button click event
                unsubscribeButton.addEventListener('click', () => {
                    hideElements();
                    const dropdownButton = channel.querySelector("#notification-preference-button > ytd-subscription-notification-toggle-button-renderer-next > yt-button-shape > button > yt-touch-feedback-shape > div > div.yt-spec-touch-feedback-shape__fill");
                    if (dropdownButton) {
                        simulateClick(dropdownButton);
                        setTimeout(() => {
                            const unsubscribeButton = document.querySelector("#items > ytd-menu-service-item-renderer:nth-child(4) > tp-yt-paper-item > yt-formatted-string");
                            if (unsubscribeButton) {
                                simulateClick(unsubscribeButton);
                                setTimeout(() => {
                                    const confirmButton = document.querySelector("#confirm-button > yt-button-shape > button > yt-touch-feedback-shape > div > div.yt-spec-touch-feedback-shape__fill");
                                    if (confirmButton) {
                                        simulateClick(confirmButton);
                                        setTimeout(showElements, 100);
                                    } else {
                                        showElements();
                                    }
                                }, 100);
                            } else {
                                showElements();
                            }
                        }, 100);
                    } else {
                        showElements();
                    }
                });

                const actionButtons = channel.querySelector('#buttons');
                if (actionButtons) {
                    actionButtons.appendChild(unsubscribeButton);
                }
            }
        });
    }

    addUnsubscribeButtons();

    // Observe for new channel elements and add unsubscribe buttons dynamically
    const observer = new MutationObserver(addUnsubscribeButtons);
    const pageManager = document.querySelector('ytd-page-manager');

    if (pageManager) {
        observer.observe(pageManager, { childList: true, subtree: true });
    } else {
        console.error('YouTube page manager not found');
    }
})();