Zeigt die letzten Kommentare eines Benutzers an
目前為
此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/528796/1586404/MyDealz%20Comment%20Viewer.js
// ==UserScript==
// @name MyDealz Comment Viewer
// @namespace http://tampermonkey.net/
// @version 2.3
// @description Zeigt die letzten Kommentare eines Benutzers an
// @author MD928835
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Globale Funktion definieren
window.viewUserComments = async function(username) {
// SessionStorage für Kommentare leeren
sessionStorage.removeItem('mydealz_comments');
const fetchDealTitle = async (threadId) => {
const query = `
query getThread($filter: IDFilter!) {
thread(threadId: $filter) {
title
}
}`;
try {
const response = await fetch("https://www.mydealz.de/graphql", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query,
variables: { filter: { eq: threadId } }
})
});
const result = await response.json();
return result.data.thread.title || "Titel nicht verfügbar";
} catch (error) {
console.error(`Fehler beim Abrufen des Titels für threadId ${threadId}:`, error);
return "Titel nicht verfügbar";
}
};
try {
// Profilseite abrufen
const response = await fetch(`https://www.mydealz.de/profile/${username}?page=1`);
if (!response.ok) throw new Error(`HTTP Fehler! Status: ${response.status}`);
const html = await response.text();
// Kommentar- und Thread-IDs extrahieren
const pattern = /href=https:\/\/www\.mydealz\.de\/.*?-(\d+)#(?:comment|reply)-(\d+)/g;
const matches_raw = [...html.matchAll(pattern)];
const ids = matches_raw.map(match => ({
threadId: match[1],
commentId: match[2],
url: match[0].replace('href=', '')
}));
// Parallelisierte Anfragen für Kommentare und Titel
const fetchPromises = ids.map(async ({ threadId, commentId, url }) => {
const commentQuery = `
query comment($id: ID!) {
comment(id: $id) {
preparedHtmlContent
createdAt
createdAtTs
}
}`;
try {
const [commentResponse, title] = await Promise.all([
fetch("https://www.mydealz.de/graphql", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: commentQuery,
variables: { id: commentId }
})
}).then(res => res.json()),
fetchDealTitle(threadId)
]);
const commentData = commentResponse?.data?.comment;
if (commentData) {
const comment = commentData.preparedHtmlContent.replace(/]*>/g, '');
const date = new Date(commentData.createdAtTs * 1000)
.toLocaleString('de-DE', {
day: '2-digit',
month: '2-digit',
year: '2-digit',
hour: '2-digit',
minute: '2-digit'
})
.replace(',', '');
return {
html: `<div class="comment-item">
<div class="comment-header">
<a href="${url}" target="_blank" class="comment-title">${title}</a>
<span class="comment-date">${date}</span>
</div>
<div class="comment-content">${comment}</div>
<div class="comment-footer">
<a href="${url}" target="_blank" class="comment-link">Zum Kommentar</a>
</div>
</div>`,
date: commentData.createdAtTs
};
}
return null;
} catch (error) {
console.error(`Fehler beim Abrufen des Kommentars ${commentId}:`, error);
return null;
}
});
// Alle Kommentare abrufen und sortieren
const comments = (await Promise.all(fetchPromises))
.filter(Boolean)
.sort((a, b) => b.date - a.date);
// Popup erstellen und anzeigen
const popup = document.createElement('div');
popup.id = 'comment-popup';
popup.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
max-width: 800px;
max-height: 80vh;
background: white;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
z-index: 10000;
display: flex;
flex-direction: column;
overflow: hidden;
`;
// Header
const header = document.createElement('div');
header.className = 'bubble-button-background';
header.style.cssText = `
padding: 15px;
background: #0277bd;
color: white;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: center;
`;
header.innerHTML = `
<span>Kommentare von ${username}</span>
<button id="close-popup" style="background: none; border: none; color: white; cursor: pointer; font-size: 20px;">×</button>
`;
// Sortieroptionen
const sortOptions = document.createElement('div');
sortOptions.className = 'comment-sorting-options';
sortOptions.style.cssText = `
padding: 10px 15px;
border-bottom: 1px solid #eee;
display: flex;
gap: 10px;
`;
sortOptions.innerHTML = `
<span>Kommentare sortieren nach</span>
<label>
<input type="radio" name="sort" value="all" checked> alle
</label>
<label>
<input type="radio" name="sort" value="chrono"> chronologisch
</label>
<label>
<input type="radio" name="sort" value="thread"> beitragschronologisch
</label>
`;
// Kommentare Container
const commentsContainer = document.createElement('div');
commentsContainer.style.cssText = `
padding: 15px;
overflow-y: auto;
flex-grow: 1;
`;
// Kommentare anzeigen
commentsContainer.innerHTML = comments.map(comment => comment.html).join('<hr style="margin: 15px 0; border: 0; border-top: 1px solid #eee;">');
// Komponenten zusammenfügen
popup.appendChild(header);
popup.appendChild(sortOptions);
popup.appendChild(commentsContainer);
document.body.appendChild(popup);
// Event-Listener für Schließen-Button
document.getElementById('close-popup').addEventListener('click', () => {
document.body.removeChild(popup);
});
// Event-Listener für Sortierung
const sortRadios = sortOptions.querySelectorAll('input[name="sort"]');
sortRadios.forEach(radio => {
radio.addEventListener('change', () => {
const sortValue = radio.value;
let sortedComments;
if (sortValue === 'chrono') {
sortedComments = [...comments].sort((a, b) => b.date - a.date);
} else if (sortValue === 'thread') {
// Hier müsste eine threadbasierte Sortierung implementiert werden
sortedComments = [...comments];
} else {
sortedComments = [...comments];
}
commentsContainer.innerHTML = sortedComments.map(comment => comment.html).join('<hr style="margin: 15px 0; border: 0; border-top: 1px solid #eee;">');
});
});
// Schließen bei Klick außerhalb
document.addEventListener('click', function closePopup(e) {
if (!popup.contains(e.target) && e.target.id !== 'view-comments-btn') {
document.body.removeChild(popup);
document.removeEventListener('click', closePopup);
}
});
// Escape-Taste zum Schließen
document.addEventListener('keydown', function escapeClose(e) {
if (e.key === 'Escape') {
document.body.removeChild(popup);
document.removeEventListener('keydown', escapeClose);
}
});
} catch (error) {
console.error('Fehler beim Abrufen der Kommentare:', error);
alert('Fehler beim Abrufen der Kommentare: ' + error.message);
}
};
// Button zu Benutzerprofilen hinzufügen
const addViewCommentsButton = () => {
const userProfileHeader = document.querySelector('.userProfile-header');
if (userProfileHeader) {
const username = window.location.pathname.split('/').pop();
const buttonContainer = document.createElement('div');
buttonContainer.style.marginTop = '10px';
buttonContainer.innerHTML = `
<button id="view-comments-btn" class="userProfile-actionButton" style="margin-right: 10px;">
Kommentare anzeigen
</button>
`;
userProfileHeader.appendChild(buttonContainer);
document.getElementById('view-comments-btn').addEventListener('click', (e) => {
e.stopPropagation();
viewUserComments(username);
});
}
};
// MutationObserver für dynamisch geladene Inhalte
const observer = new MutationObserver((mutations) => {
if (window.location.pathname.includes('/profile/')) {
addViewCommentsButton();
observer.disconnect();
}
});
// Beobachtung starten
observer.observe(document.body, { childList: true, subtree: true });
// Initiale Prüfung
if (window.location.pathname.includes('/profile/')) {
addViewCommentsButton();
}
})();