Last active
June 5, 2025 15:15
-
-
Save Wikinaut/2237d5fcf9db551e31222f7206a10bbf to your computer and use it in GitHub Desktop.
Get TAGESSPIEGEL Kommentare as text (Greasemonkey Script)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Coral Talk Auto Load All Comments mit Autor, Zeit, Zustimmungen und Download (mit Thread-Erkennung) | |
// @namespace http://tampermonkey.net/ | |
// @version 2.3 | |
// @description Automatisch „weitere Kommentare anzeigen“ klicken mit Autor, Zeit, Zustimmungen und Thread-Einrückung im Download-Text. | |
// @author ChatGPT | |
// @match https://coral.tagesspiegel.de/embed/stream* | |
// @grant none | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
function wait(ms) { | |
return new Promise(resolve => setTimeout(resolve, ms)); | |
} | |
const statusBtn = document.createElement('button'); | |
statusBtn.style.position = 'fixed'; | |
statusBtn.style.top = '10px'; | |
statusBtn.style.right = '10px'; | |
statusBtn.style.padding = '10px 20px'; | |
statusBtn.style.borderRadius = '5px'; | |
statusBtn.style.fontSize = '14px'; | |
statusBtn.style.fontWeight = 'bold'; | |
statusBtn.style.boxShadow = '0 2px 6px rgba(0,0,0,0.3)'; | |
statusBtn.style.zIndex = 9999; | |
statusBtn.style.color = 'white'; | |
statusBtn.style.border = 'none'; | |
statusBtn.style.cursor = 'default'; | |
statusBtn.disabled = true; | |
document.body.appendChild(statusBtn); | |
let blinkInterval; | |
function startLoadingStatus() { | |
statusBtn.textContent = 'Lade Kommentare...'; | |
statusBtn.style.backgroundColor = '#d32f2f'; | |
statusBtn.disabled = true; | |
statusBtn.style.cursor = 'default'; | |
blinkInterval = setInterval(() => { | |
statusBtn.style.opacity = statusBtn.style.opacity === '0.5' ? '1' : '0.5'; | |
}, 600); | |
} | |
function showFinishedStatus(count) { | |
clearInterval(blinkInterval); | |
statusBtn.style.opacity = '1'; | |
statusBtn.textContent = `✅ ${count} Kommentare geladen. Klicke für Textdownload`; | |
statusBtn.style.backgroundColor = '#4caf50'; | |
statusBtn.disabled = false; | |
statusBtn.style.cursor = 'pointer'; | |
} | |
function gatherAllCommentsText() { | |
const commentContainers = document.querySelectorAll('.talk-stream-comment'); | |
let allText = ''; | |
let count = 0; | |
commentContainers.forEach((container) => { | |
// Autor | |
let author = 'Unbekannter Autor'; | |
const header = container.querySelector('.talk-stream-comment-header'); | |
if (header) { | |
const authorSpan = header.querySelector('span'); | |
if (authorSpan && authorSpan.innerText.trim() !== '') { | |
author = authorSpan.innerText.trim(); | |
} | |
} | |
// Zeitpunkt | |
let date = 'Unbekannter Zeitpunkt'; | |
const timeEl = container.querySelector('time'); | |
if (timeEl && timeEl.innerText.trim() !== '') { | |
date = timeEl.innerText.trim(); | |
} else if (header) { | |
const headerText = header.innerText.trim(); | |
const afterAuthor = headerText.replace(author, '').trim(); | |
if (afterAuthor.length > 0) date = afterAuthor; | |
} | |
// Kommentartext | |
const textEl = container.querySelector('.talk-stream-comment-content'); | |
const text = textEl ? textEl.innerText.trim() : ''; | |
// Zustimmung | |
let votes = '0 Zustimmungen'; | |
const voteEls = Array.from(container.querySelectorAll('span, button')).filter(el => | |
el.textContent.toLowerCase().includes('zustimmen') | |
); | |
for (const el of voteEls) { | |
const match = el.textContent.match(/(\d+)/); | |
if (match && match[1]) { | |
votes = match[1] + ' Zustimmungen'; | |
break; | |
} | |
} | |
if (text) { | |
count++; | |
// Prüfe auf @Erwähnung als Zeichen für Antwort | |
const isReply = /^@\S+/.test(text.split('\n')[0].trim()); | |
const prefix = isReply ? '| ' : ''; | |
allText += `${prefix}Kommentar ${count} von ${author} am ${date} (${votes}):\n${prefix}${text.replace(/\n/g, '\n' + prefix)}\n\n---\n\n`; | |
} | |
}); | |
return { text: allText.trim(), count }; | |
} | |
function downloadTextFile(filename, text) { | |
const blob = new Blob([text], {type: 'text/plain;charset=utf-8'}); | |
const url = URL.createObjectURL(blob); | |
const a = document.createElement('a'); | |
a.href = url; | |
a.download = filename; | |
document.body.appendChild(a); | |
a.click(); | |
setTimeout(() => { | |
document.body.removeChild(a); | |
URL.revokeObjectURL(url); | |
}, 0); | |
} | |
statusBtn.addEventListener('click', () => { | |
if (statusBtn.disabled) return; | |
const { text, count } = gatherAllCommentsText(); | |
if (!text) { | |
alert('Keine Kommentare gefunden zum Download.'); | |
return; | |
} | |
const filename = 'Kommentare_Tagesspiegel.txt'; | |
downloadTextFile(filename, text); | |
}); | |
async function clickLoadMoreLoop() { | |
console.log('Starte automatisches Laden aller Kommentare...'); | |
startLoadingStatus(); | |
let attemptsWithoutButton = 0; | |
let noNewCountAttempts = 0; | |
while (true) { | |
const buttons = Array.from(document.querySelectorAll('button')); | |
const button = buttons.find(b => { | |
const text = b.textContent.trim().toLowerCase(); | |
return text.startsWith('weitere kommentare anzeigen') || text.startsWith('alle antworten anzeigen') | |
}); | |
if (button && !button.disabled) { | |
console.log('„weitere Kommentare anzeigen“-Button gefunden, klicke...'); | |
const lastCount = document.querySelectorAll('.talk-stream-comment').length; | |
button.click(); | |
// Warte bis neue Kommentare sichtbar sind oder Timeout (max 10s) | |
const maxWait = 20000; // 10 Sekunden max warten | |
const interval = 5000; // alle 5000 ms prüfen | |
let waited = 0; | |
while (waited < maxWait) { | |
await wait(interval); | |
waited += interval; | |
const currentCount = document.querySelectorAll('.talk-stream-comment').length; | |
if (currentCount > lastCount) { | |
// neue Kommentare da, weiter | |
break; | |
} | |
} | |
noNewCountAttempts = 0; // Reset weil neue Kommentare kamen | |
attemptsWithoutButton = 0; // Reset | |
} else { | |
attemptsWithoutButton++; | |
noNewCountAttempts++; | |
if (attemptsWithoutButton >= 10 || noNewCountAttempts >= 10) { | |
console.log('Kein „weitere Kommentare anzeigen“-Button mehr gefunden oder keine neuen Kommentare, fertig.'); | |
const { count } = gatherAllCommentsText(); | |
showFinishedStatus(count); | |
break; | |
} | |
await wait(2000); | |
} | |
} | |
} | |
window.addEventListener('load', () => { | |
setTimeout(() => { | |
clickLoadMoreLoop(); | |
}, 2000); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment