Paywalls der Verlage überwinden: Bypass Paywall Clean von Mozilla geblockt

Update: Nach längerer Suche des richtigen Add-ons durch Mozilla (es gingen mehrere E-Mails hin und her), kam heute (22. August 2025) endlich die Antwort auf unsere Presseanfrage:

Der Vertreter des Rechteinhabers hat uns eine Urheberrechtsverletzungsmitteilung zugesandt. Wir haben den Entwickler benachrichtigt und das Add-on gemäß unseren Richtlinien und unseren gesetzlichen Verpflichtungen entfernt. Wir haben keine Gegendarstellung vom Entwickler erhalten. Alle Entwickler, die Add-ons auf AMO listen möchten, müssen unsere Add-on-Richtlinien kennen und befolgen. (Erklärung: AMO = addons.mozilla.org)

Add-ons oder Entwickler, die gegen unsere Richtlinien oder gegen das Gesetz verstoßen, können entfernt oder deaktiviert werden. Die Add-on-Richtlinien legen fest, dass alle auf addons.mozilla.org gelisteten Add-ons der Nutzungsrichtlinie von Mozilla unterliegen. Die Nutzungsrichtlinie verbietet ausdrücklich die Nutzung der Dienste von Mozilla zur Verletzung von Urheberrechten, Markenrechten, Patentrechten oder anderen Rechten an geistigem Eigentum Dritter.

Warum Mozilla die Erweiterung Bypass Paywalls Clean (BPC) als „schädlich“ kennzeichnet, obwohl davon gar kein Schaden ausgeht, haben wir ebenfalls gefragt. Das wollte man uns leider nicht mitteilen. Unklar bleibt auch welcher Verlag juristisch aktiv wurde.

OK, manchmal sieht man den Wald voller Bäume nicht :slight_smile: danke

1 „Gefällt mir“

script aufgrund der vielen anfragen öffentlich gemacht, siehe beitrag oben

1 „Gefällt mir“

@spedersen2111

// ==UserScript==
// @name         Nachrichten aus Archiv lesen
// @namespace    N/A
// @version      0.7.0
// @description  Findet echten Kurzlink aus archive.vn/.ph/.fo
// @match        https://www.spiegel.de/*
// @match        https://www.tagesspiegel.de/*
// @match        https://www.zeit.de/*
// @match        https://www.welt.de/*
// @match        https://www.sueddeutsche.de/*
// @match        https://www.faz.net/*
// @match        https://www.bild.de/*
// @match        https://www.heise.de/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      archive.vn
// @connect      archive.ph
// @connect      archive.fo
// @connect      archive.is
// @connect      archive.md
// @connect      archive.li
// @connect      archive.today
// ==/UserScript==

(function () {
    'use strict';

    // Konfiguration
    const config = {
        tlds: ['vn', 'ph', 'fo', 'is', 'md', 'li', 'today'],
        timeout: 8000, // 8 Sekunden Timeout pro Archive
        retries: 2, // Anzahl Wiederholungen bei Netzwerkfehlern
    };

    window.addEventListener('load', () => {
        // Nur fortfahren, wenn ein Pfad existiert (nicht nur Domain)
        const path = location.pathname;
        const host = location.hostname;

        // Button nur anzeigen, wenn Pfad weiterführt
        const isStartseite = (
            path === '/' ||
            path === '' ||
            (host.includes('faz.net') && path === '/aktuell/') ||
            (host.includes('zeit.de') && path === '/index')
        );
        if (isStartseite) return;

        setTimeout(() => {
            if (document.getElementById('archive-button')) return;
            createArchiveButton();
        }, 500);
    });

    function createArchiveButton() {
        const btn = document.createElement('button');
        btn.id = 'archive-button';
        btn.textContent = 'Archiv anzeigen';
        btn.title = 'Klick: Archivierte Version suchen\nShift+Klick: Direkt zu archive.vn\nAlt+Klick: Neue Archivierung erstellen';

        Object.assign(btn.style, {
            position: 'fixed',
            bottom: '40px',
            left: '75%',
            transform: 'translateX(-50%)',
            zIndex: '2147483647',
            backgroundColor: '#ffcc00',
            color: '#000',
            fontSize: '16px',
            fontWeight: 'bold',
            padding: '12px 24px',
            border: '2px solid #000',
            borderRadius: '10px',
            cursor: 'pointer',
            boxShadow: '0 4px 8px rgba(0,0,0,0.3)',
            transition: 'all 0.2s ease',
            fontFamily: 'Arial, sans-serif',
        });

        // Hover-Effekt
        btn.addEventListener('mouseenter', () => {
            btn.style.backgroundColor = '#ffd700';
            btn.style.transform = 'translateX(-50%) scale(1.05)';
        });

        btn.addEventListener('mouseleave', () => {
            btn.style.backgroundColor = '#ffcc00';
            btn.style.transform = 'translateX(-50%) scale(1)';
        });

        btn.onclick = handleButtonClick;

        // Keyboard shortcut: Ctrl+Shift+A
        document.addEventListener('keydown', (e) => {
            if (e.ctrlKey && e.shiftKey && e.key === 'A') {
                e.preventDefault();
                handleButtonClick(e);
            }
        });

        document.body.appendChild(btn);
    }

    function handleButtonClick(event) {
        const btn = document.getElementById('archive-button');
        if (btn.disabled) return;

        const currentUrl = location.href;
        const hostAndPath = location.host + location.pathname;

        // Verschiedene Modi basierend auf Modifier-Keys
        if (event.shiftKey) {
            // Shift+Klick: Direkt zu archive.vn ohne Suche
            openArchiveUrl(`https://archive.vn/https://${hostAndPath}`);
            return;
        }

        if (event.altKey) {
            // Alt+Klick: Neue Archivierung erstellen
            openArchiveUrl(`https://archive.vn/submit/?url=${encodeURIComponent(currentUrl)}`);
            return;
        }

        // Normale Suche
        searchForArchivedVersion(btn, hostAndPath);
    }

    function searchForArchivedVersion(btn, hostAndPath) {
        btn.textContent = 'Suche Archiv...';
        btn.disabled = true;

        // Bevorzugte Archive basierend auf letztem Erfolg
        const lastSuccessfulTld = GM_getValue('lastSuccessfulTld', '');
        const sortedTlds = lastSuccessfulTld ?
            [lastSuccessfulTld, ...config.tlds.filter(t => t !== lastSuccessfulTld)] :
            config.tlds;

        tryNextArchive(0, sortedTlds, hostAndPath, btn);
    }

    function tryNextArchive(index, tlds, hostAndPath, btn, retryCount = 0) {
        if (index >= tlds.length) {
            // Fallback: Öffne archive.vn direkt für manuelle Archivierung
            btn.textContent = 'Öffne Archiv...';
            const fallbackUrl = `https://archive.vn/https://${hostAndPath}`;

            setTimeout(() => {
                openArchiveUrl(fallbackUrl);
                btn.textContent = 'Archiv geöffnet';
                btn.disabled = false;

                // Nach 3 Sekunden Button-Text zurücksetzen
                setTimeout(() => {
                    btn.textContent = 'Archiv anzeigen';
                }, 3000);
            }, 500);
            return;
        }

        const tld = tlds[index];
        const archiveUrl = `https://archive.${tld}/https://${hostAndPath}`;

        // Progress anzeigen
        btn.textContent = `Prüfe ${tld}... (${index + 1}/${tlds.length})`;

        GM_xmlhttpRequest({
            method: 'GET',
            url: archiveUrl,
            timeout: config.timeout,
            onload: (res) => {
                if (res.status === 200) {
                    const shortUrl = findValidArchiveUrl(res.responseText, tld);

                    if (shortUrl) {
                        // Erfolg! Merke dir dieses TLD für nächstes Mal
                        GM_setValue('lastSuccessfulTld', tld);
                        openArchiveUrl(shortUrl);
                        btn.textContent = 'Archiv gefunden!';

                        setTimeout(() => {
                            btn.textContent = 'Archiv anzeigen';
                            btn.disabled = false;
                        }, 2000);
                        return;
                    }
                }

                // Nächstes Archive versuchen
                tryNextArchive(index + 1, tlds, hostAndPath, btn);
            },
            onerror: () => {
                // Bei Netzwerkfehler: Retry
                if (retryCount < config.retries) {
                    setTimeout(() => {
                        tryNextArchive(index, tlds, hostAndPath, btn, retryCount + 1);
                    }, 1000);
                } else {
                    // Nach mehreren Fehlern: Nächstes Archive
                    tryNextArchive(index + 1, tlds, hostAndPath, btn);
                }
            },
            ontimeout: () => {
                // Timeout: Nächstes Archive versuchen
                tryNextArchive(index + 1, tlds, hostAndPath, btn);
            }
        });
    }

    function findValidArchiveUrl(responseText, tld) {
        const regex = new RegExp(`https:\\/\\/archive\\.${tld}\\/([a-zA-Z0-9]{3,6})`, 'g');
        const allMatches = [...responseText.matchAll(regex)];

        const valid = allMatches.find(match => {
            const suffix = match[1];
            const invalidSuffixes = ['www', 'https', 'search', 'submit', 'help', 'api'];
            return !invalidSuffixes.includes(suffix.toLowerCase());
        });

        return valid ? valid[0] : null;
    }

    function openArchiveUrl(url) {
        if (window.innerWidth < 600 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
            // Mobile: In gleichem Tab öffnen
            window.location.href = url;
        } else {
            // Desktop: In neuem Tab öffnen
            window.open(url, '_blank', 'noopener,noreferrer');
        }
    }

    // CSS für bessere Animation
    const style = document.createElement('style');
    style.textContent = `
        @keyframes archiveButtonPulse {
            0% { transform: translateX(-50%) scale(1); }
            50% { transform: translateX(-50%) scale(1.1); }
            100% { transform: translateX(-50%) scale(1); }
        }

        #archive-button:active {
            animation: archiveButtonPulse 0.3s ease;
        }

        #archive-button:disabled {
            opacity: 0.7;
            cursor: not-allowed !important;
        }
    `;
    document.head.appendChild(style);
})();

@tarnkaepple
Habs nochmal kopiert. Du weißt doch, Scroll-Funktion extrem schwierig!
:laughing:

schade, habe über tampermonkey das script auf mehreren seiten getestet aber es wird kein button angezeigt um weitergeleitet zu werden

   };

    window.addEventListener('load', () => {
        // Nur fortfahren, wenn ein Pfad existiert (nicht nur Domain)
        const path = location.pathname;
        const host = location.hostname;

        // Button nur anzeigen, wenn Pfad weiterführt 
        const isStartseite = (
            path === '/' ||
            path === '' ||
            (host.includes('faz.net') && path === '/aktuell/') ||
            (host.includes('zeit.de') && path === '/index')
        );

→ // Button nur anzeigen, wenn Pfad weiterführt :bangbang: :bangbang: :bangbang:

Was fällt dir auf? :wink:

1 „Gefällt mir“