EmbedCast Link Extractor (Sidebar Edition)

Collapsible sidebar that centralizes all detected video/iframe links.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         EmbedCast Link Extractor (Sidebar Edition)
// @namespace    https://github.com/MoriNo23/embedCast
// @version      2.0
// @description  Collapsible sidebar that centralizes all detected video/iframe links.
// @author       mori
// @match        *://*/*
// @grant        none
// @license MIT
// @run-at       document-end
// @icon         https://raw.githubusercontent.com/MoriNo23/embedCast/main/assets/logo.png
// ==/UserScript==

(function() {
    'use strict';

    // --- COMMUNICATION SETUP ---
    const MESSAGE_TYPE = 'EMBEDCAST_FOUND_URL';

    // --- LOGIC FOR IFRAMES (CHILDREN) ---
    if (window.self !== window.top) {
        const notifyTop = (url) => {
            if (url && url.startsWith('http') && !url.includes('about:blank')) {
                // Send the URL to the main page
                window.top.postMessage({ type: MESSAGE_TYPE, url: url }, '*');
            }
        };

        // Notify the current iframe URL
        notifyTop(window.location.href);

        // Look for lazyload elements inside the iframe
        const checkLazyInIframe = () => {
            const lazy = document.querySelector('iframe, .lazyload, .lazyloade, [data-src]');
            if (lazy) {
                const url = lazy.src || lazy.getAttribute('data-src') || lazy.getAttribute('data-lazy-src');
                notifyTop(url);
            }
        };
        setInterval(checkLazyInIframe, 3000);
        return; // Stop execution here for iframes
    }

    // --- LOGIC FOR MAIN WINDOW (PARENT) ---
    const capturedUrls = new Set();
    let sidebar, listContainer;

    const createSidebar = () => {
        if (document.getElementById('embedcast-sidebar')) return;

        // Create the sidebar container
        sidebar = document.createElement('div');
        sidebar.id = 'embedcast-sidebar';
        Object.assign(sidebar.style, {
            position: 'fixed',
            right: '-260px', // Hidden by default
            top: '0',
            width: '260px',
            height: '100vh',
            background: '#1a1a2e',
            borderLeft: '2px solid #00ffcc',
            zIndex: '2147483647', // Always on top
            transition: 'right 0.3s ease',
            display: 'flex',
            flexDirection: 'column',
            boxShadow: '-5px 0 15px rgba(0,0,0,0.5)',
            color: '#fff',
            fontFamily: 'sans-serif'
        });

        sidebar.innerHTML = `
            <div style="padding: 15px; background: #16213e; border-bottom: 1px solid #00ffcc; display: flex; align-items: center; justify-content: space-between;">
                <div style="display:flex; align-items:center;">
                    <img src="https://raw.githubusercontent.com/MoriNo23/embedCast/main/assets/logo.png" style="width:20px; margin-right:8px;">
                    <span style="color:#00ffcc; font-weight:bold; font-size:14px;">EmbedCast</span>
                </div>
                <button id="ec-close" style="background:none; border:none; color:#00ffcc; cursor:pointer; font-size:18px;">×</button>
            </div>
            <div id="ec-list" style="flex:1; overflow-y:auto; padding:10px;">
                <p id="ec-empty" style="color:#666; font-size:12px; text-align:center; margin-top:20px;">Searching links...</p>
            </div>
            <div id="ec-toggle" style="position:absolute; left:-40px; top:50%; width:40px; height:60px; background:#1a1a2e; border:2px solid #00ffcc; border-right:none; border-radius:10px 0 0 10px; cursor:pointer; display:flex; align-items:center; justify-content:center; color:#00ffcc; font-weight:bold;">
                <img src="https://raw.githubusercontent.com/MoriNo23/embedCast/main/assets/logo.png" style="width:25px;">
            </div>
        `;

        document.body.appendChild(sidebar);
        listContainer = document.getElementById('ec-list');

        // UI Events
        const toggleBtn = document.getElementById('ec-toggle');
        const closeBtn = document.getElementById('ec-close');
        
        const toggleSidebar = () => {
            const isOpen = sidebar.style.right === '0px';
            sidebar.style.right = isOpen ? '-260px' : '0px';
        };

        toggleBtn.onclick = toggleSidebar;
        closeBtn.onclick = toggleSidebar;
    };

    const addUrlToList = (url) => {
        // Avoid duplicate links
        if (capturedUrls.has(url)) return;
        capturedUrls.add(url);

        const emptyMsg = document.getElementById('ec-empty');
        if (emptyMsg) emptyMsg.remove();

        // Create link item in the list
        const item = document.createElement('div');
        Object.assign(item.style, {
            background: '#16213e',
            padding: '10px',
            marginBottom: '8px',
            borderRadius: '5px',
            border: '1px solid #30475e',
            fontSize: '11px'
        });

        item.innerHTML = `
            <div style="color:#00ffcc; margin-bottom:5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${url}">
                ${url}
            </div>
            <button class="ec-copy-btn" style="width:100%; background:#0f3460; color:#00ffcc; border:1px solid #00ffcc; padding:5px; cursor:pointer; border-radius:3px; font-weight:bold;">
                COPY
            </button>
        `;

        item.querySelector('.ec-copy-btn').onclick = function() {
            navigator.clipboard.writeText(url);
            this.innerText = 'COPIED!';
            setTimeout(() => this.innerText = 'COPY', 2000);
        };

        listContainer.appendChild(item);
        
        // Auto-open sidebar when the first link is found
        if (capturedUrls.size === 1) {
            sidebar.style.right = '0px';
        }
    };

    // Listen for messages from iframes
    window.addEventListener('message', (event) => {
        if (event.data && event.data.type === MESSAGE_TYPE) {
            addUrlToList(event.data.url);
        }
    });

    // Initialize sidebar
    createSidebar();

    // Also search in the main page for links
    setInterval(() => {
        const potential = document.querySelectorAll('iframe, .lazyload, .lazyloade, [data-src]');
        potential.forEach(el => {
            const url = el.src || el.getAttribute('data-src') || el.getAttribute('data-lazy-src');
            if (url && url.startsWith('http')) addUrlToList(url);
        });
    }, 3000);

})();