YouTube Downloader pro

Download button by youtube.com (PRO)

// ==UserScript==
// @name         YouTube Downloader pro
// @namespace    http://tampermonkey.net/
// @version      5.6
// @description  Download button by youtube.com (PRO)
// @author       You
// @match        *://www.youtube.com/*
// @match        *://youtube.com/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // SVG icoon voor download
    const downloadIcon = `
        <svg viewBox="0 0 24 24" style="width: 24px; height: 24px; fill: currentColor;">
            <path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
        </svg>
    `;

    function getVideoId() {
        const urlParams = new URLSearchParams(window.location.search);
        return urlParams.get('v');
    }

    function createDownloadButton() {
        const videoId = getVideoId();
        if (!videoId) return null;

        // Creëer de button container
        const buttonContainer = document.createElement('div');
        buttonContainer.className = 'download-btn-container';
        buttonContainer.style.cssText = 'display: inline-flex; align-items: center;';

        // Creëer de button (zelfde stijl als YouTube buttons)
        const button = document.createElement('button');
        button.className = 'yt-spec-button-shape-next yt-spec-button-shape-next--tonal yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m';
        button.style.cssText = `
            cursor: pointer;
            margin: 0 4px;
        `;

        button.innerHTML = `
            <div class="yt-spec-button-shape-next__button-text-content">
                <span class="yt-core-attributed-string yt-core-attributed-string--white-space-no-wrap" style="display: flex; align-items: center; gap: 6px;">
                    ${downloadIcon}
                    <span>Download</span>
                </span>
            </div>
        `;

        button.addEventListener('click', () => {
            downloadVideo(videoId);
        });

        buttonContainer.appendChild(button);
        return buttonContainer;
    }

    function downloadVideo(videoId) {
        // Verschillende download opties
        const services = [
            {
                name: 'SaveFrom',
                url: `https://savefrom.net/?url=https://www.youtube.com/watch?v=${videoId}`
            },
            {
                name: 'YT5s',
                url: `https://yt5s.io/en/?q=https://www.youtube.com/watch?v=${videoId}`
            },
            {
                name: 'Y4KConvert',
                url: `https://www.y4kconvert.com/en/?url=https://www.youtube.com/watch?v=${videoId}`
            }
        ];

        // Toon een keuze menu
        showDownloadMenu(services, videoId);
    }

    function showDownloadMenu(services, videoId) {
        // Verwijder bestaand menu indien aanwezig
        const existingMenu = document.getElementById('yt-download-menu');
        if (existingMenu) {
            existingMenu.remove();
            return;
        }

        const menu = document.createElement('div');
        menu.id = 'yt-download-menu';
        menu.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: #282828;
            color: white;
            padding: 20px;
            border-radius: 12px;
            z-index: 10000;
            box-shadow: 0 4px 16px rgba(0,0,0,0.5);
            min-width: 350px;
            font-family: "Roboto", Arial, sans-serif;
        `;

        menu.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
                <h3 style="margin: 0; font-size: 18px; font-weight: 500;">Download Video</h3>
                <button id="close-menu" style="
                    background: none;
                    border: none;
                    color: white;
                    font-size: 24px;
                    cursor: pointer;
                    padding: 0;
                    width: 30px;
                    height: 30px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                ">✕</button>
            </div>
            <p style="margin: 0 0 15px 0; color: #aaa; font-size: 13px;">Choose service</p>
            <div id="service-list"></div>
            <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #404040;">
                <button id="copy-url-btn" style="
                    width: 100%;
                    padding: 10px;
                    background: #065fd4;
                    color: white;
                    border: none;
                    border-radius: 18px;
                    cursor: pointer;
                    font-size: 14px;
                    font-weight: 500;
                ">Copy URL</button>
            </div>
        `;

        const serviceList = menu.querySelector('#service-list');
        services.forEach(service => {
            const serviceBtn = document.createElement('button');
            serviceBtn.style.cssText = `
                width: 100%;
                padding: 12px;
                margin-bottom: 8px;
                background: #3f3f3f;
                color: white;
                border: none;
                border-radius: 8px;
                cursor: pointer;
                font-size: 14px;
                text-align: left;
                transition: background 0.2s;
            `;
            serviceBtn.textContent = `⬇️ ${service.name}`;
            serviceBtn.addEventListener('mouseover', () => {
                serviceBtn.style.background = '#4f4f4f';
            });
            serviceBtn.addEventListener('mouseout', () => {
                serviceBtn.style.background = '#3f3f3f';
            });
            serviceBtn.addEventListener('click', () => {
                window.open(service.url, '_blank');
                menu.remove();
            });
            serviceList.appendChild(serviceBtn);
        });

        // Close button
        menu.querySelector('#close-menu').addEventListener('click', () => {
            menu.remove();
        });

        // Copy URL button
        menu.querySelector('#copy-url-btn').addEventListener('click', () => {
            const videoUrl = `https://www.youtube.com/watch?v=${videoId}`;
            navigator.clipboard.writeText(videoUrl).then(() => {
                const btn = menu.querySelector('#copy-url-btn');
                btn.textContent = '✓ URL copied!';
                btn.style.background = '#00a000';
                setTimeout(() => {
                    btn.textContent = '📋 Copy URL';
                    btn.style.background = '#065fd4';
                }, 2000);
            });
        });

        // Close bij klikken buiten het menu
        const overlay = document.createElement('div');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.7);
            z-index: 9999;
        `;
        overlay.addEventListener('click', () => {
            menu.remove();
            overlay.remove();
        });

        document.body.appendChild(overlay);
        document.body.appendChild(menu);
    }

    function addDownloadButton() {
        // Zoek de actions bar (waar share, save, etc. staan)
        const actionsBar = document.querySelector('#actions #top-level-buttons-computed');

        if (!actionsBar) {
            return;
        }

        // Check of de button al bestaat
        if (document.querySelector('.download-btn-container')) {
            return;
        }

        // Zoek de share button
        const shareButton = actionsBar.querySelector('button[aria-label*="Share"], button[aria-label*="Delen"]');

        if (shareButton && shareButton.parentElement) {
            const downloadBtn = createDownloadButton();
            if (downloadBtn) {
                // Voeg de download button toe na de share button
                shareButton.parentElement.parentElement.insertAdjacentElement('afterend', downloadBtn);
            }
        }
    }

    // Probeer de button toe te voegen
    function init() {
        addDownloadButton();
    }

    // Wacht tot de pagina geladen is
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // Observer voor dynamische pagina wijzigingen (YouTube is een SPA)
    const observer = new MutationObserver(() => {
        if (getVideoId()) {
            addDownloadButton();
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // Luister naar URL wijzigingen
    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            setTimeout(init, 1000);
        }
    }).observe(document, {subtree: true, childList: true});

})();