EmbedCast Link Extractor (Sidebar Edition)

Collapsible sidebar that centralizes all detected video/iframe links.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==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);

})();