MyDealz Comment Viewer

Zeigt die letzten Kommentare eines Benutzers an

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greatest.deepsurf.us/scripts/528796/1586409/MyDealz%20Comment%20Viewer.js

  1. // ==UserScript==
  2. // @name MyDealz Comment Viewer
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.5
  5. // @description Zeigt die letzten Kommentare eines Benutzers an
  6. // @author MD928835
  7. // @license MIT
  8. // ==/UserScript==
  9. (function() {
  10. 'use strict';
  11. // Globale Funktion definieren
  12. window.viewUserComments = async function(username) {
  13. // SessionStorage für Kommentare leeren
  14. sessionStorage.removeItem('mydealz_comments');
  15. const fetchDealTitle = async (threadId) => {
  16. const query = `
  17. query getThread($filter: IDFilter!) {
  18. thread(threadId: $filter) {
  19. title
  20. }
  21. }`;
  22. try {
  23. const response = await fetch("https://www.mydealz.de/graphql", {
  24. method: 'POST',
  25. headers: {
  26. 'Content-Type': 'application/json'
  27. },
  28. body: JSON.stringify({
  29. query,
  30. variables: { filter: { eq: threadId } }
  31. })
  32. });
  33. const result = await response.json();
  34. return result.data.thread.title || "Titel nicht verfügbar";
  35. } catch (error) {
  36. console.error(`Fehler beim Abrufen des Titels für threadId ${threadId}:`, error);
  37. return "Titel nicht verfügbar";
  38. }
  39. };
  40. try {
  41. // Profilseite abrufen
  42. const response = await fetch(`https://www.mydealz.de/profile/${username}?page=1`);
  43. if (!response.ok) throw new Error(`HTTP Fehler! Status: ${response.status}`);
  44. const html = await response.text();
  45. // Kommentar- und Thread-IDs extrahieren
  46. const pattern = /href=https:\/\/www\.mydealz\.de\/.*?-(\d+)#(?:comment|reply)-(\d+)/g;
  47. const matches_raw = [...html.matchAll(pattern)];
  48. const ids = matches_raw.map(match => ({
  49. threadId: match[1],
  50. commentId: match[2],
  51. url: match[0].replace('href=', '')
  52. }));
  53.  
  54. // Mutable und isMuted Status abfragen
  55. const query = `query userProfile($username: String) {
  56. user(username: $username) {
  57. mutable isMuted
  58. }
  59. }`;
  60. const userDataResponse = await fetch('/graphql', {
  61. method: 'POST',
  62. headers: {
  63. 'Content-Type': 'application/json'
  64. },
  65. body: JSON.stringify({
  66. query,
  67. variables: { username }
  68. })
  69. });
  70. const userData = await userDataResponse.json();
  71. const { mutable, isMuted } = userData.data.user;
  72.  
  73. // Parallelisierte Anfragen für Kommentare und Titel
  74. const fetchPromises = ids.map(async ({ threadId, commentId, url }) => {
  75. const commentQuery = `
  76. query comment($id: ID!) {
  77. comment(id: $id) {
  78. preparedHtmlContent
  79. createdAt
  80. createdAtTs
  81. }
  82. }`;
  83. try {
  84. const [commentResponse, title] = await Promise.all([
  85. fetch("https://www.mydealz.de/graphql", {
  86. method: 'POST',
  87. headers: {
  88. 'Content-Type': 'application/json'
  89. },
  90. body: JSON.stringify({
  91. query: commentQuery,
  92. variables: { id: commentId }
  93. })
  94. }).then(res => res.json()),
  95. fetchDealTitle(threadId)
  96. ]);
  97. const commentData = commentResponse?.data?.comment;
  98. if (commentData) {
  99. const comment = commentData.preparedHtmlContent.replace(/<img[^>]*>/g, '');
  100. const date = new Date(commentData.createdAtTs * 1000)
  101. .toLocaleString('de-DE', {
  102. day: '2-digit',
  103. month: '2-digit',
  104. year: '2-digit',
  105. hour: '2-digit',
  106. minute: '2-digit'
  107. })
  108. .replace(',', '');
  109. return {
  110. 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}">${commentData.createdAt}</span> <b>${title}</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='${url}' target='_blank'>Zum Kommentar</a></div>`,
  111. title,
  112. comment,
  113. dealId: threadId,
  114. commentId
  115. };
  116. }
  117. } catch (error) {
  118. console.error(`Fehler bei der Verarbeitung von commentId ${commentId}:`, error);
  119. return null;
  120. }
  121. });
  122. const pageResults = (await Promise.all(fetchPromises)).filter(r => r);
  123. // Ergebnisse sicher in sessionStorage speichern
  124. sessionStorage.setItem('mydealz_comments', JSON.stringify(pageResults));
  125. // Popup anzeigen
  126. const resultWindow = window.open("", "Results", "width=1000,height=700,location=no,menubar=no,toolbar=no,status=no,titlebar=no");
  127. if (resultWindow) {
  128. resultWindow.document.write(`
  129. <html>
  130. <head>
  131. <title>${username}s letzte Kommentare</title>
  132. <style>
  133. body { margin: 0; padding: 0; background: #00a000; font-family: Arial, sans-serif; }
  134. .header { background: #00a000; height: 56px; display: flex; align-items: center; justify-content: center; color: white; font-size: 24px; position: relative; }
  135. .logo { height: 40px; position: absolute; left: 20px; }
  136. .sort-options { text-align: center; padding: 10px; }
  137. .comments-container { margin: 20px; }
  138. .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); }
  139. </style>
  140. <script>
  141. function sortComments(type) {
  142. let comments = JSON.parse(sessionStorage.getItem('mydealz_comments'));
  143. if (type === 'all') {
  144. comments.sort((a, b) => b.commentId - a.commentId);
  145. } else {
  146. comments.sort((a, b) => b.dealId === a.dealId ? b.commentId - a.commentId : b.dealId - a.dealId);
  147. }
  148. document.getElementById('comments-container').innerHTML = comments.map(r => r.html).join('');
  149. }
  150. </script>
  151. </head>
  152. <body>
  153. <div class="header">
  154. <img src="https://www.mydealz.de/assets/img/logo/default-light_d4b86.svg" class="logo">
  155. <a href="https://www.mydealz.de/profile/${username}" style="color:white;text-decoration:none" target="_blank">${username}s letzte ${pageResults.length} Kommentare</a>
  156. </div>
  157. <div class="sort-options">
  158. Kommentare sortieren nach
  159. <label><input type="radio" name="sort" checked onclick="sortComments('all')"> alle chronologisch</label>
  160. <label><input type="radio" name="sort" onclick="sortComments('deal')"> beitragschronologisch</label>
  161. </div>
  162. <div id="comments-container" class="comments-container">
  163. ${pageResults.map(r => r.html).join('')}
  164. </div>
  165.  
  166. <script>
  167. // Mute-Funktionalität
  168. let mutable = ${mutable};
  169. let isMuted = ${isMuted};
  170. const username = "${username}";
  171. const muteBtn = document.getElementById('muteBtn');
  172. const muteText = document.getElementById('muteText');
  173. const muteIcon = document.getElementById('muteIcon');
  174. muteBtn.addEventListener('click', function() {
  175. const endpoint = isMuted ? "/profile/" + username + "/unmute" : "/profile/" + username + "/mute";
  176.  
  177. fetch(endpoint, {
  178. method: 'POST',
  179. headers: {
  180. 'X-Request-Type': 'application/vnd.pepper.v1+json',
  181. 'X-Requested-With': 'XMLHttpRequest',
  182. 'X-Pepper-Txn': 'user.profile.overview',
  183. 'X-XSRF-TOKEN': document.cookie.split('xsrf_t=')[1]?.split(';')[0]?.replace(/"/g, '')
  184. }
  185. })
  186. .then(response => response.json())
  187. .then(data => {
  188. if (data.status === 'success') {
  189. isMuted = !isMuted;
  190. muteText.textContent = username + ' ' + (isMuted ? 'nicht mehr stumm schalten' : 'stumm schalten');
  191. muteIcon.setAttribute('xlink:href', '/assets/img/ico_632f5.svg#' + (isMuted ? 'mute' : 'unmute'));
  192. }
  193. })
  194. .catch(error => console.error('Fehler:', error));
  195. });
  196. </script>
  197. </body>
  198. </html>`);
  199. resultWindow.document.close();
  200. resultWindow.focus();
  201. } else {
  202. alert("Popup blockiert!");
  203. }
  204. } catch (error) {
  205. console.error("Fehler:", error);
  206. alert(`Fehler: ${error.message}`);
  207. }
  208. };
  209. })();
  210.