Universal Link Extractor

Estrae link con filtri di inclusione specifici per ogni sito, con GUI e toggle.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Universal Link Extractor
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Estrae link con filtri di inclusione specifici per ogni sito, con GUI e toggle.
// @author       ChatGPT (modificato)
// @match        *://*/*
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @license MIT 
// ==/UserScript==

(function() {
    'use strict';

    const currentHost = location.host;
    const enabledSites = JSON.parse(GM_getValue('enabledSites', '[]'));

    // Struttura per salvare i filtri specifici per ogni sito
    // { "example.com": ["pattern1", "pattern2"], "another.com": ["pattern3"] }
    const siteFilters = JSON.parse(GM_getValue('siteFilters', '{}'));

    // Menu per abilitare/disabilitare lo script su questo sito
    GM_registerMenuCommand(
        enabledSites.includes(currentHost)
            ? 'Disabilita Universal Link Extractor su questo sito'
            : 'Abilita Universal Link Extractor su questo sito',
        () => {
            let sites = JSON.parse(GM_getValue('enabledSites', '[]'));
            if (sites.includes(currentHost)) {
                sites = sites.filter(s => s !== currentHost);
                GM_setValue('enabledSites', JSON.stringify(sites));
                alert('Script disabilitato su: ' + currentHost);
            } else {
                sites.push(currentHost);
                GM_setValue('enabledSites', JSON.stringify(sites));

                // Se non esistono filtri per questo sito, crea un default
                if (!siteFilters[currentHost]) {
                    siteFilters[currentHost] = [`^https://${currentHost}/.*`];
                    GM_setValue('siteFilters', JSON.stringify(siteFilters));
                }

                alert('Script abilitato su: ' + currentHost);
            }
        }
    );

    // Se non abilitato, esci
    if (!enabledSites.includes(currentHost)) return;

    // GUI principale
    const panel = document.createElement('div');
    Object.assign(panel.style, {
        position: 'fixed', top: '50px', right: '10px',
        width: '360px', maxHeight: '300px', overflowY: 'auto', overflowX: 'hidden',
        backgroundColor: 'rgba(0,0,0,0.85)', color: '#fff',
        border: '1px solid #444', borderRadius: '4px',
        boxShadow: '0 2px 8px rgba(0,0,0,0.6)', zIndex: '999999',
        fontFamily: 'Arial, sans-serif', fontSize: '14px', lineHeight: '1.4',
        transition: 'max-height 0.3s ease, opacity 0.3s ease', opacity: '1'
    });

    // Ottieni i filtri del sito corrente
    const currentSiteFilters = siteFilters[currentHost] || [`^https://${currentHost}/.*`];

    panel.innerHTML = `
        <div style="padding:12px;">
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;">
                <strong>Universal Link Extractor</strong>
                <button id="extractBtn" style="background:#28a745; border:none; color:#fff; padding:4px 8px; border-radius:3px; cursor:pointer;">Estrai link</button>
            </div>
            <div style="font-weight:bold; margin-bottom:8px;">Come usare:</div>
            <ul style="padding-left:20px; margin:0 0 8px 0;">
                <li>Clicca "Estrai link" per copiare quelli che matchano i filtri.</li>
                <li>Configura filtri di <strong>inclusione</strong> specifici per ${currentHost}.</li>
            </ul>
            <div style="font-weight:bold; margin-bottom:4px;">Filtri attivi per ${currentHost}:</div>
            <pre style="background:#f4f4f4; color:#000; padding:10px; border-radius:4px; font-family:monospace; font-size:13px; max-height:80px; overflow-y:auto;">
${currentSiteFilters.join('\n')}
            </pre>
            <div style="font-size:12px; color:#ccc; margin-top:8px;">Apri/chiudi con la freccia blu in alto a destra.</div>
        </div>
    `;
    document.body.appendChild(panel);

    // Listener Estrai
    document.getElementById('extractBtn').addEventListener('click', extractLinks);

    // Toggle sempre visibile
    const toggle = document.createElement('div');
    Object.assign(toggle.style, {
        position: 'fixed', top: '10px', right: '10px',
        width: '32px', height: '32px', cursor: 'pointer',
        backgroundColor: '#007bff', color: '#fff', display: 'flex',
        alignItems: 'center', justifyContent: 'center',
        borderRadius: '4px', fontSize: '18px', fontWeight: 'bold',
        boxShadow: '0 2px 4px rgba(0,0,0,0.5)', zIndex: '1000000',
        userSelect: 'none', transition: 'opacity 0.3s ease', opacity: '1'
    });
    toggle.textContent = '▼';
    document.body.appendChild(toggle);

    let expanded = true;
    toggle.addEventListener('click', () => {
        expanded = !expanded;
        if (expanded) {
            panel.style.maxHeight = '300px'; panel.style.opacity = '1'; toggle.textContent = '▼'; toggle.style.opacity = '1';
        } else {
            panel.style.maxHeight = '0'; panel.style.opacity = '0'; toggle.textContent = '▲'; toggle.style.opacity = '0';
        }
    });

    // Menu comando per configurare i filtri specifici per il sito
    GM_registerMenuCommand(`Configura filtri di inclusione per ${currentHost}`, () => {
        const defaultVal = currentSiteFilters.join(',');
        const inp = prompt(`Regex da includere per ${currentHost} (separa con virgola):`, defaultVal);

        if (inp !== null) {
            const newFilters = inp.split(',').map(s => s.trim()).filter(s => s);

            // Aggiorna i filtri specifici per questo sito
            siteFilters[currentHost] = newFilters;
            GM_setValue('siteFilters', JSON.stringify(siteFilters));

            alert(`Filtri di inclusione aggiornati per ${currentHost}`);
            // Refresh per aggiornare l'interfaccia
            location.reload();
        }
    });

    // Estrai link basandosi solo sui filtri del sito corrente
    function matchesAny(link, patterns) {
        return patterns.some(pat => {
            try {
                return new RegExp(pat).test(link);
            } catch {
                return false;
            }
        });
    }

    function extractLinks() {
        const currentFilters = siteFilters[currentHost] || [`^https://${currentHost}/.*`];

        const links = Array.from(document.querySelectorAll('a[href]'))
            .map(a => a.href)
            .filter(l => matchesAny(l, currentFilters));

        if (!links.length) return alert('Nessun link trovato');

        const count = links.length;
        navigator.clipboard.writeText(links.join('\n')).then(() => {
            console.log('Link estratti:', links);
            alert(`Ho copiato ${count} link negli appunti`);
        });
    }
})();