Mydealz User Profil Enhancer

Erweitert die Profilbuttons um zusätzliche Funktionen

目前為 2025-03-03 提交的版本,檢視 最新版本

// ==UserScript==
// @name Mydealz User Profil Enhancer
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Erweitert die Profilbuttons um zusätzliche Funktionen
// @author MD928835
// @license MIT
// @match https://www.mydealz.de/*
// @require https://update.gf.qytechs.cn/scripts/528580/1545878/MyDealz%20Reactions%20Viewer%202025.js
// @grant GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    // CSS zur sofortigen Ausblendung hinzufügen
    const style = document.createElement('style');
    style.textContent = `
      /* Originalen Button sofort ausblenden */
      .popover a.width--all-12.space--mt-2.button:not(.custom-button) {
        display: none !important;
      }

      /* Badges sofort ausblenden */
      .popover .flex.gap-1 {
        visibility: hidden !important;
      }

      /* Neue Buttons normal anzeigen */
      .popover .custom-buttons .button {
        display: flex !important;
      }
    `;
    document.head.appendChild(style);

    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            const popover = document.querySelector('.popover--visible');
            if (popover) {
                setTimeout(() => modifyPopup(popover), 100);
            }
        });
    });

    async function modifyPopup(popover) {
        const profileBtn = popover.querySelector('a.width--all-12.space--mt-2.button');
        if (!profileBtn || popover.querySelector('.custom-buttons')) return;

        const username = profileBtn.href.split('/profile/')[1];
        const container = profileBtn.parentElement;
        container.classList.add('custom-buttons');

        // GraphQL Query für Online-Status und Beitrittsdatum
        const query = `query userProfile($username: String) {
            user(username: $username) {
                joinedAgo isOnline mutable isMuted allowToBeMessaged
            }
        }`;

        try {
            const response = await fetch('/graphql', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    query,
                    variables: {
                        username
                    }
                })
            });
            const data = await response.json();
            const {
                isOnline,
                joinedAgo,
                mutable,
                isMuted,
                allowToBeMessaged
            } = data.data.user;

            // Mitgliedschaftsdauer aktualisieren
            const membershipElement = popover.querySelector('.overflow--wrap-off.size--all-s');
            if (membershipElement) {
                membershipElement.textContent = `Dabei seit ${joinedAgo}`;
            }

            // Zeitangabe von der Profilseite holen
            let lastActivityTime = 'unbekannt';
            try {
                const profileHtml = await fetch(`https://www.mydealz.de/profile/${username}`);
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = await profileHtml.text();
                const timeElement = tempDiv.querySelector('.userProfile-action-item .overflow--wrap-break .mute--text');
                if (timeElement) {
                    lastActivityTime = timeElement.textContent.trim();
                }
            } catch (error) {
                console.error('Fehler beim Abrufen der Profilseite:', error);
            }

            // Badge-Container durch Online-Status ersetzen
            const badgeContainer = popover.querySelector('.flex.gap-1');
            if (badgeContainer) {
                const statusContainer = document.createElement('div');
                // statusContainer.className = 'size--all-s color--text-TranslucentSecondary space--mt-2 space--mb-4';
                statusContainer.className = 'size--all-s space--mt-2 space--mb-4';
                const status = isOnline ? 'ON_line' : 'OFF_line';
                statusContainer.textContent = `${status}, zuletzt aktiv ${lastActivityTime}`;
                badgeContainer.replaceWith(statusContainer);
            }

            // Buttons Container erstellen
            const btnContainer = document.createElement('div');
            btnContainer.className = 'flex flex--grow-1 gap--all-2';
            btnContainer.style.gap = '5px';
            btnContainer.style.width = '100%';

            // Profil Button
            const profileButton = document.createElement('a');
            profileButton.href = `/profile/${username}`;
            profileButton.className = 'flex button button--shape-circle button--type-secondary button--mode-default';
            profileButton.style.flex = '1';
            profileButton.innerHTML = `<svg width="17" height="14" class="icon icon--mail"><use xlink:href="/assets/img/ico_632f5.svg#person"></use></svg><span class="space--ml-2"> Profil </span>`;

            // Nachricht Button
            const messageButton = document.createElement('button');
            messageButton.type = 'button';
            messageButton.className = 'flex button button--shape-circle button--type-secondary button--mode-default';
            messageButton.style.flex = '1';
            messageButton.innerHTML = `<svg width="17" height="14" class="icon icon--mail"><use xlink:href="/assets/img/ico_632f5.svg#mail"></use></svg><span class="space--ml-2"> Nachricht </span>`;

            // Styling für nicht anschreibbar
            if (!allowToBeMessaged) {
                messageButton.style.color = '#e02020';
                messageButton.style.borderColor = '#e02020';
                messageButton.style.cursor = 'not-allowed';
                messageButton.disabled = true;
                messageButton.title = 'Dieser Nutzer möchte keine Nachrichten empfangen';
            }
            if (allowToBeMessaged) {
                messageButton.onclick = async () => {
                    const username = document.querySelector('.popover--visible a[href^="/profile/"]')?.href.split('/profile/')[1];
                    if (!username) return;

                    try {
                        // GET-Request zur Prüfung des Inhalts
                        const response = await fetch(`/profile/messages/${username}`);
                        const html = await response.text();

                        // Prüfen, ob der Username im HTML vorkommt
                        const isSpecificMessagePage = html.includes(`<span class="size--all-l text--b space--mr-1">${username}</span>`);

                        if (isSpecificMessagePage) {
                            // Bei existierendem User direkt zur Nachrichtenseite
                            const win = window.open(`/profile/messages/${username}`, '_blank');

                            if (win) {
                                win.addEventListener('load', () => {
                                    const observer = new MutationObserver((mutations, obs) => {
                                        const sendButton = win.document.querySelector('button[data-t="sendButton"]');
                                        if (sendButton) {
                                            sendButton.click();
                                            obs.disconnect();
                                        }
                                    });

                                    observer.observe(win.document.body, {
                                        childList: true,
                                        subtree: true
                                    });

                                    setTimeout(() => observer.disconnect(), 3000);
                                });
                            }
                        } else {
                            // Bei nicht-existierendem User zur Profilseite
                            const win = window.open(`/profile/${username}`, '_blank');

                            if (win) {
                                win.addEventListener('load', () => {
                                    const observer = new MutationObserver((mutations, obs) => {
                                        const sendButton = win.document.querySelector('button[data-t="sendButton"]');
                                        if (sendButton) {
                                            sendButton.click();
                                            obs.disconnect();
                                        }
                                    });

                                    observer.observe(win.document.body, {
                                        childList: true,
                                        subtree: true
                                    });

                                    setTimeout(() => observer.disconnect(), 3000);
                                });
                            }
                        }
                    } catch (error) {
                        console.error('Fehler beim Prüfen der Nachrichtenseite:', error);
                        window.open(`/profile/${username}`, '_blank');
                    }
                };
            };

            // Buttons hinzufügen
            btnContainer.appendChild(profileButton);
            btnContainer.appendChild(messageButton);

            // Alten Button ersetzen
            profileBtn.replaceWith(btnContainer);

            // Statistikbereich finden und "letzte anzeigen" Link hinzufügen
            setTimeout(() => {
                const kommentareElement = Array.from(popover.querySelectorAll('li.lbox--f.lbox--v-3 .size--all-s'))
                    .find(el => el.textContent.includes('Kommentare'));

                if (kommentareElement) {
                    // "letzte anzeigen" Link erstellen
                    const linkElement = document.createElement('span');
                    linkElement.className = 'showCommentsBtn';
                    linkElement.textContent = 'anzeigen';
                    linkElement.style.backgroundColor = '#e6f7e6';
                    linkElement.style.padding = '0 4px';
                    linkElement.style.borderRadius = '3px';
                    linkElement.style.cursor = 'pointer';
                    linkElement.style.marginLeft = '5px';
                    linkElement.style.fontSize = '14px';

                    // wird später ausgelagert
                    linkElement.onclick = async () => {
                        const CONFIG = {
                            BATCH_SIZE: 5,
                            MAX_COMMENTS_PER_PAGE: 20
                        };

                        // Username aus dem PopUp holen
                        const p = document.querySelector('.popover--visible');
                        const username = p?.querySelector('a[href^="/profile/"]')?.getAttribute('href')?.split('/')[2];
                        if (!username) return;

                        // Progress Bar
                        const progress = document.createElement('div');
                        progress.style.cssText = 'position:fixed;top:0;left:0;height:3px;background:#4CAF50;z-index:9999;';
                        document.body.appendChild(progress);

                        try {
                            const response = await fetch(`https://www.mydealz.de/profile/${username}?page=1`);
                            if (!response.ok) throw new Error(`HTTP error! status:${response.status}`);
                            const html = await response.text();
                            const pattern = /href=https:\/\/www\.mydealz\.de\/.*?-(\d+)#(?:comment|reply)-(\d+)/g;
                            const matches_raw = [...html.matchAll(pattern)];

                            const tempDiv = document.createElement('div');
                            tempDiv.innerHTML = html;
                            const titles = [];
                            tempDiv.querySelectorAll('.userHtml').forEach(item => {
                                if (item.textContent.includes('kommentiert')) {
                                    const strongTag = item.querySelector('strong');
                                    if (strongTag) titles.push(strongTag.textContent);
                                }
                            });

                            const pageResults = [];
                            const commentPromises = matches_raw.map((match, index) =>
                                fetch("https://www.mydealz.de/graphql", {
                                    method: 'POST',
                                    headers: {
                                        'Content-Type': 'application/json'
                                    },
                                    body: JSON.stringify({
                                        query: 'query comment($id: ID!) { comment(id: $id) { preparedHtmlContent createdAt createdAtTs } }',
                                        variables: {
                                            id: match[2]
                                        }
                                    })
                                })
                                .then(res => res.json())
                                .then(data => {
                                    progress.style.width = `${(index / matches_raw.length) * 100}%`;
                                    if (!data?.data?.comment) return null;
                                    const comment = data.data.comment.preparedHtmlContent.replace(/<img[^>]*>/g, '');
                                    const date = new Date(data.data.comment.createdAtTs * 1000)
                                        .toLocaleString('de-DE', {
                                            day: '2-digit',
                                            month: '2-digit',
                                            year: '2-digit',
                                            hour: '2-digit',
                                            minute: '2-digit'
                                        })
                                        .replace(',', '');
                                    const result = {
                                        html: `<div class="comment-card" style="background-color:white;padding:1rem;margin:0.75rem 0;border-radius:8px;box-shadow:0 2px 4px rgba(0,0,0,0.1);"><span title="${date}">${data.data.comment.createdAt}</span> <b>${titles[index]}</b><br>${comment}<br><svg width="15px" height="16px" class="icon icon--comment" style="vertical-align: middle"><use xlink:href="/assets/img/ico_632f5.svg#comment"></use></svg> <a href='${match[0].replace('href=','')}'target='_blank'>Zum Kommentar</a></div>`,
                                        title: titles[index],
                                        comment: comment.replace(/<blockquote>.*?<\/blockquote>/g, ''),
                                        dealId: match[1],
                                        commentId: match[2]
                                    };
                                    pageResults.push(result);
                                    return result;
                                })
                                .catch(() => null)
                            );

                            await Promise.all(commentPromises);

                            const flatResults = pageResults.filter(r => r);
                            flatResults.sort((a, b) => b.commentId - a.commentId);

                            sessionStorage.setItem('mydealz_comments', JSON.stringify(flatResults));

                            // Kommentarfenster
                            const resultWindow = window.open("", "Results", "width=1000,height=700,location=no,menubar=no,toolbar=no,status=no,titlebar=no");
                            if (resultWindow) {
                                // HTML für das Popup mit bedingter Anzeige des Mute/Unmute-Buttons
                                resultWindow.document.write(`
            <html>
            <head>
              <title>Schnorrer oder Nassauer?</title>
              <style>
                body { margin: 0; padding: 0; background: #f5f5f5; font-family: Arial, sans-serif; }
                .header { background: #005293; height: 56px; display: flex; align-items: center; justify-content: center; color: white; font-size: 24px; position: relative; }
                .logo { height: 40px; position: absolute; left: 20px; }
                .sort-options { text-align: center; padding: 10px; }
                .comments-container { margin: 20px; }
                .comment-card { background-color: white; padding: 1rem; margin: 0.75rem 0; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
                .mute-container { display: flex; justify-content: center; margin: 10px 0; }
                .mute-btn {
                  display: inline-flex;
                  align-items: center;
                  padding: 8px 16px;
                  border-radius: 4px;
                  cursor: pointer;
                  background-color: #fff;
                  border: 1px solid #ccc;
                  font-size: 14px;
                  color: #666;
                  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
                }
                .mute-btn:hover {
                  background-color: #f8f8f8;
                }
              </style>
              <script>
                function sortComments(type) {
                  let comments = JSON.parse(sessionStorage.getItem('mydealz_comments'));
                  if (type === 'all') {
                    comments.sort((a, b) => b.commentId - a.commentId);
                  } else {
                    comments.sort((a, b) => b.dealId === a.dealId ? b.commentId - a.commentId : b.dealId - a.dealId);
                  }
                  document.getElementById('comments-container').innerHTML = comments.map(r => r.html).join('');
                }
              </script>
            </head>
            <body>
              <div class="header">
                <img src="https://www.mydealz.de/assets/img/logo/default-light_d4b86.svg" class="logo">
                <a href="https://www.mydealz.de/profile/${username}" style="color:white;text-decoration:none" target="_blank">${username}s letzte ${flatResults.length} Kommentare</a>
              </div>

              <div class="sort-options">
                Kommentare sortieren nach
                <label><input type="radio" name="sort" checked onclick="sortComments('all')"> alle chronologisch</label>
                <label><input type="radio" name="sort" onclick="sortComments('deal')"> beitragschronologisch</label>
              </div>

              <div class="mute-container">
  <button id="muteBtn" class="mute-btn" style="display: ${mutable ? 'inline-flex' : 'none'}">
    <svg width="20" height="20" class="icon" style="margin-right: 8px;">
      <use id="muteIcon" xlink:href="/assets/img/ico_632f5.svg#${isMuted ? 'mute' : 'unmute'}"></use>
    </svg>
    <span id="muteText">${username} ${isMuted ? 'nicht mehr stumm schalten' : 'stumm schalten'}</span>
  </button>
</div>

<div id="comments-container" class="comments-container">${flatResults.map(r => r.html).join('')}</div>

<script>
  // Mute-Funktionalität
  let mutable = ${mutable};
  let isMuted = ${isMuted};
  const username = "${username}"; // Username als Variable definieren
  const muteBtn = document.getElementById('muteBtn');
  const muteText = document.getElementById('muteText');
  const muteIcon = document.getElementById('muteIcon');

  muteBtn.addEventListener('click', function() {
    const endpoint = isMuted ? "/profile/" + username + "/unmute" : "/profile/" + username + "/mute";

    fetch(endpoint, {
      method: 'POST',
      headers: {
        'X-Request-Type': 'application/vnd.pepper.v1+json',
        'X-Requested-With': 'XMLHttpRequest',
        'X-Pepper-Txn': 'user.profile.overview',
        'X-XSRF-TOKEN': document.cookie.split('xsrf_t=')[1]?.split(';')[0]?.replace(/"/g, '')
      }
    })
    .then(response => response.json())
    .then(data => {
      if (data.status === 'success') {
        isMuted = !isMuted;
        muteText.textContent = username + ' ' + (isMuted ? 'nicht mehr stumm schalten' : 'stumm schalten');
        muteIcon.setAttribute('xlink:href', '/assets/img/ico_632f5.svg#' + (isMuted ? 'mute' : 'unmute'));
      }
    })
    .catch(error => console.error('Fehler:', error));
  });
</script>
            </body>
            </html>`);
                                resultWindow.document.close();
                                resultWindow.focus();
                            } else {
                                alert("Popup blockiert!");
                            }

                            progress.remove();
                        } catch (err) {
                            alert(`Fehler: ${err.message}`);
                            progress.remove();
                        }
                    };
                    // Link zum Kommentare-Element hinzufügen
                    kommentareElement.appendChild(document.createTextNode(' '));
                    kommentareElement.appendChild(linkElement);
                }
                const reactionsElement = Array.from(popover.querySelectorAll('li.lbox--f.lbox--v-3 .size--all-s'))
                    .find(el => el.textContent.includes('Reaktionen'));

                if (reactionsElement) {
                    const linkElement = document.createElement('span');
                    linkElement.className = 'showReactionsBtn';
                    linkElement.textContent = 'anzeigen';
                    linkElement.style.backgroundColor = '#e6f7e6';
                    linkElement.style.padding = '0 4px';
                    linkElement.style.borderRadius = '3px';
                    linkElement.style.cursor = 'pointer';
                    linkElement.style.marginLeft = '5px';
                    linkElement.style.fontSize = '14px';

                    linkElement.onclick = () => {
                        const p = document.querySelector('.popover--visible');
                        const username = p?.querySelector('a[href^="/profile/"]')?.getAttribute('href')?.split('/')[2];
                        if (!username) return;
                        viewReactions(username);
                    };

                    reactionsElement.appendChild(document.createTextNode(' '));
                    reactionsElement.appendChild(linkElement);
                }
            }, 500);
        } catch (error) {
            console.error('Fehler:', error);
        }
    }

    observer.observe(document.body, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['class']
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址