您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Exportiert alle Nachrichten aller Kontakte als mbox-Datei
当前为
// ==UserScript== // @name Mydealz Nachrichten-Exporter // @namespace https://www.mydealz.de/ // @version 1.0 // @description Exportiert alle Nachrichten aller Kontakte als mbox-Datei // @author MD928835 // @match https://www.mydealz.de/profile/messages* // @match https://www.mydealz.de/profile/*/settings* // @license MIT // @grant none // ==/UserScript== (function() { 'use strict'; // Stil für das Popup const style = document.createElement('style'); style.textContent = ` #export-popup { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 0 20px rgba(0,0,0,0.3); z-index: 10000; max-width: 80%; max-height: 80vh; overflow-y: auto; color: #333; } #export-popup h2 { margin-top: 0; border-bottom: 1px solid #ddd; padding-bottom: 10px; } #export-popup .buttons { margin-top: 15px; text-align: right; } #export-popup button { padding: 8px 15px; margin-left: 10px; border-radius: 4px; cursor: pointer; } #export-popup .status { margin-top: 10px; padding: 10px; background-color: #f5f5f5; border-radius: 4px; } #export-popup .progress { margin-top: 10px; height: 20px; background-color: #eee; border-radius: 4px; overflow: hidden; } #export-popup .progress-bar { height: 100%; background-color: #4CAF50; width: 0%; transition: width 0.3s; } #export-popup .log { margin-top: 10px; max-height: 200px; overflow-y: auto; font-family: monospace; font-size: 12px; background-color: #f8f8f8; padding: 10px; border-radius: 4px; white-space: pre-wrap; word-break: break-all; } `; document.head.appendChild(style); // Prüfen, ob wir auf der Einstellungsseite sind if (window.location.href.includes('/settings')) { // Button zum Exportieren der Nachrichten auf der Einstellungsseite hinzufügen const nutzerdatenContainer = document.querySelector('.formList-row .formList-content .iGrid-item'); if (nutzerdatenContainer) { const exportButton = document.createElement('button'); exportButton.type = 'button'; exportButton.className = 'width--all-12 hAlign--all-c button button--shape-circle button--type-secondary button--mode-default'; exportButton.style.marginTop = '10px'; exportButton.innerHTML = '<span class="flex--inline boxAlign-ai--all-c">Nachrichten exportieren</span>'; exportButton.addEventListener('click', function() { window.location.href = 'https://www.mydealz.de/profile/messages'; }); nutzerdatenContainer.appendChild(exportButton); } } // Wenn wir auf der Nachrichtenseite sind, starte den Export else if (window.location.href.includes('/messages')) { // Prüfen, ob wir von der Einstellungsseite kommen if (document.referrer.includes('/settings')) { // Starte den Export automatisch setTimeout(exportAllMessages, 1000); } } async function exportAllMessages() { // Abbruch-Controller für Fetch-Anfragen const controller = new AbortController(); let continueLoading = true; // Popup erstellen const popup = document.createElement('div'); popup.id = 'export-popup'; popup.innerHTML = ` <h2>Alle Nachrichten exportieren</h2> <div class="status">Kontakte werden geladen...</div> <div class="progress"> <div class="progress-bar"></div> </div> <div class="log"></div> <div class="buttons"> <button id="schliessen-button">Schließen</button> <button id="export-button" disabled>Als mbox exportieren</button> </div> `; document.body.appendChild(popup); document.getElementById('schliessen-button').addEventListener('click', () => { popup.remove(); continueLoading = false; controller.abort(); }); const statusElement = popup.querySelector('.status'); const progressBar = popup.querySelector('.progress-bar'); const logElement = popup.querySelector('.log'); const exportButton = document.getElementById('export-button'); // Aktuellen Benutzernamen ermitteln const currentUser = document.querySelector('.navDropDown-avatar').alt.replace("'s Profilbild", ""); // Alle Kontakte laden const contacts = await loadAllContacts(statusElement, progressBar, logElement, controller, continueLoading); if (!continueLoading || contacts.length === 0) { statusElement.textContent = 'Keine Kontakte gefunden oder Export abgebrochen.'; return; } statusElement.textContent = `${contacts.length} Kontakte gefunden. Nachrichten werden geladen...`; // Alle Nachrichten laden const allMessages = []; let processedContacts = 0; for (const contact of contacts) { if (!continueLoading) break; statusElement.textContent = `Lade Nachrichten von ${contact.username} (${processedContacts + 1}/${contacts.length})...`; progressBar.style.width = `${(processedContacts / contacts.length) * 100}%`; logElement.textContent += `Lade Nachrichten von ${contact.username} (ID: ${contact.userId})...\n`; const messages = await loadMessagesForUser(contact.userId, contact.username, currentUser, logElement, controller, continueLoading); allMessages.push(...messages); processedContacts++; // Kurze Pause, um den Server nicht zu überlasten await new Promise(resolve => setTimeout(resolve, 500)); } if (!continueLoading) { statusElement.textContent = 'Export wurde abgebrochen.'; return; } // Export vorbereiten statusElement.textContent = `${allMessages.length} Nachrichten von ${contacts.length} Kontakten geladen. Bereit zum Export.`; progressBar.style.width = '100%'; exportButton.disabled = false; // Export-Funktion exportButton.addEventListener('click', () => { // mbox-Format erstellen const mboxContent = allMessages.map(msg => { return `From ${msg.from} ${msg.date} From: ${msg.from} To: ${msg.to} Date: ${msg.date} Subject: ${msg.subject} ${msg.content} `; }).join('\n'); const blob = new Blob([mboxContent], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `mydealz_alle_nachrichten_${new Date().toISOString().slice(0,10)}.mbox`; a.click(); URL.revokeObjectURL(url); }); } async function loadAllContacts(statusElement, progressBar, logElement, controller, continueLoading) { const contacts = []; let page = 1; let hasMore = true; while (hasMore && continueLoading) { try { statusElement.textContent = `Lade Kontakte Seite ${page}...`; const response = await fetch(`https://www.mydealz.de/conversation/recent/20/${page}`, { headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, signal: controller.signal }); const data = await response.json(); if (data && data.data && data.data.content) { const tempDiv = document.createElement('div'); tempDiv.innerHTML = data.data.content; // Prüfen, ob "Weitere Nachrichten laden" Button vorhanden ist const loadMoreButton = tempDiv.querySelector('.moreConversations button'); hasMore = loadMoreButton !== null; // Kontakte aus der Antwort extrahieren const items = tempDiv.querySelectorAll('li[id^="conversation-"]'); items.forEach(item => { const usernameElement = item.querySelector('.conversationList-senderLine'); if (usernameElement) { const username = usernameElement.textContent.trim(); const userId = item.getAttribute('data-replace')?.match(/\/user\/(\d+)\//)?.[1]; if (username && userId && !contacts.some(c => c.userId === userId)) { contacts.push({ userId, username }); logElement.textContent += `Kontakt gefunden: ${username} (ID: ${userId})\n`; } } }); } else { hasMore = false; } page++; // Kurze Pause, um den Server nicht zu überlasten await new Promise(resolve => setTimeout(resolve, 300)); } catch (error) { if (error.name === 'AbortError') { logElement.textContent += `Export abgebrochen.\n`; return contacts; } console.error('Fehler beim Laden der Kontakte:', error); logElement.textContent += `FEHLER: ${error.message}\n`; hasMore = false; } } return contacts; } async function loadMessagesForUser(userId, username, currentUser, logElement, controller, continueLoading) { const messages = []; let page = 1; let hasMoreMessages = true; while (hasMoreMessages && continueLoading) { try { const url = `https://www.mydealz.de/conversation/user/${userId}/0/${page}`; logElement.textContent += ` Lade Seite ${page}: ${url}\n`; const response = await fetch(url, { headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, signal: controller.signal }); const data = await response.json(); if (data && data.data && data.data.content) { const tempDiv = document.createElement('div'); tempDiv.innerHTML = data.data.content; // Nachrichten aus der Antwort extrahieren const messageElements = tempDiv.querySelectorAll('.cept-message'); if (messageElements.length === 0) { // Keine Nachrichten mehr, Ende erreicht hasMoreMessages = false; } else { // Nachrichten verarbeiten messageElements.forEach(messageElement => { const senderElement = messageElement.querySelector('.button--type-text'); const dateElement = messageElement.querySelector('.mute--text'); const contentElement = messageElement.querySelector('.conversation-content'); if (senderElement && dateElement && contentElement) { const sender = senderElement.textContent.trim(); const dateText = dateElement.textContent.trim(); const content = contentElement.textContent.trim().replace(/\s+/g, ' '); // Datum in mbox-Format konvertieren const dateParts = dateText.match(/(\d{2})\.(\d{2})\.(\d{4})\s+(\d{2}):(\d{2})/); let mboxDate = ''; if (dateParts) { const [_, day, month, year, hours, minutes] = dateParts; const dateObj = new Date(year, month-1, day, hours, minutes); mboxDate = dateObj.toUTCString(); } else { mboxDate = new Date().toUTCString(); // Fallback } // Bestimmen, wer Sender und Empfänger ist const from = sender === currentUser ? `${currentUser}@mydealz.de` : `${sender}@mydealz.de`; const to = sender === currentUser ? `${username}@mydealz.de` : `${currentUser}@mydealz.de`; // Betreff aus den ersten 40 Zeichen der Nachricht const subject = content.substring(0, 40).replace(/\n/g, ' '); messages.push({ from, to, date: mboxDate, subject, content }); } }); // Wenn weniger als 10 Nachrichten zurückkommen, haben wir das Ende erreicht if (messageElements.length < 10) { hasMoreMessages = false; } } } else { // Keine Daten mehr oder Fehler in der Antwort hasMoreMessages = false; } page++; // Kurze Pause, um den Server nicht zu überlasten await new Promise(resolve => setTimeout(resolve, 300)); } catch (error) { if (error.name === 'AbortError') { logElement.textContent += ` Export abgebrochen.\n`; return messages; } console.error('Fehler beim Laden der Nachrichten:', error); logElement.textContent += ` FEHLER: ${error.message}\n`; hasMoreMessages = false; } } logElement.textContent += ` ${messages.length} Nachrichten von ${username} geladen\n`; return messages; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址