Universal Video Downloader

Enhanced video downloader with platform-specific support

目前为 2025-03-06 提交的版本。查看 最新版本

// ==UserScript==
// @name         Universal Video Downloader
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Enhanced video downloader with platform-specific support
// @author       usercromix & Grok
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Platform detection patterns
    const platformPatterns = {
        youtube: /youtube\.com|youtu\.be/,
        twitter: /twitter\.com|x\.com/,
        facebook: /facebook\.com/
    };

    // Create UI container (unchanged from original)
    const uiContainer = document.createElement('div');
    uiContainer.id = 'video-downloader-ui';
    uiContainer.style.cssText = `
        position: fixed;
        z-index: 9999;
        background: linear-gradient(135deg, #2b2d42, #8d99ae);
        padding: 15px;
        border-radius: 10px;
        box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
        cursor: move;
        user-select: none;
        top: 20px;
        right: 20px;
        font-family: Arial, sans-serif;
        transition: all 0.3s ease;
    `;

    // Create header and buttons (unchanged styling)
    const header = document.createElement('div');
    header.textContent = 'Video Downloader';
    header.style.cssText = `
        color: #edf2f4;
        font-size: 14px;
        font-weight: bold;
        margin-bottom: 10px;
        text-align: center;
    `;

    const buttonContainer = document.createElement('div');
    buttonContainer.style.cssText = `
        display: flex;
        flex-direction: column;
        gap: 10px;
    `;

    const downloadButton = document.createElement('button');
    downloadButton.textContent = 'Download Video';
    downloadButton.style.cssText = `
        background: linear-gradient(45deg, #ef233c, #d90429);
        color: white;
        border: none;
        padding: 8px 16px;
        border-radius: 5px;
        cursor: pointer;
        transition: transform 0.2s ease;
    `;

    const selectButton = document.createElement('button');
    selectButton.textContent = 'Select Video';
    selectButton.style.cssText = `
        background: linear-gradient(45deg, #023e8a, #0077b6);
        color: white;
        border: none;
        padding: 8px 16px;
        border-radius: 5px;
        cursor: pointer;
        transition: transform 0.2s ease;
    `;

    // Button hover effects
    [downloadButton, selectButton].forEach(button => {
        button.addEventListener('mouseover', () => button.style.transform = 'scale(1.05)');
        button.addEventListener('mouseout', () => button.style.transform = 'scale(1)');
    });

    // Append elements
    buttonContainer.appendChild(downloadButton);
    buttonContainer.appendChild(selectButton);
    uiContainer.appendChild(header);
    uiContainer.appendChild(buttonContainer);
    document.body.appendChild(uiContainer);

    // Draggable UI (unchanged from original)
    let isDragging = false;
    let currentX = window.innerWidth - uiContainer.offsetWidth - 20;
    let currentY = 20;

    header.addEventListener('mousedown', (e) => {
        isDragging = true;
        const rect = uiContainer.getBoundingClientRect();
        initialX = e.clientX - rect.left;
        initialY = e.clientY - rect.top;
    });

    let initialX, initialY;
    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            e.preventDefault();
            currentX = e.clientX - initialX;
            currentY = e.clientY - initialY;
            uiContainer.style.left = currentX + 'px';
            uiContainer.style.top = currentY + 'px';
            uiContainer.style.right = 'auto';
        }
    });

    document.addEventListener('mouseup', () => isDragging = false);

    // Platform-specific video detection
    function detectPlatform() {
        const url = window.location.href;
        for (const [platform, pattern] of Object.entries(platformPatterns)) {
            if (pattern.test(url)) return platform;
        }
        return 'generic';
    }

    function getYoutubeVideoUrl() {
        const videoId = new URLSearchParams(window.location.search).get('v');
        if (videoId) {
            return `https://www.youtube.com/watch?v=${videoId}`;
        }
        const meta = document.querySelector('meta[property="og:video:url"]');
        return meta?.content;
    }

    function getTwitterVideoUrl() {
        const video = document.querySelector('video[src*="video.twimg.com"]');
        if (video) return video.src;
        const tweet = document.querySelector('div[data-testid="tweet"] video');
        return tweet?.src;
    }

    function getFacebookVideoUrl() {
        const video = document.querySelector('video[src*="fbcdn.net"]');
        if (video) return video.src;
        const meta = document.querySelector('meta[property="og:video"]');
        return meta?.content;
    }

    function detectVideo() {
        const platform = detectPlatform();
        
        switch (platform) {
            case 'youtube':
                return getYoutubeVideoUrl();
            case 'twitter':
                return getTwitterVideoUrl();
            case 'facebook':
                return getFacebookVideoUrl();
            default:
                const videos = document.getElementsByTagName('video');
                if (videos.length > 0) {
                    return videos[0].src || videos[0].currentSrc ||
                           videos[0].getElementsByTagName('source')[0]?.src;
                }
                const videoExtensions = ['.mp4', '.webm', '.mkv', '.avi', '.mov'];
                const links = Array.from(document.getElementsByTagName('a'));
                return links.find(link => 
                    videoExtensions.some(ext => link.href.toLowerCase().endsWith(ext))
                )?.href;
        }
    }

    // Download handler with platform-specific naming
    function downloadVideo(videoUrl) {
        if (!videoUrl) {
            alert('No video selected or detected!');
            return;
        }

        const platform = detectPlatform();
        let filenamePrefix = 'video';
        switch (platform) {
            case 'youtube':
                filenamePrefix = 'youtube';
                break;
            case 'twitter':
                filenamePrefix = 'twitter';
                break;
            case 'facebook':
                filenamePrefix = 'facebook';
                break;
        }

        const downloadLink = document.createElement('a');
        downloadLink.href = videoUrl;
        downloadLink.download = `${filenamePrefix}_${new Date().getTime()}.mp4`;
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);
        alert('Video download started!');
    }

    // Button handlers
    downloadButton.addEventListener('click', () => {
        const videoUrl = detectVideo();
        downloadVideo(videoUrl);
    });

    let isSelecting = false;
    selectButton.addEventListener('click', () => {
        if (!isSelecting) {
            isSelecting = true;
            selectButton.textContent = 'Click a Video';
            document.body.style.cursor = 'crosshair';

            const videoClickHandler = (e) => {
                let videoUrl;
                const platform = detectPlatform();

                switch (platform) {
                    case 'youtube':
                        videoUrl = e.target.closest('video')?.src || getYoutubeVideoUrl();
                        break;
                    case 'twitter':
                        videoUrl = e.target.closest('video')?.src || getTwitterVideoUrl();
                        break;
                    case 'facebook':
                        videoUrl = e.target.closest('video')?.src || getFacebookVideoUrl();
                        break;
                    default:
                        const video = e.target.closest('video') || 
                                    e.target.closest('a[href*=".mp4"]') || 
                                    e.target.closest('a[href*=".webm"]');
                        videoUrl = video?.src || video?.currentSrc || video?.href;
                }

                if (videoUrl) {
                    e.preventDefault();
                    downloadVideo(videoUrl);
                    cleanupSelection();
                }
            };

            const cleanupSelection = () => {
                isSelecting = false;
                selectButton.textContent = 'Select Video';
                document.body.style.cursor = 'default';
                document.removeEventListener('click', videoClickHandler);
            };

            document.addEventListener('click', videoClickHandler, { once: true });
            setTimeout(cleanupSelection, 10000);
        }
    });

    // Anti-detection measures
    Object.defineProperty(window, 'videoDownloader', {
        value: undefined,
        writable: false,
        configurable: false
    });
    console.log = function() {};
})();