// ==UserScript== // @name GreasyFork Bullshit Filter // @namespace darkred // @version 2020.7.31 // @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. // @author kuehlschrank, darkred, valacar, Graphen // @license MIT // @icon https://raw.githubusercontent.com/darkred/Userscripts/master/GreasyFork_Bullshit_Filter/large.png // @include /^https:\/\/(greasy|sleazy)fork\.org\/(.*\/)?(scripts|discussions|users).*$/ // @exclude /^https:\/\/(greasy|sleazy)fork\.org\/(.*\/)?(scripts\/[0-9]+.*(?.filter-switches { display: block; } .filter-on, .filter-off { display: block; width: 100px; } .filter-switches a { text-decoration: none; color: inherit; cursor: pointer; } .filter-switches a { margin-left: 8px; padding: 0 4px; } a.filter-on { background-color: #ffcccc; color: #333333; text-decoration: line-through; } a.filter-off { background-color: #ccffcc; color: #333333; } `; const isOnForum = /discussions|feedback/.test(window.location.href); const site = {}; if (isOnForum) { site.css = '.discussion-list-item.filtered { display: none; } .filter-on, .filter-off { color: black; } ' + commonCss; site.cssDebug = '.discussion-list-item.filtered { background-color: khaki; } ' + commonCss; site.filterStatusLocation = '.list-option-groups'; site.itemsToCheck = '.discussion-list-item'; site.itemType = 'discussions'; site.removeFilter = function(el) { el.classList.remove('filtered'); }; site.applyFilter = function(el, activeFilter) { const temp = el.children[1].innerText; if (temp && temp.match(activeFilter)) { el.classList.add('filtered'); return true; } return false; }; } else { site.css = 'li.filtered { display: none; } ' + commonCss; site.cssDebug = 'li.filtered { background-color: khaki; } ' + commonCss; site.filterStatusLocation = '#script-list-option-groups'; site.itemsToCheck = 'article > h2'; site.itemType = 'scripts'; site.removeFilter = function(el) { el.parentNode.parentNode.classList.remove('filtered'); }; site.applyFilter = function(el, activeFilter) { if (el.innerText.match(activeFilter)) { el.parentNode.parentNode.classList.add('filtered'); return true; } return false; }; } insertStyle(); insertStatus(); filterScripts(); insertSwitches(); function insertStyle() { const style = document.createElement('style'); style.textContent = DEBUGGING ? site.cssDebug : site.css; style.type = 'text/css'; document.head.appendChild(style); } function insertStatus() { const p = document.querySelector(site.filterStatusLocation); if (p) { const status = document.createElement('span'); status.className = 'filter-status'; p.appendChild(status); } } function filterScripts() { const activeFilters = []; for (let filterType of Object.keys(filters)) { if (configGetValue(filterType, 'on') === 'on') { activeFilters.push(filters[filterType]); } } const nodes = document.querySelectorAll(site.itemsToCheck); let numFiltered = 0; for (let node of nodes) { site.removeFilter(node); for (let activeFilter of activeFilters) { let filtered = site.applyFilter(node, activeFilter); if (filtered) { numFiltered++; break; } } } const filterStatus = document.querySelector('.filter-status'); if (filterStatus) { const numUnfiltered = document.querySelectorAll(site.itemsToCheck).length - numFiltered; filterStatus.textContent = `${numUnfiltered} ${site.itemType} (${numFiltered} filtered)`; } } function insertSwitches() { const span = document.createElement('span'); span.className = 'filter-switches'; for (let filterType of Object.keys(filters)) { span.appendChild(createSwitch(filterType, configGetValue(filterType, 'on') === 'on')); } const filterStatus = document.querySelector('.filter-status'); if (filterStatus) { filterStatus.parentNode.appendChild(span); } } function createSwitch(label, isOn) { const a = document.createElement('a'); a.className = isOn ? 'filter-on' : 'filter-off'; a.textContent = label; a.addEventListener('click', function(e) { if (this.className === 'filter-on') { this.className = 'filter-off'; configSetValue(this.textContent, 'off'); } else { this.className = 'filter-on'; configSetValue(this.textContent, 'on'); } filterScripts(); e.preventDefault(); }, false); return a; } function configSetValue(name, value) { localStorage.setItem(name, value); } function configGetValue(name, defaultValue) { const value = localStorage.getItem(name); return value ? value : defaultValue; } })();