attempts Block bypassed variations using fuzzy matching
// ==UserScript==
// @name ROBLOX: Global Title Filter
// @description attempts Block bypassed variations using fuzzy matching
// @match *://*.roblox.com/*
// @run-at document-start
// @grant none
// @version 9.0.0
// @namespace https://greasyfork.org/users/1576301
// ==/UserScript==
(() => {
"use strict";
const BASE_WORDS = [
"brainrot",
"gen alpha",
"garden",
"farm",
"garten",
"grow a",
"grow your poop",
"steal",
"steal a"
];
function normalize(s) {
return String(s || "")
.toLowerCase()
.replace(/@/g,"a")
.replace(/\$/g,"s")
.replace(/0/g,"o")
.replace(/1/g,"i")
.replace(/3/g,"e")
.replace(/4/g,"a")
.replace(/5/g,"s")
.replace(/7/g,"t")
.replace(/[^a-z0-9\s]/g,"")
.replace(/\s+/g," ")
.trim();
}
function levenshtein(a,b){
if(a.length===0) return b.length;
if(b.length===0) return a.length;
const matrix=[];
for(let i=0;i<=b.length;i++) matrix[i]=[i];
for(let j=0;j<=a.length;j++) matrix[0][j]=j;
for(let i=1;i<=b.length;i++){
for(let j=1;j<=a.length;j++){
if(b.charAt(i-1)===a.charAt(j-1)){
matrix[i][j]=matrix[i-1][j-1];
}else{
matrix[i][j]=Math.min(
matrix[i-1][j-1]+1,
matrix[i][j-1]+1,
matrix[i-1][j]+1
);
}
}
}
return matrix[b.length][a.length];
}
function fuzzyMatch(title){
const t = normalize(title);
for(const base of BASE_WORDS){
const b = normalize(base);
if(t.includes(b)) return true;
const words = t.split(" ");
for(const w of words){
if(levenshtein(w,b) <= 2) return true;
}
}
return false;
}
const originalFetch = window.fetch;
window.fetch = async function(...args){
const res = await originalFetch.apply(this,args);
try{
const url = args[0]?.toString()||"";
if(!/games|discover|charts/i.test(url)) return res;
const clone = res.clone();
const data = await clone.json();
if(data?.data && Array.isArray(data.data)){
data.data = data.data.filter(g=>!fuzzyMatch(g.name||g.title));
return new Response(JSON.stringify(data),{
status:res.status,
statusText:res.statusText,
headers:res.headers
});
}
}catch{}
return res;
};
const originalXHR = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(...args){
this.addEventListener("readystatechange",function(){
try{
if(this.readyState===4 && this.responseText){
if(!/games|discover|charts/i.test(args[1])) return;
const json = JSON.parse(this.responseText);
if(json?.data && Array.isArray(json.data)){
json.data = json.data.filter(g=>!fuzzyMatch(g.name||g.title));
Object.defineProperty(this,"responseText",{value:JSON.stringify(json)});
}
}
}catch{}
});
return originalXHR.apply(this,args);
};
function hideDOM(){
const links = Array.from(document.querySelectorAll('a[href*="/games/"]'));
for(const a of links){
const tile = a.closest('li,[role="row"],[role="listitem"],div');
if(!tile) continue;
if(tile.dataset.filtered==="1") continue;
const text = tile.textContent||"";
if(fuzzyMatch(text)){
tile.dataset.filtered="1";
tile.style.display="none";
}
}
}
const observer = new MutationObserver(()=>hideDOM());
document.addEventListener("DOMContentLoaded",hideDOM);
observer.observe(document.documentElement,{childList:true,subtree:true});
setInterval(hideDOM,1000);
})();