ClipboardUrler

Detects direct video file URLs and shows a small clipboard icon for copying

目前為 2025-05-25 提交的版本,檢視 最新版本

// ==UserScript==
// @name         ClipboardUrler
// @namespace    http://your.namespace
// @version      2.0
// @description  Detects direct video file URLs and shows a small clipboard icon for copying
// @license      MIT
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const videoExtensions = /\.(mp4|webm|mkv|avi|mov|m3u8|ts|flv|f4v|3gp|3g2|ogv|rm|rmvb|asf|wmv|m4v|vob|mpeg|mpg|m2ts|mts)(\?|#|$)/i;

    function isValidVideoURL(url) {
        return url && !url.startsWith('blob:') && /^https?:\/\//.test(url) && videoExtensions.test(url);
    }

    // UI: Clipboard icon
    const clipIcon = document.createElement('div');
    clipIcon.textContent = '📋';
    Object.assign(clipIcon.style, {
        position: 'fixed',
        bottom: '10px',
        left: '10px',
        fontSize: '20px',
        cursor: 'pointer',
        zIndex: '99999',
        padding: '6px',
        background: 'rgba(255,255,255,0.9)',
        borderRadius: '6px',
        boxShadow: '0 0 3px rgba(0,0,0,0.3)',
        userSelect: 'none',
        display: 'none'
    });

    // Tooltip
    const tooltip = document.createElement('div');
    tooltip.textContent = 'Copied!';
    Object.assign(tooltip.style, {
        position: 'fixed',
        bottom: '40px',
        left: '10px',
        padding: '4px 8px',
        background: '#333',
        color: '#fff',
        borderRadius: '4px',
        fontSize: '12px',
        opacity: '0',
        transition: 'opacity 0.3s',
        zIndex: '99999',
        pointerEvents: 'none'
    });

    document.body.appendChild(clipIcon);
    document.body.appendChild(tooltip);

    let lastURL = '';

    clipIcon.onclick = () => {
        if (lastURL) {
            navigator.clipboard.writeText(lastURL).then(() => {
                tooltip.style.opacity = '1';
                setTimeout(() => (tooltip.style.opacity = '0'), 1200);
            });
        }
    };

    // Efficient element cache (every few seconds)
    let videos = [], iframes = [], links = [];
    let lastCache = 0;

    function refreshCache() {
        videos = Array.from(document.querySelectorAll('video'));
        iframes = Array.from(document.querySelectorAll('iframe'));
        links = Array.from(document.querySelectorAll('a[href]'));
        lastCache = Date.now();
    }

    function detectVideoURL() {
        const now = Date.now();
        if (now - lastCache > 5000) refreshCache();

        let foundURL = '';

        for (const vid of videos) {
            const src = vid.currentSrc || vid.src;
            if (isValidVideoURL(src)) {
                foundURL = src;
                break;
            }
        }

        if (!foundURL) {
            for (const iframe of iframes) {
                const src = iframe.src;
                if (src.includes('youtube.com/embed/')) {
                    const id = src.split('/').pop().split('?')[0];
                    foundURL = `https://www.youtube.com/watch?v=${id}`;
                    break;
                } else if (src.includes('player.vimeo.com/video/')) {
                    const id = src.split('/').pop().split('?')[0];
                    foundURL = `https://vimeo.com/${id}`;
                    break;
                } else if (isValidVideoURL(src)) {
                    foundURL = src;
                    break;
                }
            }
        }

        if (!foundURL) {
            for (const a of links) {
                if (isValidVideoURL(a.href)) {
                    foundURL = a.href;
                    break;
                }
            }
        }

        if (foundURL && foundURL !== lastURL) {
            lastURL = foundURL;
            clipIcon.title = 'Click to copy:\n' + lastURL;
            clipIcon.style.display = 'block';
        } else if (!foundURL) {
            clipIcon.style.display = 'none';
        }
    }

    setInterval(detectVideoURL, 2000); // low frequency, low CPU
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址