@spedersen2111
// ==UserScript==
// @name Nachrichten aus Archiv lesen
// @namespace N/A
// @version 0.7.0
// @description Findet echten Kurzlink aus archive.vn/.ph/.fo
// @match https://www.spiegel.de/*
// @match https://www.tagesspiegel.de/*
// @match https://www.zeit.de/*
// @match https://www.welt.de/*
// @match https://www.sueddeutsche.de/*
// @match https://www.faz.net/*
// @match https://www.bild.de/*
// @match https://www.heise.de/*
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @connect archive.vn
// @connect archive.ph
// @connect archive.fo
// @connect archive.is
// @connect archive.md
// @connect archive.li
// @connect archive.today
// ==/UserScript==
(function () {
'use strict';
// Konfiguration
const config = {
tlds: ['vn', 'ph', 'fo', 'is', 'md', 'li', 'today'],
timeout: 8000, // 8 Sekunden Timeout pro Archive
retries: 2, // Anzahl Wiederholungen bei Netzwerkfehlern
};
window.addEventListener('load', () => {
// Nur fortfahren, wenn ein Pfad existiert (nicht nur Domain)
const path = location.pathname;
const host = location.hostname;
// Button nur anzeigen, wenn Pfad weiterführt
const isStartseite = (
path === '/' ||
path === '' ||
(host.includes('faz.net') && path === '/aktuell/') ||
(host.includes('zeit.de') && path === '/index')
);
if (isStartseite) return;
setTimeout(() => {
if (document.getElementById('archive-button')) return;
createArchiveButton();
}, 500);
});
function createArchiveButton() {
const btn = document.createElement('button');
btn.id = 'archive-button';
btn.textContent = 'Archiv anzeigen';
btn.title = 'Klick: Archivierte Version suchen\nShift+Klick: Direkt zu archive.vn\nAlt+Klick: Neue Archivierung erstellen';
Object.assign(btn.style, {
position: 'fixed',
bottom: '40px',
left: '75%',
transform: 'translateX(-50%)',
zIndex: '2147483647',
backgroundColor: '#ffcc00',
color: '#000',
fontSize: '16px',
fontWeight: 'bold',
padding: '12px 24px',
border: '2px solid #000',
borderRadius: '10px',
cursor: 'pointer',
boxShadow: '0 4px 8px rgba(0,0,0,0.3)',
transition: 'all 0.2s ease',
fontFamily: 'Arial, sans-serif',
});
// Hover-Effekt
btn.addEventListener('mouseenter', () => {
btn.style.backgroundColor = '#ffd700';
btn.style.transform = 'translateX(-50%) scale(1.05)';
});
btn.addEventListener('mouseleave', () => {
btn.style.backgroundColor = '#ffcc00';
btn.style.transform = 'translateX(-50%) scale(1)';
});
btn.onclick = handleButtonClick;
// Keyboard shortcut: Ctrl+Shift+A
document.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.shiftKey && e.key === 'A') {
e.preventDefault();
handleButtonClick(e);
}
});
document.body.appendChild(btn);
}
function handleButtonClick(event) {
const btn = document.getElementById('archive-button');
if (btn.disabled) return;
const currentUrl = location.href;
const hostAndPath = location.host + location.pathname;
// Verschiedene Modi basierend auf Modifier-Keys
if (event.shiftKey) {
// Shift+Klick: Direkt zu archive.vn ohne Suche
openArchiveUrl(`https://archive.vn/https://${hostAndPath}`);
return;
}
if (event.altKey) {
// Alt+Klick: Neue Archivierung erstellen
openArchiveUrl(`https://archive.vn/submit/?url=${encodeURIComponent(currentUrl)}`);
return;
}
// Normale Suche
searchForArchivedVersion(btn, hostAndPath);
}
function searchForArchivedVersion(btn, hostAndPath) {
btn.textContent = 'Suche Archiv...';
btn.disabled = true;
// Bevorzugte Archive basierend auf letztem Erfolg
const lastSuccessfulTld = GM_getValue('lastSuccessfulTld', '');
const sortedTlds = lastSuccessfulTld ?
[lastSuccessfulTld, ...config.tlds.filter(t => t !== lastSuccessfulTld)] :
config.tlds;
tryNextArchive(0, sortedTlds, hostAndPath, btn);
}
function tryNextArchive(index, tlds, hostAndPath, btn, retryCount = 0) {
if (index >= tlds.length) {
// Fallback: Öffne archive.vn direkt für manuelle Archivierung
btn.textContent = 'Öffne Archiv...';
const fallbackUrl = `https://archive.vn/https://${hostAndPath}`;
setTimeout(() => {
openArchiveUrl(fallbackUrl);
btn.textContent = 'Archiv geöffnet';
btn.disabled = false;
// Nach 3 Sekunden Button-Text zurücksetzen
setTimeout(() => {
btn.textContent = 'Archiv anzeigen';
}, 3000);
}, 500);
return;
}
const tld = tlds[index];
const archiveUrl = `https://archive.${tld}/https://${hostAndPath}`;
// Progress anzeigen
btn.textContent = `Prüfe ${tld}... (${index + 1}/${tlds.length})`;
GM_xmlhttpRequest({
method: 'GET',
url: archiveUrl,
timeout: config.timeout,
onload: (res) => {
if (res.status === 200) {
const shortUrl = findValidArchiveUrl(res.responseText, tld);
if (shortUrl) {
// Erfolg! Merke dir dieses TLD für nächstes Mal
GM_setValue('lastSuccessfulTld', tld);
openArchiveUrl(shortUrl);
btn.textContent = 'Archiv gefunden!';
setTimeout(() => {
btn.textContent = 'Archiv anzeigen';
btn.disabled = false;
}, 2000);
return;
}
}
// Nächstes Archive versuchen
tryNextArchive(index + 1, tlds, hostAndPath, btn);
},
onerror: () => {
// Bei Netzwerkfehler: Retry
if (retryCount < config.retries) {
setTimeout(() => {
tryNextArchive(index, tlds, hostAndPath, btn, retryCount + 1);
}, 1000);
} else {
// Nach mehreren Fehlern: Nächstes Archive
tryNextArchive(index + 1, tlds, hostAndPath, btn);
}
},
ontimeout: () => {
// Timeout: Nächstes Archive versuchen
tryNextArchive(index + 1, tlds, hostAndPath, btn);
}
});
}
function findValidArchiveUrl(responseText, tld) {
const regex = new RegExp(`https:\\/\\/archive\\.${tld}\\/([a-zA-Z0-9]{3,6})`, 'g');
const allMatches = [...responseText.matchAll(regex)];
const valid = allMatches.find(match => {
const suffix = match[1];
const invalidSuffixes = ['www', 'https', 'search', 'submit', 'help', 'api'];
return !invalidSuffixes.includes(suffix.toLowerCase());
});
return valid ? valid[0] : null;
}
function openArchiveUrl(url) {
if (window.innerWidth < 600 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
// Mobile: In gleichem Tab öffnen
window.location.href = url;
} else {
// Desktop: In neuem Tab öffnen
window.open(url, '_blank', 'noopener,noreferrer');
}
}
// CSS für bessere Animation
const style = document.createElement('style');
style.textContent = `
@keyframes archiveButtonPulse {
0% { transform: translateX(-50%) scale(1); }
50% { transform: translateX(-50%) scale(1.1); }
100% { transform: translateX(-50%) scale(1); }
}
#archive-button:active {
animation: archiveButtonPulse 0.3s ease;
}
#archive-button:disabled {
opacity: 0.7;
cursor: not-allowed !important;
}
`;
document.head.appendChild(style);
})();
@tarnkaepple
Habs nochmal kopiert. Du weißt doch, Scroll-Funktion extrem schwierig!
