diff --git a/frontend/src/tools/paywallkiller.jsx b/frontend/src/tools/paywallkiller.jsx
index c34bb82..29f8c0d 100644
--- a/frontend/src/tools/paywallkiller.jsx
+++ b/frontend/src/tools/paywallkiller.jsx
@@ -9,13 +9,15 @@ const C = {
};
export default function PaywallKiller() {
- const [inputUrl, setInputUrl] = useState('');
- const [status, setStatus] = useState('idle');
- const [archiveUrl, setArchiveUrl] = useState('');
- const [captchaDone, setCaptchaDone] = useState(false);
- const [errMsg, setErrMsg] = useState('');
- const [pdfLoading, setPdfLoading] = useState(false);
- const inputRef = useRef(null);
+ const [inputUrl, setInputUrl] = useState('');
+ const [status, setStatus] = useState('idle');
+ const [archiveUrl, setArchiveUrl] = useState('');
+ const [snapshotUrl, setSnapshotUrl] = useState('');
+ const [captchaDone, setCaptchaDone] = useState(false);
+ const [errMsg, setErrMsg] = useState('');
+ const [pdfLoading, setPdfLoading] = useState(false);
+ const inputRef = useRef(null);
+ const snapshotRef = useRef(null);
function getTargetUrl() {
const url = inputUrl.trim();
@@ -26,6 +28,7 @@ export default function PaywallKiller() {
if (!inputUrl.trim()) return;
const aUrl = `https://archive.ph/newest/${getTargetUrl()}`;
setArchiveUrl(aUrl);
+ setSnapshotUrl('');
setStatus('open_archive');
setCaptchaDone(false);
setErrMsg('');
@@ -36,6 +39,8 @@ export default function PaywallKiller() {
}
async function handlePdf() {
+ const urlToUse = snapshotUrl.trim() || archiveUrl;
+ if (!urlToUse) return;
setPdfLoading(true);
setErrMsg('');
try {
@@ -46,7 +51,7 @@ export default function PaywallKiller() {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
- body: JSON.stringify({ archiveUrl }),
+ body: JSON.stringify({ archiveUrl: urlToUse }),
});
if (!res.ok) {
const d = await res.json().catch(() => ({}));
@@ -72,16 +77,18 @@ export default function PaywallKiller() {
setInputUrl('');
setStatus('idle');
setArchiveUrl('');
+ setSnapshotUrl('');
setCaptchaDone(false);
setErrMsg('');
setPdfLoading(false);
setTimeout(() => inputRef.current?.focus(), 50);
}
+ const canPdf = captchaDone && (snapshotUrl.trim().startsWith('https://archive.') || archiveUrl);
+
return (
- {/* Header */}
🔓
@@ -116,83 +123,92 @@ export default function PaywallKiller() {
- {/* Schritt 1: archive.ph öffnen + CAPTCHA */}
{status === 'open_archive' && (
-
-
- 1
- ARCHIVE.PH ÖFFNEN
-
-
-
- Öffne archive.ph im Browser. Falls ein CAPTCHA erscheint: abhaken und warten bis der Artikel vollständig sichtbar ist. Dann zurückkommen und Schritt 2 ausführen.
-
-
-
- 🌐 archive.ph öffnen
-
-
- {/* Checkbox-Bestätigung */}
-
setCaptchaDone(v => !v)}
- style={{ display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer', padding: '10px 12px', background: captchaDone ? `${C.success}15` : 'rgba(255,255,255,0.03)', border: `1px solid ${captchaDone ? C.success + '55' : 'rgba(255,255,255,0.1)'}`, borderRadius: 8 }}>
-
- {captchaDone &&
✓ }
+ <>
+ {/* Schritt 1 */}
+
+
+ 1
+ ARCHIVE.PH ÖFFNEN & CAPTCHA LÖSEN
-
- Artikel ist sichtbar – CAPTCHA gelöst
-
-
-
- )}
+
+ Öffne archive.ph, löse das CAPTCHA, warte bis der Artikel vollständig sichtbar ist.{'\n'}
+ Kopiere dann die URL aus der Adressleiste (sieht aus wie{' '}
+ archive.ph/AbCdE ) und füge sie unten ein.
+
+
+ 🌐 archive.ph öffnen
+
- {/* Schritt 2: PDF erstellen */}
- {status === 'open_archive' && captchaDone && (
-
-
-
2
- PDF ERSTELLEN
+ {/* Snapshot-URL Eingabe */}
+
SNAPSHOT-URL AUS ADRESSLEISTE (optional)
+
setSnapshotUrl(e.target.value)}
+ placeholder="https://archive.ph/AbCdE"
+ style={{ ...S.inp, width: '100%', boxSizing: 'border-box', marginBottom: 12, fontSize: 12 }}
+ />
+
+ {/* Checkbox */}
+
setCaptchaDone(v => !v)}
+ style={{ display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer', padding: '10px 12px', background: captchaDone ? `${C.success}12` : 'rgba(255,255,255,0.03)', border: `1px solid ${captchaDone ? C.success + '55' : 'rgba(255,255,255,0.1)'}`, borderRadius: 8 }}>
+
+ {captchaDone && ✓ }
+
+
+ Artikel ist vollständig sichtbar
+
+
-
- Der Server lädt den Artikel über archive.ph und erstellt ein PDF (15–30 Sekunden).
-
-
- {pdfLoading ? '⏳ PDF wird erstellt...' : '⬇ Als PDF speichern'}
-
- {pdfLoading && (
-
- Seite wird gerendert, bitte warten...
+
+ {/* Schritt 2 – nur wenn Checkbox gesetzt */}
+ {captchaDone && (
+
+
+ 2
+ PDF ERSTELLEN
+
+
+ {snapshotUrl.trim()
+ ? `Nutzt Snapshot-URL: ${snapshotUrl.trim()}`
+ : 'Nutzt: ' + archiveUrl}
+
+
+ {pdfLoading ? '⏳ PDF wird erstellt (15–30s)...' : '⬇ Als PDF speichern'}
+
)}
-
+ >
)}
- {/* Fehler */}
{errMsg && (
⚠️
-
{errMsg}
+
+
{errMsg}
+ {errMsg.includes('CAPTCHA') && (
+
+ 🌐 archive.ph nochmal öffnen
+
+ )}
+
)}
- {/* Idle-Info */}
{status === 'idle' && (
SO FUNKTIONIERT ES
{[
['1', 'URL des gesperrten Artikels einfügen'],
['2', 'archive.ph im Browser öffnen, CAPTCHA einmalig lösen'],
- ['3', 'Bestätigen dass der Artikel sichtbar ist'],
+ ['3', 'Snapshot-URL aus Adressleiste kopieren und einfügen'],
['4', 'PDF automatisch herunterladen'],
].map(([num, text]) => (