feat: /render endpoint bereinigt archive.ph HTML (Banner weg, Links original)

This commit is contained in:
2026-06-12 16:04:41 +02:00
parent 2e89669c9b
commit 5469a17a3f
2 changed files with 230 additions and 162 deletions

View File

@@ -9,11 +9,13 @@ 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 inputRef = useRef(null);
const [inputUrl, setInputUrl] = useState('');
const [snapshotUrl, setSnapshotUrl] = useState('');
const [status, setStatus] = useState('idle'); // idle | step1 | step2
const [archiveUrl, setArchiveUrl] = useState('');
const [captchaDone, setCaptchaDone] = useState(false);
const inputRef = useRef(null);
const snapshotRef = useRef(null);
function getTargetUrl() {
const url = inputUrl.trim();
@@ -22,20 +24,38 @@ export default function PaywallKiller() {
function handleSearch() {
if (!inputUrl.trim()) return;
const aUrl = `https://archive.ph/newest/${getTargetUrl()}`;
setArchiveUrl(aUrl);
setStatus('open_archive');
setArchiveUrl(`https://archive.ph/newest/${getTargetUrl()}`);
setStatus('step1');
setCaptchaDone(false);
setSnapshotUrl('');
}
function handleCaptchaDone() {
setCaptchaDone(true);
setStatus('step2');
setTimeout(() => snapshotRef.current?.focus(), 100);
}
function getRenderUrl() {
const snap = snapshotUrl.trim();
// Snapshot-URL die der User eingefügt hat → über /render bereinigen
if (snap && snap.startsWith('https://archive.')) {
return `/api/tools/paywallkiller/render?url=${encodeURIComponent(snap)}`;
}
return null;
}
function handleReset() {
setInputUrl('');
setSnapshotUrl('');
setStatus('idle');
setArchiveUrl('');
setCaptchaDone(false);
setTimeout(() => inputRef.current?.focus(), 50);
}
const renderUrl = getRenderUrl();
return (
<div style={{ padding: '20px 16px', maxWidth: 640, margin: '0 auto' }}>
@@ -44,7 +64,7 @@ export default function PaywallKiller() {
<span style={{ fontSize: 20 }}>🔓</span>
<span style={{ color: C.accent, fontFamily: 'monospace', fontSize: 13, letterSpacing: 1 }}>PAYWALL-KILLER</span>
</div>
<div style={{ color: C.muted, fontSize: 11, fontFamily: 'monospace' }}>archive.ph · Als PDF speichern</div>
<div style={{ color: C.muted, fontSize: 11, fontFamily: 'monospace' }}>archive.ph · Bereinigt · Als PDF drucken</div>
</div>
{/* URL-Eingabe */}
@@ -73,69 +93,75 @@ export default function PaywallKiller() {
</div>
</div>
{status === 'open_archive' && (
<>
{/* Schritt 1 */}
<div style={{ ...S.card, borderColor: captchaDone ? `${C.success}55` : `${C.accent}55`, marginBottom: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
<span style={{ background: `${C.accent}20`, border: `1px solid ${C.accent}44`, borderRadius: '50%', width: 22, height: 22, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, color: C.accent, fontFamily: 'monospace', flexShrink: 0 }}>1</span>
<span style={{ color: C.accent, fontFamily: 'monospace', fontSize: 12 }}>ARCHIVE.PH ÖFFNEN & CAPTCHA LÖSEN</span>
</div>
<div style={{ color: C.muted, fontSize: 11, fontFamily: 'monospace', lineHeight: 1.7, marginBottom: 12 }}>
Öffne archive.ph und löse das CAPTCHA. Warte bis der vollständige Artikel sichtbar ist, dann zurückkommen und Schritt 2 ausführen.
</div>
<a href={archiveUrl} target="_blank" rel="noreferrer"
style={{ ...S.btn(C.accent), display: 'block', textAlign: 'center', textDecoration: 'none', boxSizing: 'border-box', fontSize: 13, marginBottom: 12 }}>
🌐 archive.ph öffnen
</a>
<div onClick={() => 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 }}>
<div style={{ width: 22, height: 22, borderRadius: 5, flexShrink: 0, background: captchaDone ? C.success : 'transparent', border: `2px solid ${captchaDone ? C.success : 'rgba(255,255,255,0.3)'}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
{captchaDone && <span style={{ color: '#000', fontSize: 14, fontWeight: 'bold' }}></span>}
</div>
<span style={{ color: captchaDone ? C.success : 'rgba(255,255,255,0.6)', fontFamily: 'monospace', fontSize: 12 }}>
Artikel ist vollständig sichtbar
</span>
</div>
{/* Schritt 1: archive.ph öffnen */}
{(status === 'step1' || status === 'step2') && (
<div style={{ ...S.card, borderColor: status === 'step2' ? `${C.success}44` : `${C.accent}55`, marginBottom: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
<span style={{ background: `${C.accent}20`, border: `1px solid ${C.accent}44`, borderRadius: '50%', width: 22, height: 22, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, color: C.accent, fontFamily: 'monospace', flexShrink: 0 }}>1</span>
<span style={{ color: C.accent, fontFamily: 'monospace', fontSize: 12 }}>ARCHIVE.PH ÖFFNEN</span>
{status === 'step2' && <span style={{ color: C.success, fontFamily: 'monospace', fontSize: 10 }}> erledigt</span>}
</div>
{/* Schritt 2 PDF über Browser-Druck */}
{captchaDone && (
<div style={{ ...S.card, borderColor: `${C.success}55`, marginBottom: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
<span style={{ background: `${C.success}20`, border: `1px solid ${C.success}44`, borderRadius: '50%', width: 22, height: 22, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, color: C.success, fontFamily: 'monospace', flexShrink: 0 }}>2</span>
<span style={{ color: C.success, fontFamily: 'monospace', fontSize: 12 }}>ALS PDF SPEICHERN</span>
{status === 'step1' && (
<>
<div style={{ color: C.muted, fontSize: 11, fontFamily: 'monospace', lineHeight: 1.7, marginBottom: 12 }}>
Öffne archive.ph. Falls ein CAPTCHA erscheint: lösen und warten bis der Artikel vollständig sichtbar ist. Dann die <strong style={{ color: 'rgba(255,255,255,0.6)' }}>URL aus der Adressleiste</strong> kopieren sie sieht dann so aus:<br/>
<span style={{ color: C.accent }}>archive.ph/AbCdE</span> oder <span style={{ color: C.accent }}>archive.ph/20260608.../https://...</span>
</div>
<div style={{ color: C.muted, fontSize: 11, fontFamily: 'monospace', lineHeight: 1.7, marginBottom: 14 }}>
Öffne den Artikel nochmal und nutze die <strong style={{ color: 'rgba(255,255,255,0.7)' }}>Drucken-Funktion</strong> deines Browsers um ihn als PDF zu speichern:
</div>
{/* Anleitung */}
{[
['📱', 'Android Chrome', 'Menü (⋮) → Teilen → Drucken → Als PDF speichern'],
['🍎', 'iOS Safari', 'Teilen → Als PDF sichern'],
['💻', 'Desktop', 'Strg+P / Cmd+P → Ziel: Als PDF speichern'],
].map(([icon, label, desc]) => (
<div key={label} style={{ display: 'flex', gap: 10, marginBottom: 8, padding: '8px 10px', background: 'rgba(255,255,255,0.03)', borderRadius: 6, border: '1px solid rgba(255,255,255,0.07)' }}>
<span style={{ fontSize: 16, flexShrink: 0 }}>{icon}</span>
<div>
<div style={{ color: 'rgba(255,255,255,0.7)', fontFamily: 'monospace', fontSize: 11, marginBottom: 2 }}>{label}</div>
<div style={{ color: C.muted, fontFamily: 'monospace', fontSize: 10, lineHeight: 1.5 }}>{desc}</div>
</div>
</div>
))}
<a href={archiveUrl} target="_blank" rel="noreferrer"
style={{ ...S.btn(C.success), display: 'block', textAlign: 'center', textDecoration: 'none', boxSizing: 'border-box', fontSize: 13, marginTop: 4 }}>
🖨 Artikel öffnen Als PDF drucken
style={{ ...S.btn(C.accent), display: 'block', textAlign: 'center', textDecoration: 'none', boxSizing: 'border-box', fontSize: 13, marginBottom: 12 }}>
🌐 archive.ph öffnen
</a>
<button onClick={handleCaptchaDone}
style={{ ...S.btn(C.success), width: '100%', fontSize: 12 }}>
Artikel ist sichtbar weiter
</button>
</>
)}
</div>
)}
{/* Schritt 2: Snapshot-URL einfügen + bereinigt öffnen */}
{status === 'step2' && (
<div style={{ ...S.card, borderColor: `${C.success}55`, marginBottom: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
<span style={{ background: `${C.success}20`, border: `1px solid ${C.success}44`, borderRadius: '50%', width: 22, height: 22, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, color: C.success, fontFamily: 'monospace', flexShrink: 0 }}>2</span>
<span style={{ color: C.success, fontFamily: 'monospace', fontSize: 12 }}>SNAPSHOT-URL EINFÜGEN</span>
</div>
<div style={{ color: C.muted, fontSize: 11, fontFamily: 'monospace', lineHeight: 1.6, marginBottom: 10 }}>
Kopiere die URL aus der Adressleiste von archive.ph und füge sie hier ein:
</div>
<input
ref={snapshotRef}
value={snapshotUrl}
onChange={e => setSnapshotUrl(e.target.value)}
placeholder="https://archive.ph/AbCdE"
style={{ ...S.inp, width: '100%', boxSizing: 'border-box', marginBottom: 12, fontSize: 12 }}
/>
{renderUrl ? (
<>
<a href={renderUrl} target="_blank" rel="noreferrer"
style={{ ...S.btn(C.success), display: 'block', textAlign: 'center', textDecoration: 'none', boxSizing: 'border-box', fontSize: 13, marginBottom: 10 }}>
🧹 Bereinigt öffnen (ohne Banner & Archiv-Links)
</a>
<div style={{ padding: '8px 12px', background: 'rgba(255,255,255,0.02)', borderRadius: 6, border: '1px solid rgba(255,255,255,0.06)' }}>
<div style={{ color: 'rgba(255,255,255,0.4)', fontFamily: 'monospace', fontSize: 10, marginBottom: 4 }}>DANN ALS PDF DRUCKEN</div>
<div style={{ color: C.muted, fontFamily: 'monospace', fontSize: 10, lineHeight: 1.6 }}>
📱 Android: Menü Teilen Drucken Als PDF · Kopf-/Fußzeilen aus{'\n'}
🍎 iOS: Teilen Als PDF sichern{'\n'}
💻 Desktop: Strg+P Als PDF · Kopf-/Fußzeilen aus
</div>
</div>
</>
) : (
<div style={{ color: C.muted, fontSize: 11, fontFamily: 'monospace', opacity: 0.5 }}>
Snapshot-URL oben einfügen um fortzufahren...
</div>
)}
</>
</div>
)}
{status === 'idle' && (
@@ -144,8 +170,8 @@ export default function PaywallKiller() {
{[
['1', 'URL des gesperrten Artikels einfügen'],
['2', 'archive.ph öffnen, CAPTCHA einmalig lösen'],
['3', 'Bestätigen dass der Artikel sichtbar ist'],
['4', 'Über Drucken-Funktion als PDF speichern'],
['3', 'URL aus Adressleiste kopieren und hier einfügen'],
['4', 'Bereinigt öffnen (kein Banner, normale Links) → als PDF drucken'],
].map(([num, text]) => (
<div key={num} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', marginBottom: 8 }}>
<span style={{ background: `${C.accent}20`, border: `1px solid ${C.accent}44`, borderRadius: '50%', width: 20, height: 20, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, color: C.accent, fontFamily: 'monospace', marginTop: 2 }}>{num}</span>