Freesmth User Blocker

在 freesmth.net 上屏蔽指定用户的帖子

  1. // ==UserScript==
  2. // @name Freesmth User Blocker
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.2
  5. // @description 在 freesmth.net 上屏蔽指定用户的帖子
  6. // @author
  7. // @match https://freesmth.net/*
  8. // @match https://freesmth.uk/*
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // 从存储中加载屏蔽的用户列表
  18. let blockedUsers = GM_getValue('blockedUsers', []);
  19.  
  20. // 处理并修改帖子
  21. function processPost(postElement) {
  22. // 避免重复处理同一帖子
  23. if (postElement.getAttribute('data-processed')) {
  24. return;
  25. }
  26. postElement.setAttribute('data-processed', 'true');
  27.  
  28. // 查找用户名元素
  29. let usernameElement = postElement.querySelector('.PostUser-name .username');
  30. if (!usernameElement) return; // 如果找不到用户名,则跳过此帖子
  31. let username = usernameElement.textContent.trim();
  32.  
  33. // 在用户名后添加或更新“隐藏/显示”按钮
  34. addToggleButton(usernameElement, username);
  35.  
  36. // 检查用户是否被屏蔽
  37. if (blockedUsers.includes(username)) {
  38. // 隐藏帖子内容
  39. hidePostContent(postElement);
  40. // 将按钮文字设置为“显示”
  41. setToggleButtonCaption(usernameElement, '显示');
  42. } else {
  43. // 显示帖子内容
  44. showPostContent(postElement);
  45. // 将按钮文字设置为“隐藏”
  46. setToggleButtonCaption(usernameElement, '隐藏');
  47. }
  48. }
  49.  
  50. // 隐藏帖子内容
  51. function hidePostContent(postElement) {
  52. // 隐藏帖子正文和操作
  53. let postBody = postElement.querySelector('.Post-body');
  54. if (postBody) postBody.style.display = 'none';
  55. let postActions = postElement.querySelector('.Post-actions');
  56. if (postActions) postActions.style.display = 'none';
  57. }
  58.  
  59. // 显示帖子内容
  60. function showPostContent(postElement) {
  61. // 显示帖子正文和操作
  62. let postBody = postElement.querySelector('.Post-body');
  63. if (postBody) postBody.style.display = '';
  64. let postActions = postElement.querySelector('.Post-actions');
  65. if (postActions) postActions.style.display = '';
  66. }
  67.  
  68. // 在用户名后添加或更新“隐藏/显示”按钮
  69. function addToggleButton(usernameElement, username) {
  70. // 检查按钮是否已存在
  71. let h3Element = usernameElement.closest('.PostUser-name');
  72. if (!h3Element) return;
  73.  
  74. let existingButton = h3Element.querySelector('.toggleUserButton');
  75. if (existingButton) {
  76. // 更新事件处理器以确保使用正确的用户名
  77. existingButton.removeEventListener('click', existingButton.handlerReference);
  78. existingButton.handlerReference = function(e) {
  79. e.stopPropagation();
  80. e.preventDefault();
  81. toggleUser(username);
  82. };
  83. existingButton.addEventListener('click', existingButton.handlerReference);
  84. } else {
  85. // 创建按钮
  86. let toggleButton = document.createElement('button');
  87. toggleButton.className = 'toggleUserButton';
  88. toggleButton.style.marginLeft = '5px';
  89.  
  90. toggleButton.handlerReference = function(e) {
  91. e.stopPropagation(); // 阻止事件冒泡
  92. e.preventDefault(); // 阻止默认行为
  93. toggleUser(username);
  94. };
  95. toggleButton.addEventListener('click', toggleButton.handlerReference);
  96.  
  97. // 在用户名后添加按钮
  98. h3Element.appendChild(toggleButton);
  99. }
  100. }
  101.  
  102. // 设置按钮文字
  103. function setToggleButtonCaption(usernameElement, caption) {
  104. let h3Element = usernameElement.closest('.PostUser-name');
  105. if (!h3Element) return;
  106. let toggleButton = h3Element.querySelector('.toggleUserButton');
  107. if (toggleButton) {
  108. toggleButton.textContent = caption;
  109. }
  110. }
  111.  
  112. // 切换用户的屏蔽状态
  113. function toggleUser(username) {
  114. if (blockedUsers.includes(username)) {
  115. // 用户当前被屏蔽,解除屏蔽
  116. blockedUsers = blockedUsers.filter(u => u !== username);
  117. } else {
  118. // 用户未被屏蔽,添加到屏蔽列表
  119. blockedUsers.push(username);
  120. }
  121. GM_setValue('blockedUsers', blockedUsers);
  122. // 重新处理所有帖子以更新显示
  123. processAllPosts();
  124. }
  125.  
  126. // 处理页面上的所有帖子
  127. function processAllPosts() {
  128. let posts = document.querySelectorAll('.PostStream-item .Post');
  129. posts.forEach(function(postElement) {
  130. // 移除处理标记
  131. postElement.removeAttribute('data-processed');
  132. });
  133. // 处理每个帖子
  134. posts.forEach(function(postElement) {
  135. processPost(postElement);
  136. });
  137. }
  138.  
  139. // 初始处理帖子
  140. processAllPosts();
  141.  
  142. // 观察 DOM,处理动态加载的帖子(无限滚动)
  143. const observer = new MutationObserver(function(mutationsList) {
  144. mutationsList.forEach(function(mutation) {
  145. mutation.addedNodes.forEach(function(node) {
  146. if (node.nodeType !== Node.ELEMENT_NODE) return;
  147. let posts = [];
  148. if (node.matches('.PostStream-item .Post')) {
  149. posts.push(node);
  150. } else {
  151. posts = node.querySelectorAll('.PostStream-item .Post');
  152. }
  153. posts.forEach(function(postElement) {
  154. processPost(postElement);
  155. });
  156. });
  157. });
  158. });
  159. observer.observe(document.body, { childList: true, subtree: true });
  160.  
  161. })();