Reddit User/Subreddit/Domain Filter

Filter Reddit posts based on the user, subreddit, domain, or post flair name.

  1. // ==UserScript==
  2. // @name Reddit User/Subreddit/Domain Filter
  3. // @namespace RedditUserSubDomainFilter
  4. // @version 1.0.3
  5. // @license GNU AGPLv3
  6. // @description Filter Reddit posts based on the user, subreddit, domain, or post flair name.
  7. // @author jcunews
  8. // @include https://*.reddit.com/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. var filterFlair = JSON.parse(localStorage.filterFlair || "[]"),
  13. filterUser = JSON.parse(localStorage.filterUser || "[]"),
  14. filterSub = JSON.parse(localStorage.filterSub || "[]"),
  15. filterDomain = JSON.parse(localStorage.filterDomain || "[]"),
  16. posts, flair, user, sub, domain, buttonTemplate, button, match, filtered;
  17.  
  18. function doFilter(dontHide) {
  19. posts = Array.prototype.slice.call(document.querySelectorAll(".thing"));
  20. posts.forEach(function(post,i) {
  21. filtered = false;
  22. flair = post.querySelector(".linkflairlabel");
  23. if (flair) {
  24. match = filterFlair.indexOf(flair.title) >= 0;
  25. filtered = filtered || !!match;
  26. button = flair.nextSibling;
  27. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  28. button = buttonTemplate.cloneNode(true);
  29. button.title = "Filter posts with this flair (CTRL+Click to undo)";
  30. button.style.marginLeft = "";
  31. button.setAttribute("type", "flair");
  32. button.setAttribute("value", flair.title);
  33. button.onclick = setFilter;
  34. flair.parentNode.insertBefore(button, flair.nextSibling);
  35. }
  36. button.style.background = match ? "#b0b" : "#c00";
  37. }
  38. user = post.querySelector(".author");
  39. if (user) {
  40. match = filterUser.indexOf(user.textContent) >= 0;
  41. filtered = filtered || !!match;
  42. button = user.nextSibling;
  43. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  44. button = buttonTemplate.cloneNode(true);
  45. button.title = "Filter posts from this user (CTRL+Click to undo)";
  46. button.style.marginLeft = "";
  47. button.setAttribute("type", "user");
  48. button.setAttribute("value", user.textContent);
  49. button.onclick = setFilter;
  50. user.parentNode.insertBefore(button, user.nextSibling);
  51. }
  52. button.style.background = match ? "#b0b" : "#c00";
  53. }
  54. sub = post.querySelector(".subreddit");
  55. if (sub) {
  56. match = filterSub.indexOf(sub.textContent.match(/\/?(.*)/)[1]) >= 0;
  57. filtered = filtered || !!match;
  58. button = sub.nextSibling;
  59. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  60. button = buttonTemplate.cloneNode(true);
  61. button.title = "Filter posts from this subreddit (CTRL+Click to undo)";
  62. button.setAttribute("type", "sub");
  63. button.setAttribute("value", sub.textContent.match(/\/?(.*)/)[1]);
  64. button.onclick = setFilter;
  65. sub.parentNode.insertBefore(button, sub.nextSibling);
  66. }
  67. button.style.background = match ? "#b0b" : "#c00";
  68. }
  69. domain = post.querySelector(".domain");
  70. if (domain) {
  71. match = filterDomain.indexOf(domain.textContent.match(/\((.*)\)/)[1]) >= 0;
  72. filtered = filtered || !!match;
  73. button = domain.nextSibling;
  74. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  75. button = buttonTemplate.cloneNode(true);
  76. button.title = "Filter posts from this domain (CTRL+Click to undo)";
  77. button.setAttribute("type", "domain");
  78. button.setAttribute("value", domain.textContent.match(/\((.*)\)/)[1]);
  79. button.onclick = setFilter;
  80. domain.parentNode.insertBefore(button, domain.nextSibling);
  81. }
  82. button.style.background = match ? "#b0b" : "#c00";
  83. }
  84. if (filtered) {
  85. if (!dontHide) {
  86. post.setAttribute("filtered", "1");
  87. post.style.display = "none";
  88. }
  89. } else {
  90. post.removeAttribute("filtered");
  91. post.style.display = "";
  92. }
  93. });
  94. }
  95.  
  96. function setFilter(ev) {
  97. var value, i;
  98. button = ev.target;
  99. value = button.getAttribute("value");
  100. if (!ev.ctrlKey) {
  101. //add filter
  102. switch (button.getAttribute("type")) {
  103. case "flair":
  104. if (filterFlair.indexOf(value) < 0) {
  105. filterFlair.push(value);
  106. localStorage.filterFlair = JSON.stringify(filterFlair);
  107. }
  108. break;
  109. case "user":
  110. if (filterUser.indexOf(value) < 0) {
  111. filterUser.push(value);
  112. localStorage.filterUser = JSON.stringify(filterUser);
  113. }
  114. break;
  115. case "sub":
  116. if (filterSub.indexOf(value) < 0) {
  117. filterSub.push(value);
  118. localStorage.filterSub = JSON.stringify(filterSub);
  119. }
  120. break;
  121. default: //domain
  122. if (filterDomain.indexOf(value) < 0) {
  123. filterDomain.push(value);
  124. localStorage.filterDomain = JSON.stringify(filterDomain);
  125. }
  126. }
  127. } else {
  128. //remove filter
  129. switch (button.getAttribute("type")) {
  130. case "flair":
  131. i = filterFlair.indexOf(value);
  132. if (i >= 0) {
  133. filterFlair.splice(i, 1);
  134. localStorage.filterFlair = JSON.stringify(filterFlair);
  135. }
  136. break;
  137. case "user":
  138. i = filterUser.indexOf(value);
  139. if (i >= 0) {
  140. filterUser.splice(i, 1);
  141. localStorage.filterUser = JSON.stringify(filterUser);
  142. }
  143. break;
  144. case "sub":
  145. i = filterSub.indexOf(value);
  146. if (i >= 0) {
  147. filterSub.splice(i, 1);
  148. localStorage.filterSub = JSON.stringify(filterSub);
  149. }
  150. break;
  151. default: //domain
  152. i = filterDomain.indexOf(value);
  153. if (i >= 0) {
  154. filterDomain.splice(i, 1);
  155. localStorage.filterDomain = JSON.stringify(filterDomain);
  156. }
  157. }
  158. }
  159. doFilter(ev.ctrlKey);
  160. }
  161.  
  162. function showFiltered() {
  163. posts = Array.prototype.slice.call(document.querySelectorAll(".thing[filtered]"));
  164. posts.forEach(function(post) {
  165. post.style.display = "";
  166. });
  167. }
  168.  
  169. function addLink(ele) {
  170. ele.appendChild(button);
  171. //monitor dynamic post list
  172. if (window.siteTable_organic) {
  173. (new MutationObserver(function(records) {
  174. var newNodes = 0;
  175. records.forEach(function(record) {
  176. if (record.addedNodes) newNodes += record.addedNodes.length;
  177. });
  178. if (newNodes) doFilter();
  179. })).observe(window.siteTable_organic, { childList: true });
  180. }
  181. }
  182.  
  183. if (!document.querySelector(".siteTable")) {
  184. //create button template
  185. buttonTemplate = document.createElement("DIV");
  186. buttonTemplate.textContent = "X";
  187. buttonTemplate.style.cssText = "\
  188. display:inline-block; margin-left:1ex; border-radius:4px; padding:0 .7ex; \
  189. background:#c00; text-align:center; line-height:normal; font-size: x-small; \
  190. font-weight:bold; color:#fff; cursor:pointer";
  191. //filter posts
  192. doFilter();
  193. //add link to show all filtered posts
  194. button = document.createElement("A");
  195. button.textContent = "Show Filtered";
  196. button.title = "Temporarily show filtered posts";
  197. button.style.marginLeft = "2ex";
  198. button.href = "javascript:void(0)";
  199. button.onclick = showFiltered;
  200. if (match = document.querySelector(".tabmenu")) { //old layout
  201. addLink(match);
  202. } else if (match = document.querySelector(".gXMvOl")) { //new layout
  203. setTimeout(addLink, 50, match);
  204. }
  205. }

QingJ © 2025

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