diff --git a/frontend/src/tools/paywallkiller.jsx b/frontend/src/tools/paywallkiller.jsx index 73d335b..d699b18 100644 --- a/frontend/src/tools/paywallkiller.jsx +++ b/frontend/src/tools/paywallkiller.jsx @@ -8,10 +8,27 @@ const C = { muted: '#6b7280', }; +// Wayback CDX – prüft ob Snapshot existiert (CORS: *) +async function checkWayback(targetUrl) { + try { + const res = await fetch( + `https://web.archive.org/cdx/search/cdx?url=${encodeURIComponent(targetUrl)}&output=json&limit=1&fl=timestamp&filter=statuscode:200&fastLatest=true` + ); + if (!res.ok) return null; + const data = await res.json(); + if (Array.isArray(data) && data.length >= 2 && data[1]?.[0]) { + return `https://web.archive.org/web/${data[1][0]}/${targetUrl}`; + } + } catch {} + return null; +} + export default function PaywallKiller() { - const [inputUrl, setInputUrl] = useState(''); + const [inputUrl, setInputUrl] = useState(''); const [archiveUrl, setArchiveUrl] = useState(''); - const [done, setDone] = useState(false); + // status: idle | checking | archiving | ready | notfound + const [status, setStatus] = useState('idle'); + const [statusMsg, setStatusMsg] = useState(''); const inputRef = useRef(null); function getTargetUrl() { @@ -19,16 +36,57 @@ export default function PaywallKiller() { return url.startsWith('http') ? url : 'https://' + url; } - function handleSearch() { + async function handleSearch() { if (!inputUrl.trim()) return; - setArchiveUrl(`https://archive.ph/newest/${getTargetUrl()}`); - setDone(false); + const targetUrl = getTargetUrl(); + setStatus('checking'); + setStatusMsg('Prüfe ob Archiv existiert...'); + setArchiveUrl(''); + + // Schritt 1: Prüfen ob archive.ph schon einen Snapshot hat + // archive.ph /newest/ leitet weiter wenn gefunden, sonst Suchseite + // Wir nutzen CDX der Wayback Machine als schnelle Vorab-Prüfung + // und bauen immer die archive.ph URL auf + const newestUrl = `https://archive.ph/newest/${targetUrl}`; + + // Parallel: Wayback prüfen (liefert uns Info ob überhaupt archiviert) + // Aber primär: archive.ph direkt versuchen + // Falls "No results" → automatisch archivieren via no-cors submit + + setArchiveUrl(newestUrl); + + // Schritt 2: archive.ph Submit (fire-and-forget, no-cors) + // Das triggert die Archivierung falls noch nicht vorhanden + setStatus('archiving'); + setStatusMsg('Archiviere Artikel (falls noch nicht vorhanden)...'); + + try { + // archive.ph Submit via no-cors – kein Response lesbar aber Request geht raus + const formData = new FormData(); + formData.append('url', targetUrl); + formData.append('anyway', '1'); + fetch('https://archive.ph/submit/', { + method: 'POST', + mode: 'no-cors', + body: formData, + }).catch(() => {}); + } catch {} + + // Schritt 3: 8s warten dann Artikel öffnen + // (archive.ph braucht ~5-15s zum Archivieren) + for (let i = 8; i > 0; i--) { + setStatusMsg(`Archivierung läuft... öffnet in ${i}s`); + await new Promise(r => setTimeout(r, 1000)); + } + + setStatus('ready'); } function handleReset() { setInputUrl(''); setArchiveUrl(''); - setDone(false); + setStatus('idle'); + setStatusMsg(''); setTimeout(() => inputRef.current?.focus(), 50); } @@ -40,10 +98,10 @@ export default function PaywallKiller() { 🔓 PAYWALL-KILLER -
archive.ph · Als PDF speichern
+
archive.ph · Als PDF speichern
- {/* Getestet mit */} -
+ {/* Getestet-Badges */} +
GETESTET MIT {[ { name: 'waz.de', favicon: 'https://www.google.com/s2/favicons?domain=waz.de&sz=16' }, @@ -65,26 +123,42 @@ export default function PaywallKiller() { ref={inputRef} value={inputUrl} onChange={e => setInputUrl(e.target.value)} - onKeyDown={e => e.key === 'Enter' && handleSearch()} + onKeyDown={e => e.key === 'Enter' && status === 'idle' && handleSearch()} placeholder="URL einfügen (Long-Press → Einfügen)" style={{ ...S.inp, width: '100%', boxSizing: 'border-box', marginBottom: 10 }} />
- - {archiveUrl && ( + {status === 'idle' ? ( + + ) : ( )}
+ {/* Lade-Status */} + {(status === 'checking' || status === 'archiving') && ( +
+
+ + {statusMsg} +
+ {status === 'archiving' && ( +
+ archive.ph archiviert den Artikel. Das dauert einen Moment. Anschließend wird er automatisch geöffnet. +
+ )} +
+ )} + {/* Ergebnis */} - {archiveUrl && ( + {status === 'ready' && archiveUrl && (
ARTIKEL ÖFFNEN & ALS PDF SPEICHERN
@@ -107,7 +181,7 @@ export default function PaywallKiller() { 2
- Wenn der Artikel sichtbar ist, als PDF speichern: + Als PDF speichern:
{[ @@ -132,13 +206,13 @@ export default function PaywallKiller() { )} {/* Idle-Info */} - {!archiveUrl && ( + {status === 'idle' && (
SO FUNKTIONIERT ES
{[ ['1', 'URL des gesperrten Artikels einfügen'], - ['2', 'Artikel auf archive.ph öffnen'], - ['3', 'CAPTCHA einmalig lösen (danach dauerhaft gespeichert)'], + ['2', 'Archiv wird automatisch gesucht und erstellt falls nötig'], + ['3', 'Artikel auf archive.ph öffnen – CAPTCHA einmalig lösen'], ['4', 'Über Drucken-Funktion als PDF speichern'], ].map(([num, text]) => (