import { useState, useRef } from 'react'; import { S, api } from '../lib.js'; // ── Farben ───────────────────────────────────────────────────────────────── const C = { accent: '#f59e0b', success: '#4ade80', error: '#f87171', muted: 'rgba(255,255,255,0.4)', dim: 'rgba(255,255,255,0.07)', }; // ── Hilfsfunktion: Domain aus URL extrahieren ────────────────────────────── function getDomain(url) { try { return new URL(url).hostname.replace(/^www\./, ''); } catch { return url; } } export default function PaywallKiller() { const [inputUrl, setInputUrl] = useState(''); const [status, setStatus] = useState('idle'); // idle | checking | found | notfound | pdf | error const [archiveUrl, setArchiveUrl] = useState(''); const [archiveType, setArchiveType] = useState(''); const [errMsg, setErrMsg] = useState(''); const [pdfLoading, setPdfLoading] = useState(false); const inputRef = useRef(null); // ── URL prüfen ──────────────────────────────────────────────────────────── async function handleCheck() { const url = inputUrl.trim(); if (!url) return; setStatus('checking'); setErrMsg(''); setArchiveUrl(''); setArchiveType(''); try { const data = await api('/tools/paywallkiller/check', { body: { url } }); setArchiveUrl(data.archiveUrl); setArchiveType(data.type); setStatus('found'); } catch (err) { if (err.message && err.message.includes('Kein Archiv')) { setStatus('notfound'); } else { setErrMsg(err.message || 'Unbekannter Fehler'); setStatus('error'); } } } // ── PDF herunterladen ───────────────────────────────────────────────────── async function handlePdf() { setPdfLoading(true); try { const token = localStorage.getItem('sk_token'); const res = await fetch('/api/tools/paywallkiller/pdf', { method: 'POST', headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), }, body: JSON.stringify({ archiveUrl }), }); if (!res.ok) { const data = await res.json().catch(() => ({})); throw new Error(data.error || 'PDF-Fehler'); } const blob = await res.blob(); const objUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = objUrl; a.download = 'archiv_' + Date.now() + '.pdf'; document.body.appendChild(a); a.click(); document.body.removeChild(a); setTimeout(() => URL.revokeObjectURL(objUrl), 5000); } catch (err) { setErrMsg(err.message || 'PDF konnte nicht erstellt werden'); setStatus('error'); } finally { setPdfLoading(false); } } // ── Reset ───────────────────────────────────────────────────────────────── function handleReset() { setInputUrl(''); setStatus('idle'); setArchiveUrl(''); setArchiveType(''); setErrMsg(''); setPdfLoading(false); setTimeout(() => inputRef.current?.focus(), 50); } // ── Paste aus Clipboard ─────────────────────────────────────────────────── async function handlePaste() { try { const text = await navigator.clipboard.readText(); if (text) setInputUrl(text.trim()); } catch { inputRef.current?.focus(); } } const isChecking = status === 'checking'; const isFound = status === 'found'; const isNotFound = status === 'notfound'; const isError = status === 'error'; return (
{/* Header */}
🔓 PAYWALL-KILLER
Artikel über archive.is abrufen · Als PDF speichern
{/* URL-Eingabe */}
ARTIKEL-URL
setInputUrl(e.target.value)} onKeyDown={e => e.key === 'Enter' && !isChecking && handleCheck()} placeholder="https://www.zeitung.de/artikel/..." style={{ ...S.inp, flex: 1 }} />
{(isFound || isNotFound || isError) && ( )}
{/* Gefunden */} {isFound && (
Archiv gefunden {archiveType === 'newest' ? 'neuestes' : 'ältestes'} Archiv
{/* Archive-URL anzeigen */}
{archiveUrl}
{/* Aktions-Buttons */}
🌐 Im Browser öffnen
{/* PDF-Hinweis */} {pdfLoading && (
Seite wird geladen und als PDF gerendert. Das kann 15–30 Sekunden dauern...
)}
)} {/* Kein Archiv */} {isNotFound && (
📭 Kein Archiv gefunden
Für {getDomain(inputUrl)} existiert kein Eintrag auf archive.is. Der Artikel wurde möglicherweise noch nie archiviert.
🔗 Manuell auf archive.is prüfen
)} {/* Fehler */} {isError && (
⚠️ {errMsg}
)} {/* Info-Sektion */} {status === 'idle' && (
WIE ES FUNKTIONIERT
{[ ['1', 'URL des gesperrten Artikels einfügen'], ['2', 'Archiv auf archive.is suchen (newest → oldest)'], ['3', 'Archivierte Version im Browser öffnen oder als PDF speichern'], ].map(([num, text]) => (
{num} {text}
))}
)}
); }