Mydealz Nachrichten-Exporter

Exportiert alle Nachrichten aller Kontakte als mbox-Datei

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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;
    }
})();