GreasyFork Bullshit Filter - for TS Citrus Gfork

Hides scripts for popular browser games and social networks as well as scripts that use "foreign" characters in descriptions. Applies to posts in Forum too.

  1. // ==UserScript==
  2. // @name GreasyFork Bullshit Filter - for TS Citrus Gfork
  3. // @namespace darkred
  4. // @version 2021.3.31
  5. // @description Hides scripts for popular browser games and social networks as well as scripts that use "foreign" characters in descriptions. Applies to posts in Forum too.
  6. // @author kuehlschrank, darkred, valacar, Graphen
  7. // @license MIT
  8. // @icon https://raw.githubusercontent.com/darkred/Userscripts/master/GreasyFork_Bullshit_Filter_-_for_TS_Citrus_Gfork/large.png
  9. // @include /^https:\/\/(greasy|sleazy)fork\.org\/(.*\/)?(scripts|discussions|users).*$/
  10. // @exclude /^https:\/\/(greasy|sleazy)fork\.org\/(.*\/)?(scripts\/[\w-]+\/feedback|discussions\/[\d]+|users\/.*\/conversations.*)$/
  11. // @grant none
  12. // @run-at document-idle
  13. // This is a modified version of this script (http://userscripts-mirror.org/scripts/show/97145) by kuehlschrank.
  14. // Thanks a lot to:
  15. // - kuehlschrank for making another great script,
  16. // - valacar for the refactoring,
  17. // - Graphen for the 'Non-Latin' regex.
  18. // @supportURL https://github.com/darkred/Userscripts/issues
  19. // ==/UserScript==
  20.  
  21.  
  22. (function() {
  23.  
  24. const DEBUGGING = 0;
  25.  
  26. const filters = {
  27. 'Non-ASCII': /[^\x00-\x7F\s]+/,
  28. 'Non-Latin': /[^\u0000-\u024F\u2000-\u214F\s]+/,
  29. 'Games': /Aimbot|AntiGame|Agar|agar\.io|alis\.io|angel\.io|ExtencionRipXChetoMalo|AposBot|DFxLite|ZTx-Lite|AposFeedingBot|AposLoader|Balz|Blah Blah|Orc Clan Script|Astro\s*Empires|^\s*Attack|^\s*Battle|BiteFight|Blood\s*Wars|Bloble|Bonk|Bots|Bots4|Brawler|\bBvS\b|Business\s*Tycoon|Castle\s*Age|City\s*Ville|chopcoin\.io|Comunio|Conquer\s*Club|CosmoPulse|cursors\.io|Dark\s*Orbit|Dead\s*Frontier|Diep\.io|\bDOA\b|doblons\.io|DotD|Dossergame|Dragons\s*of\s*Atlantis|driftin\.io|Dugout|\bDS[a-z]+\n|elites\.io|Empire\s*Board|eRep(ublik)?|Epicmafia|Epic.*War|ExoPlanet|Falcon Tools|Feuerwache|Farming|FarmVille|Fightinfo|Frontier\s*Ville|Ghost\s*Trapper|Gladiatus|Goalline|Gondal|gota\.io|Grepolis|Hobopolis|\bhwm(\b|_)|Ikariam|\bIT2\b|Jellyneo|Kapi\s*Hospital|Kings\s*Age|Kingdoms?\s*of|knastv(o|oe)gel|Knight\s*Fight|\b(Power)?KoC(Atta?ck)?\b|\bKOL\b|Kongregate|Krunker|Last\s*Emperor|Legends?\s*of|Light\s*Rising|lite\.ext\.io|Lockerz|\bLoU\b|Mafia\s*(Wars|Mofo)|Menelgame|Mob\s*Wars|Mouse\s*Hunt|Molehill\s*Empire|MooMoo|MyFreeFarm|narwhale\.io|Neopets|NeoQuest|Nemexia|\bOGame\b|Ogar(io)?|Pardus|Pennergame|Pigskin\s*Empire|PlayerScripts|pokeradar\.io|Popmundo|Po?we?r\s*(Bot|Tools)|PsicoTSI|Ravenwood|Schulterglatze|Skribbl|slither\.io|slitherplus\.io|slitheriogameplay|SpaceWars|splix\.io|Survivio|\bSW_[a-z]+\n|\bSnP\b|The\s*Crims|The\s*West|torto\.io|Travian|Treasure\s*Isl(and|e)|Tribal\s*Wars|TW.?PRO|Vampire\s*Wars|vertix\.io|War\s*of\s*Ninja|World\s*of\s*Tanks|West\s*Wars|wings\.io|\bWoD\b|World\s*of\s*Dungeons|wtf\s*battles|Wurzelimperium|Yohoho|Zombs/iu,
  30. 'Social Networks': /Face\s*book|Google(\+| Plus)|\bHabbo|Kaskus|\bLepra|Leprosorium|MySpace|meinVZ|odnoklassniki|Одноклассники|Orkut|sch(ue|ü)ler(VZ|\.cc)?|studiVZ|Unfriend|Valenth|VK|vkontakte|ВКонтакте|Qzone|Twitter|TweetDeck/iu,
  31. 'Clutter': /^\s*(.{1,3})\1+\n|^\s*(.+?)\n+\2\n*$|^\s*.{1,5}\n|do\s*n('|o)?t (install|download)|nicht installieren|(just )?(\ban? |\b)test(ing|s|\d|\b)|^\s*.{0,4}test.{0,4}\n|\ntest(ing)?\s*|^\s*(\{@|Smolka|Hacks)|\[\d{4,5}\]|free\s*download|theme|(night|dark) ?(mode)?/iu
  32. };
  33.  
  34. const commonCss = `
  35. .filter-status {
  36. margin-left: 6px;
  37. position: fixed;
  38. top: calc(0%);
  39. left: calc(13.5%);
  40. color: #787878;
  41. }
  42. .filter-switches {
  43. display: none;
  44. }
  45. *:hover > .filter-switches {
  46. display: block !important;
  47. position: fixed;
  48. top: calc(1.7%);
  49. left: calc(14%);
  50. }
  51. .filter-on,
  52. .filter-off {
  53. display: block !important;
  54. width: 105px;
  55. }
  56. .filter-switches a {
  57. text-decoration: none !important;
  58. color: inherit;
  59. cursor: pointer;
  60. }
  61. .filter-switches a {
  62. margin-left: 8px;
  63. padding: 0 4px;
  64. }
  65. a.filter-on {
  66. background-color: #ea6e6e;
  67. color: #333333;
  68. text-decoration: line-through !important;
  69. }
  70. a.filter-off {
  71. background-color: #6da46b;
  72. color: #333333;
  73. }
  74. `;
  75.  
  76. const isOnForum = /discussions|feedback/.test(window.location.href);
  77.  
  78. const site = {};
  79. if (isOnForum) {
  80. site.css = '.discussion-list-item.filtered { display: none; } .filter-on, .filter-off { color: black; } ' + commonCss;
  81. site.cssDebug = '.discussion-list-item.filtered { background-color: khaki !important; } ' + commonCss;
  82. site.filterStatusLocation = '#main-header';
  83. site.itemsToCheck = '.discussion-list-item';
  84. site.itemType = 'discussions';
  85. site.removeFilter = function(el) {
  86. el.classList.remove('filtered');
  87. };
  88. site.applyFilter = function(el, activeFilter) {
  89. let temp = el.children[1].innerText;
  90. if(temp && temp.match(activeFilter)) {
  91. el.classList.add('filtered');
  92. return true;
  93. }
  94. return false;
  95. };
  96. } else { // Is in script listings
  97. site.css = 'tr.filtered, li.filtered { display: none; } ' + commonCss;
  98. site.cssDebug = 'tr.filtered td, li.filtered { background-color: khaki !important; } ' + commonCss;
  99. site.filterStatusLocation = '#main-header';
  100. site.itemsToCheck = `tbody > tr > td > div.thetitle,
  101. #browse-script-list > li`;
  102. site.itemType = 'scripts';
  103. site.removeFilter = function(el) {
  104. if (window.location.href.indexOf('/libraries') === -1) {
  105. el.parentNode.parentNode.classList.remove('filtered');
  106. } else {
  107. el.classList.remove('filtered');
  108. }
  109. };
  110. site.applyFilter = function(el, activeFilter) {
  111. if (window.location.href.indexOf('/libraries') === -1) {
  112. var temp = el.parentNode.firstChild.firstChild.textContent + ' ' + el.parentNode.lastChild.textContent; // store script's name and description (with a space between) to variable 'temp'
  113. } else {
  114. temp = el.getAttribute('data-script-name') + ' ' + el.firstElementChild.firstElementChild.children[3].innerText;
  115. }
  116. if (temp && temp.match(activeFilter)) {
  117. if (window.location.href.indexOf('/libraries') === -1) {
  118. el.parentNode.parentNode.classList.add('filtered');
  119. } else {
  120. el.classList.add('filtered');
  121. }
  122. return true;
  123. }
  124. return false;
  125. };
  126. }
  127.  
  128. insertStyle();
  129. insertStatus();
  130. filterScripts();
  131. insertSwitches();
  132.  
  133.  
  134. if (!isOnForum){
  135.  
  136. const target = document.querySelector('#script-table > tbody:nth-child(2)');
  137. const observer = new MutationObserver((mutations) => {
  138. insertStyle();
  139. if (!document.querySelector('.filter-status')){
  140. insertStatus();
  141. }
  142. filterScripts();
  143. if (!document.querySelector('.filter-switches')){
  144. insertSwitches();
  145. }
  146. }),
  147. config = {
  148. childList: true,
  149. subtree: true,
  150. };
  151. observer.observe(target, config);
  152.  
  153. }
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160. function insertStyle() {
  161. const style = document.createElement('style');
  162. style.textContent = DEBUGGING ? site.cssDebug : site.css;
  163. style.type = 'text/css';
  164. document.head.appendChild(style);
  165. }
  166.  
  167. function insertStatus() {
  168. const p = document.querySelector(site.filterStatusLocation);
  169. if (p) {
  170. const status = document.createElement('span');
  171. status.className = 'filter-status';
  172. p.appendChild(status);
  173. }
  174. }
  175.  
  176. function filterScripts() {
  177. const activeFilters = [];
  178. for (let filterType of Object.keys(filters)) {
  179. if (configGetValue(filterType, 'on') === 'on') {
  180. activeFilters.push(filters[filterType]);
  181. }
  182. }
  183. const nodes = document.querySelectorAll(site.itemsToCheck);
  184. let numFiltered = 0;
  185. for (let node of nodes) {
  186. site.removeFilter(node);
  187. for (let activeFilter of activeFilters) {
  188. let filtered = site.applyFilter(node, activeFilter);
  189. if (filtered) {
  190. numFiltered++;
  191. break;
  192. }
  193. }
  194. }
  195. const filterStatus = document.querySelector('.filter-status');
  196. if (filterStatus) {
  197. const numUnfiltered = document.querySelectorAll(site.itemsToCheck).length - numFiltered;
  198. filterStatus.textContent = `${numUnfiltered} ${site.itemType} (${numFiltered} filtered)`;
  199. }
  200. }
  201.  
  202. function insertSwitches() {
  203. const span = document.createElement('span');
  204. span.className = 'filter-switches';
  205. for (let filterType of Object.keys(filters)) {
  206. span.appendChild(createSwitch(filterType, configGetValue(filterType, 'on') === 'on'));
  207. }
  208. const filterStatus = document.querySelector('.filter-status');
  209. if (filterStatus) {
  210. filterStatus.parentNode.appendChild(span);
  211. }
  212. }
  213.  
  214. function createSwitch(label, isOn) {
  215. const a = document.createElement('a');
  216. a.className = isOn ? 'filter-on' : 'filter-off';
  217. a.textContent = label;
  218. a.addEventListener('click', function(e) {
  219. if (this.className === 'filter-on') {
  220. this.className = 'filter-off';
  221. configSetValue(this.textContent, 'off');
  222. } else {
  223. this.className = 'filter-on';
  224. configSetValue(this.textContent, 'on');
  225. }
  226. filterScripts();
  227. e.preventDefault();
  228. }, false);
  229. return a;
  230. }
  231.  
  232. function configSetValue(name, value) {
  233. localStorage.setItem(name, value);
  234. }
  235.  
  236. function configGetValue(name, defaultValue) {
  237. const value = localStorage.getItem(name);
  238. return value ? value : defaultValue;
  239. }
  240.  
  241. })();

QingJ © 2025

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