diff --git a/backend/src/tools/paywallkiller/routes.js b/backend/src/tools/paywallkiller/routes.js index 76004f8..c2b4cf2 100644 --- a/backend/src/tools/paywallkiller/routes.js +++ b/backend/src/tools/paywallkiller/routes.js @@ -55,9 +55,11 @@ router.get('/cdx', authenticate, async (req, res) => { }); // ── POST /api/tools/paywallkiller/pdf ───────────────────────────────────── +// Immer Wayback-URL verwenden – Originalseite hat server-seitige Paywall router.post('/pdf', authenticate, async (req, res) => { const { originalUrl, archiveUrl } = req.body; - const targetUrl = originalUrl || archiveUrl; + // archiveUrl (Wayback) bevorzugen – hat vollen Text ohne server-seitige Paywall + const targetUrl = archiveUrl || originalUrl; if (!targetUrl || typeof targetUrl !== 'string') return res.status(400).json({ error: 'URL fehlt' }); const tmpFile = path.join('/tmp', `pwk_${crypto.randomBytes(8).toString('hex')}.pdf`); @@ -86,68 +88,36 @@ router.post('/pdf', authenticate, async (req, res) => { await page.setViewport({ width: 1280, height: 900 }); await page.goto(targetUrl, { waitUntil: 'networkidle0', timeout: 30000 }); - // Paywall-Elemente per JavaScript entfernen (effektiver als reines CSS) + // UI-Störelemente entfernen (Wayback-Toolbar, Cookie-Banner, Werbung) + // Der Artikel-Text ist im Wayback-Snapshot vollständig vorhanden await page.evaluate(() => { - // Selektoren für Paywall/Overlay-Elemente - const selectors = [ - // Generisch - '[class*="paywall"]', '[class*="Paywall"]', '[id*="paywall"]', - '[class*="piano"]', '[class*="Piano"]', '[id*="piano"]', - '[class*="subscription-wall"]', '[class*="subscriptionWall"]', - '[class*="overlay"]', '[class*="modal-backdrop"]', - // Cookie/Consent - '[class*="cookie-banner"]', '[class*="cookieBanner"]', - '[class*="consent"]', '[id*="consent"]', - '#usercentrics-root', '.uc-banner', + const remove = [ + // Wayback Machine Toolbar + '#wm-ipp-base', '#wm-ipp', '#donato', '#wm-ipp-print', + // Cookie/Consent Banner + '#usercentrics-root', '.uc-banner', '#usercentrics-cmp-ui', '#onetrust-consent-sdk', '.onetrust-pc-dark-filter', - // Piano/TP - '.tp-modal', '.tp-backdrop', '#tp-container', '.tp-active', - // Funke/WAZ spezifisch - '.funke-piano', '.piano-checkout', '.article__paywall', - '[data-piano-inline]', '[data-tp-content]', + '[id*="cookie"]', '[class*="cookie-banner"]', '[class*="cookieBanner"]', + '[class*="consent-banner"]', '[id*="consent-banner"]', + // Sticky Header/Footer + 'header[class*="sticky"]', '[class*="sticky-header"]', + '[class*="stickyHeader"]', '[class*="fixed-header"]', // Werbung - '[id^="ad-"]', '[class*="advertisement"]', - // Wayback toolbar - '#wm-ipp-base', '#wm-ipp', '#donato', + '[class*="advertisement"]', '[class*="adslot"]', '[id^="div-gpt-ad"]', + // Newsletter-Popup, Abo-Hinweise (nicht die Paywall selbst) + '[class*="newsletter"]', '[class*="teaser-abo"]', ]; - - // Elemente entfernen - selectors.forEach(sel => { - try { - document.querySelectorAll(sel).forEach(el => el.remove()); - } catch {} + remove.forEach(sel => { + try { document.querySelectorAll(sel).forEach(el => el.remove()); } catch {} }); - // body/html overflow und blur zurücksetzen + // body overflow freigeben document.body.style.overflow = 'visible'; document.documentElement.style.overflow = 'visible'; - - // Alle blur-Filter entfernen - document.querySelectorAll('*').forEach(el => { - const style = window.getComputedStyle(el); - if (style.filter && style.filter !== 'none') { - el.style.filter = 'none'; - } - // Versteckte Artikel-Inhalte aufdecken - if (el.getAttribute('aria-hidden') === 'true') { - const tag = el.tagName.toLowerCase(); - if (['p','div','section','article'].includes(tag)) { - el.removeAttribute('aria-hidden'); - } - } - }); - - // max-height Limits auf Artikel entfernen - document.querySelectorAll('article, [class*="article"], [class*="content"]').forEach(el => { - el.style.maxHeight = 'none'; - el.style.overflow = 'visible'; - el.style.webkitMaskImage = 'none'; - el.style.maskImage = 'none'; - }); + document.body.style.height = 'auto'; }); - // Kurz warten damit DOM-Änderungen rendern - await new Promise(r => setTimeout(r, 500)); + await new Promise(r => setTimeout(r, 300)); await page.pdf({ path: tmpFile, format: 'A4', printBackground: true,