Reddit 增強

移除推廣元素和"我們遇到伺服器錯誤..."橫幅

  1. // ==UserScript==
  2. // @name Reddit Enhancement
  3. // @name:zh-CN Reddit 增强
  4. // @name:zh-TW Reddit 增強
  5. // @name:ja Reddit 拡張
  6. // @name:ko Reddit 개선
  7. // @name:fr Amélioration de Reddit
  8. // @name:de Reddit-Erweiterung
  9. // @name:es Mejora de Reddit
  10. // @name:ru Улучшение Reddit
  11. // @name:ar تحسين Reddit
  12. // @name:pt Aprimoramento do Reddit
  13. // @name:it Miglioramento di Reddit
  14. // @description Removes the promotion element and the "We had a server error..." banner
  15. // @description:en Removes the promotion element and the "We had a server error..." banner
  16. // @description:zh-CN 移除推广元素和"我们遇到服务器错误..."横幅
  17. // @description:zh-TW 移除推廣元素和"我們遇到伺服器錯誤..."橫幅
  18. // @description:ja プロモーション要素と"サーバーエラーが発生しました..."バナーを削除
  19. // @description:ko 프로모션 요소와 "서버 오류가 발생했습니다..." 배너 제거
  20. // @description:fr Supprime l'élément promotionnel et la bannière "Nous avons rencontré une erreur serveur..."
  21. // @description:de Entfernt das Werbeelement und das "Wir hatten einen Serverfehler..."-Banner
  22. // @description:es Elimina el elemento promocional y el banner "Tuvimos un error del servidor..."
  23. // @description:ru Удаляет рекламный элемент и баннер "У нас возникла ошибка сервера..."
  24. // @description:ar يزيل العنصر الترويجي وشعار "لقد واجهنا خطأ في الخادم..."
  25. // @description:pt Remove o elemento promocional e a faixa "Tivemos um erro de servidor..."
  26. // @description:it Rimuove l'elemento promozionale e il banner "Abbiamo riscontrato un errore del server..."
  27. // @author aspen138
  28. // @namespace http://tampermonkey.net/
  29. // @version 1.0.8
  30. // @match *://www.reddit.com/*
  31. // @icon data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAQlBMVEVHcEz/RQD/RQD/QgD/RQD/RQD/RQD/RQD/RQD/RQD/////MgD/OgD/s5//z8P/a0T/5d3/VyH/iGr/qJP/mYD/+vcCA1U1AAAACnRSTlMAJP//y5WUn+ElsgVe0gAAAJFJREFUGJVtT1sOwyAMy0JpIa/C2t3/qjNQaT+zkMAmD5sIqLkwl1zpwcEPjsW3ScxMefv9m7u3WVNXdXJ9Q+BKGYRN+62miXmnMvg7WotT8SzE6ZQHHzkTL+HuIv2SKRTWkHCRC5eiJWOCSJvnNgzFWrtQ4iGuY+0wZt0jHFuWeVhPpmpwsf0PR/TaR/x9xv8CYoYGnu4Mr1kAAAAASUVORK5CYII=
  32. // @grant none
  33. // @license MIT
  34. // ==/UserScript==
  35.  
  36.  
  37. //===== hover to show exact time, leave to recover =====
  38. (function() {
  39. // Function to replace the innerText of <time> elements with their datetime attribute
  40. function replaceTimeText(node) {
  41. node.originalText = node.innerText; // Save the original text
  42. node.innerText = node.attributes.datetime.textContent;
  43. }
  44.  
  45. // Function to recover the original innerText of <time> elements
  46. function recoverTimeText(node) {
  47. if (node.originalText !== undefined) {
  48. node.innerText = node.originalText;
  49. }
  50. }
  51.  
  52. // Apply the replacement to all existing <time> elements
  53. const arr = document.evaluate(
  54. "//time", document, null,
  55. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
  56. );
  57.  
  58. for (let i = 0; i < arr.snapshotLength; i++) {
  59. const node = arr.snapshotItem(i);
  60. node.addEventListener("mouseover", () => replaceTimeText(node));
  61. node.addEventListener("mouseout", () => recoverTimeText(node));
  62. }
  63.  
  64. // Mutation observer callback to handle dynamically added <time> elements
  65. function callback(changes, observer) {
  66. for (let change of changes) {
  67. if (change.type == "childList") {
  68. for (let node of change.addedNodes) {
  69. if (node.tagName == "TIME") {
  70. node.addEventListener("mouseover", () => replaceTimeText(node));
  71. node.addEventListener("mouseout", () => recoverTimeText(node));
  72. }
  73. }
  74. }
  75. }
  76. }
  77.  
  78. // Observe changes in the DOM
  79. const body = document.getElementsByTagName("body")[0];
  80. const config = { childList: true, subtree: true };
  81. const observer = new MutationObserver(callback);
  82. observer.observe(body, config);
  83.  
  84. })();
  85.  
  86.  
  87.  
  88.  
  89. //===== hide promotion element and banner =====
  90. (function() {
  91. 'use strict';
  92.  
  93. // Searches through all Shadow DOM roots
  94. function deepQuerySelectorAll(selector) {
  95. const nodes = [];
  96. function searchInNode(node) {
  97. if (node.shadowRoot) {
  98. const matches = node.shadowRoot.querySelectorAll(selector);
  99. if (matches.length > 0) {
  100. nodes.push(...matches);
  101. }
  102. Array.from(node.shadowRoot.children).forEach(searchInNode);
  103. }
  104. Array.from(node.children).forEach(searchInNode);
  105. }
  106. searchInNode(document);
  107. return nodes;
  108. }
  109.  
  110. // Combined removal function for both error banners and promo elements
  111. function removeElements() {
  112. // Remove error banners
  113. const banners = deepQuerySelectorAll('div.banner.error');
  114. banners.forEach(banner => {
  115. banner.remove();
  116. console.log("Server Error Banner has been removed.");
  117. });
  118.  
  119. // Remove promotional elements
  120. const promoSelectors = [
  121. 'a.w-100.block.h-100.cursor-pointer',
  122. 'shreddit-ad-post.promotedlink',
  123. 'shreddit-dynamic-ad-link',
  124. 'shreddit-comments-page-ad.promotedlink'
  125. ];
  126.  
  127. promoSelectors.forEach(selector => {
  128. const promoElements = document.querySelectorAll(selector);
  129. promoElements.forEach(element => {
  130. element.remove();
  131. console.log('Promotion element removed:', selector);
  132. });
  133. });
  134.  
  135. // Hide elements with specific rel attribute
  136. const links = document.querySelectorAll('a');
  137. links.forEach(link => {
  138. if (link.getAttribute('rel') === 'noopener nofollow sponsored') {
  139. link.style.display = 'none';
  140. console.log('Link with rel "noopener nofollow sponsored" hidden');
  141. }
  142. });
  143.  
  144. // Hide element by data-immersive-translate-walked attribute
  145. const immersiveElements = deepQuerySelectorAll('div[data-immersive-translate-walked="de111be1-6c63-482a-9f03-7fc8d0ca3ba2"]');
  146. immersiveElements.forEach(element => {
  147. element.style.display = 'none';
  148. console.log('Element hidden with data-immersive-translate-walked="de111be1-6c63-482a-9f03-7fc8d0ca3ba2"');
  149. });
  150. }
  151.  
  152. // Single MutationObserver for all operations
  153. const observer = new MutationObserver(() => {
  154. removeElements();
  155. });
  156.  
  157. // Start observing changes in the document
  158. observer.observe(document, {
  159. childList: true,
  160. subtree: true
  161. });
  162.  
  163. // Perform initial cleanup when the page loads
  164. if (document.readyState === 'loading') {
  165. window.addEventListener('load', removeElements);
  166. } else {
  167. removeElements();
  168. }
  169. })();

QingJ © 2025

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