- // ==UserScript==
- // @name Uncensor GameFAQs: G*** Edition
- // @namespace TheAmazingOne_VR@gamefaqs.com
- // @description Uncensors "g***" formatted swears on GameFAQs.
- // @include http://www.gamefaqs.com/boards/*
- // @version 1.61
-
- //-------------------------------------------------------------------
- //
- // Uncensor GameFAQs
- //
- // Author: The Amazing One (the_amazing_one3000@yahoo.com)
- // Vague Rant (minor shit, no support, go away)
- //
- // Version 1.61 notes:
- // - Now implements some rudimentary all-caps guessing. It will
- // check the current word for capitals at either end of the
- // swear, e.g. ube[R]G*** will capitalize GRIS; otherwise it
- // will check the previous or next /two/ letters from adjacent
- // words, e.g. G*** [IT] or suc[K A] Gris. It's simpler than it
- // sounds. Just try it.
- // - Extremely inefficient! Really needs someone who actually
- // knows JavaScript and regex to take over!
- //
- //
- // Version 1.6 notes:
- // - G*** Edition means "Gris Edition". But "Gold" also fits. See,
- // it's clever. Bet you were all "Is that for 'Gris' or 'Gold'?"
- // - Updated to add support for new GameFAQs censorship rules
- // (first character no longer needs to be starred out). Covers a
- // few extra words over the old version, see the list below.
- // - I don't know either regex or JavaScript. This is a total hack
- // job. If anything doesn't work, it's because I hate you.
- //
- //
- // ----- About Uncensor GameFAQs -----
- // VR NOTE! RULES HAVE CHANGED SOME OF THIS IS WRONG BUT I'M
- // LAZY SO THE OLD DESCRIPTION IS STILL HERE. BRARUARBAURHAUH.
- //
- // Uncensor GameFAQs is a script that finds series of asterisks
- // on the GameFAQs message boards, and tries to figure out what
- // bad word the person meant. It makes its best guess, and fills
- // that word in. For convenience, it also replaces the bad words
- // in your own post with asterisks. Note that the Uncensor GameFAQs
- // script will always censor your own post with asterisks,
- // never by first letter. Therefore it is in your best interest
- // not to post something like "F is for fuck" since this will
- // be censored as "F is for ****", and that's a censor bypass. The
- // exception to this rule is the word "nigger", which is always
- // censored as "n-word" or "the n-word" (rather than six asterisks).
- //
- // Supported curse words:
- // - arsehole
- // - asshole
- // - bitch
- // - cunt
- // - fag
- // - fuck
- // - jizz
- // - nigger
- // - pussy
- // - pussies
- // - shit
- // - tits
- // - titties
- // - titty
- //
- // VR NOTE! Some of these words are really shitty to use as
- // descriptors for things, people, etc. Don't be a douchebag.
- //
- //-------------------------------------------------------------------
-
-
- // This script was initially adapted from IronicSans's "Uncensor the
- // Internet" script found at:
- // http://userscripts.org/scripts/show/8891
-
- // ==/UserScript==
-
- var badSp = [], goodSp = [];
- var bad = [], good = [];
- var badFlip = [], goodFlip = [];
-
- var replacements = {
-
- "Da.\\*\\*\\*Wiz": "DaShizWiz",
-
- "A\\*\\*\\*\\*\\*\\*\\*(?!\\*)": "Arsehole",
- "a\\*\\*\\*\\*\\*\\*\\*(?!\\*)": "arsehole",
- "A\\*\\*\\*\\*\\*\\*(?!\\*)": "Asshole",
- "a\\*\\*\\*\\*\\*\\*(?!\\*)": "asshole",
- "B\\*\\*\\*\\*(?!\\*)": "Bitch",
- "b\\*\\*\\*\\*(?!\\*)": "bitch",
- "C\\*\\*\\*(?!\\*)": "Cunt",
- "c\\*\\*\\*(?!\\*)": "cunt",
- "F\\*\\*(?!\\*)": "Fag",
- "f\\*\\*(?!\\*)": "fag",
- "F\\*\\*\\*(?!\\*)": "Fuck",
- "f\\*\\*\\*(?!\\*)": "fuck",
- "J\\*\\*\\*(?!\\*)": "Jizz",
- "j\\*\\*\\*(?!\\*)": "jizz",
- "N\\*\\*\\*\\*\\*(?!\\*)": "Nigger",
- "n\\*\\*\\*\\*\\*(?!\\*)": "nigger",
- "P\\*\\*\\*\\*(?!\\*)": "Pussy",
- "p\\*\\*\\*\\*(?!\\*)": "pussy",
- "P\\*\\*\\*\\*\\*\\*(?!\\*)": "Pussies",
- "p\\*\\*\\*\\*\\*\\*(?!\\*)": "pussies",
- "S\\*\\*\\*(?!\\*)": "Shit",
- "s\\*\\*\\*(?!\\*)": "shit",
- "T\\*\\*\\*(?!\\*)": "Tits",
- "t\\*\\*\\*(?!\\*)": "tits",
- "T\\*\\*\\*\\*\\*\\*(?!\\*)": "Titties",
- "t\\*\\*\\*\\*\\*\\*(?!\\*)": "titties",
- "T\\*\\*\\*\\*(?!\\*)": "Titty",
- "t\\*\\*\\*\\*(?!\\*)": "titty",
-
- "([A-Z] ?[A-Z] |[A-Z])Arsehole": "$1ARSEHOLE",
- "Arsehole(?=(?:([A-Z]| [A-Z])))": "ARSEHOLE",
- "([A-Z] ?[A-Z] |[A-Z])Asshole": "$1ASSHOLE",
- "Asshole(?=(?:([A-Z]| [A-Z])))": "ASSHOLE",
- "([A-Z] ?[A-Z] |[A-Z])Bitch": "$1BITCH",
- "Bitch(?=(?:([A-Z]| [A-Z])))": "BITCH",
- "([A-Z] ?[A-Z] |[A-Z])Cunt": "$1CUNT",
- "Cunt(?=(?:([A-Z]| [A-Z])))": "CUNT",
- "([A-Z] ?[A-Z] |[A-Z])Fag": "$1FAG",
- "Fag(?=(?:([A-Z]| [A-Z])))": "FAG",
- "([A-Z] ?[A-Z] |[A-Z])Fuck": "$1FUCK",
- "Fuck(?=(?:([A-Z]| [A-Z] ?[A-Z])))": "FUCK",
- "([A-Z] ?[A-Z] |[A-Z])Jizz": "$1JIZZ",
- "Jizz(?=(?:([A-Z]| [A-Z])))": "JIZZ",
- "([A-Z] ?[A-Z] |[A-Z])Nigger": "$1NIGGER",
- "Nigger(?=(?:([A-Z]| [A-Z])))": "NIGGER",
- "([A-Z] ?[A-Z] |[A-Z])Pussy": "$1PUSSY",
- "Pussy(?=(?:([A-Z]| [A-Z])))": "PUSSY",
- "([A-Z] ?[A-Z] |[A-Z])Pussies": "$1PUSSIES",
- "Pussies(?=(?:([A-Z]| [A-Z])))": "PUSSIES",
- "([A-Z] ?[A-Z] |[A-Z])Shit": "$1SHIT",
- "Shit(?=(?:([A-Z]| [A-Z])))": "SHIT",
- "([A-Z] ?[A-Z] |[A-Z])Tits": "$1TITS",
- "Tits(?=(?:([A-Z]| [A-Z])))": "TITS",
- "([A-Z] ?[A-Z] |[A-Z])Titties": "$1TITTIES",
- "Titties(?=(?:([A-Z]| [A-Z])))": "TITTIES",
- "([A-Z] ?[A-Z] |[A-Z])Titty": "$1TITTY",
- "Titty(?=(?:([A-Z]| [A-Z])))": "TITTY",
-
- "\\*\\*\\*\\*(?=(?:ING|ER)\\b)": "FUCK",
- "(^|\\n|\\t|[\\.!\\?] +)\\*\\*\\*\\*(?=(?:ing|er)\\b)": "$1Fuck",
- "([^\\*])\\*\\*\\*\\*(?=(?:ing|er)\\b)": "$1fuck",
- "THIS \\*\\*\\*\\*": "THIS SHIT",
- "This \\*\\*\\*\\*": "This shit",
- "this \\*\\*\\*\\*": "this shit",
- "(^|\\n|\\t|[^\\*])\\*\\*\\*\\*(?=(?:TY|TING| NO)\\b)": "$1SHIT",
- "(^|\\n|\\t|[\\.!\\?] +)\\*\\*\\*\\*(?=(?:ty|ting)\\b)": "$1Shit",
- "([^\\*])\\*\\*\\*\\*(?=(?:ty|ting)\\b)": "$1shit"
-
- };
-
- var specialReplacements = {
- "\\bthe n-word\\b": "\"nigger\"",
- "\\bn-word\\b": "nigger"
- };
-
- var flipRules = {
- "fuck": "shit",
- "Fuck": "Shit",
- "FUCK": "SHIT",
- "shit": "fuck",
- "Shit": "Fuck",
- "SHIT": "FUCK",
- "bitch": "pussy",
- "Bitch": "Pussy",
- "BITCH": "PUSSY",
- "pussy": "bitch",
- "Pussy": "Bitch",
- "PUSSY": "BITCH"
- };
-
- for (var key in specialReplacements) {
- badSp.push(new RegExp(key, "g"));
- goodSp.push(specialReplacements[key]);
- }
- for (var key in replacements) {
- bad.push(new RegExp(key, "g"));
- good.push(replacements[key]);
- }
- for (var key in flipRules) {
- badFlip.push(new RegExp(key));
- goodFlip.push(flipRules[key]);
- }
-
- function doceval(q) {
- return document.evaluate(q, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
- }
-
- function uncensor(s,sp) {
- if(sp)
- for(var i=0; i<badSp.length; i++)
- s = s.replace(badSp[i],goodSp[i]);
- for(var i=0; i<bad.length; i++)
- s = s.replace(bad[i],good[i]);
- return s;
- }
-
- function sanitize(s) {
- var flips = [], doubles = [];
- if(!s) return s;
- if(s.charAt(0)==" " && s.charAt(1)!=" ") {
- flips.push(0);
- doubles.push(false);
- }
- for(var p = s.indexOf(" ");p!=-1;p=s.indexOf(" ",p+1)) {
- if(s.charAt(p+2)==" ") continue;
- if(p+2==s.length) break;
- flips.push(p);
- var isDouble = (p==0||s.charAt(p-1)==" ");
- doubles.push(isDouble);
- if(p!=0) s = removeAt(s,p,(isDouble?2:1));
- }
- s = uncensor(s,false);
- for(var i=0; i<flips.length; i++)
- s = flipAt(s,flips[i],doubles[i]);
- s = uncensor(s,true);
- return s;
- }
-
- function flipAt(s,i,dbl) {
- while(i<s.length && s.charAt(i)==" ")
- i++;
- if(i>=s.length) return s;
- var p = i;
- while(p<s.length && s.charAt(p)!=" ")
- p++;
- var sub = s.slice(i,p);
- sub = flipWord(sub);
- if(dbl) sub = flipWord(sub);
- s = removeAt(s,i,p-i);
- s = insertAt(s,sub,i);
- return s;
- }
-
- function flipWord(s) {
- for(var i=0; i<badFlip.length; i++)
- if(badFlip[i].test(s)) {
- s=s.replace(badFlip[i],goodFlip[i]);
- return s;
- }
- return s;
- }
-
- // replace in title
- if(document.title) {
- var gameFoxTitle = false;
- if(/^GameFAQs:M: /.test(document.title)) {
- gameFoxTitle = true;
- document.title = document.title.replace(/^GameFAQs:M: /,"");
- }
- document.title = sanitize(document.title);
- if(gameFoxTitle)
- document.title = "GameFAQs:M: "+document.title;
- }
- var h2s = doceval("//h2[@class='title']//text()");
- for(var i = 0; i < h2s.snapshotLength; i++) {
- node = h2s.snapshotItem(i);
- node.data = sanitize(node.data);
- }
- if(/post\.php/.test(window.location.href)) {
- var ttPreview = doceval("//div[@class='details']/p");
- if(ttPreview.snapshotLength>0) {
- node = ttPreview.snapshotItem(0);
- node.innerHTML = sanitize(node.innerHTML);
- }
- ttPreview = doceval("//div[@class='details']//a");
- if(ttPreview.snapshotLength>0) {
- node = ttPreview.snapshotItem(0);
- node.innerHTML = sanitize(node.innerHTML);
- }
- }
-
- // replace in body text
- var gentopic = /\/boards\/[0-9]+-[^\/]*$|myposts|search/.test(window.location.href);
- var textnodes;
- if(gentopic)
- textnodes = doceval("//table[@class=\"board topics\"]//td//text()");
- else
- textnodes = doceval("//table[@class=\"board message\"]//td//text()");
- for (var i = 0; i < textnodes.snapshotLength; i++) {
- node = textnodes.snapshotItem(i);
- node.data = sanitize(node.data);
- }
-
- function censor(text, sp) {
- if (sp) text =
- text.replace(/ARSEHOLE/g, "A*******").replace(/Arsehole/g, "A*******").replace(/arsehole/g, "a*******")
- .replace(/ASSHOLE/g, "A******").replace(/Asshole/g, "A******").replace(/asshole/g, "a******")
- .replace(/BITCH/g, "B****").replace(/Bitch/g, "B****").replace(/bitch/g, "b****")
- .replace(/CUNT/g, "C***").replace(/Cunt/g, "C***").replace(/cunt/g, "c***")
- .replace(/FAG/g, "F**").replace(/Fag/g, "F**").replace(/fag/g, "f**")
- .replace(/FUCK/g, "F***").replace(/Fuck/g, "F***").replace(/fuck/g, "f***")
- .replace(/JIZZ/g, "J***").replace(/Jizz/g, "J***").replace(/jizz/g, "j***")
- .replace(/NIGGER/g, "N*****").replace(/Nigger/g, "N*****").replace(/nigger/g, "n*****")
- .replace(/PUSSY/g, "P****").replace(/Pussy/g, "P****").replace(/pussy/g, "p****")
- .replace(/PUSSIES/g, "P******").replace(/Pussies/g, "P******").replace(/pussies/g, "p******")
- .replace(/SHIT/g, "S***").replace(/Shit/g, "S***").replace(/shit/g, "s***")
- .replace(/SHIZ/g, "S***").replace(/Shiz/g, "S***").replace(/shiz/g, "s***")
- .replace(/TITS/g, "T***").replace(/Tits/g, "T***").replace(/tits/g, "t***")
- .replace(/TITTIES/g, "T******").replace(/Titties/g, "T******").replace(/titties/g, "t******")
- .replace(/TITTY/g, "T****").replace(/Titty/g, "T****").replace(/titty/g, "t****");
- return text;
- }
-
- function insertAt(string,sub,index) {
- return string.slice(0,index)+sub+string.slice(index);
- }
- function removeAt(string,index,count) {
- return string.slice(0,index)+string.slice(index+count);
- }
-
- function prevWhitespace(string,index) {
- for(;index>0 && string.charAt(index-1)!="\n"
- && string.charAt(index-1)!="\t"
- && string.charAt(index-1)!=" "; index--);
- return index;
- }
-
- function cleanUp(text) {
- var text2=text.toLowerCase();
- var text3=uncensor(censor(text,false)).toLowerCase();
- for(var p = text3.indexOf("fuck"); p!=-1; p = text3.indexOf("fuck",p+3)) {
- var p2 = prevWhitespace(text,p);
- if(text2.substr(p,4)=="shit") {
- text=insertAt(text," ",p2);
- text2=insertAt(text2," ",p2);
- text3=insertAt(text3," ",p2);
- }
- }
- for(var p = text3.indexOf("shit"); p!=-1; p = text3.indexOf("shit",p+3)) {
- var p2 = prevWhitespace(text,p);
- if(text2.substr(p,4)=="fuck") {
- text=insertAt(text," ",p2);
- text2=insertAt(text2," ",p2);
- text3=insertAt(text3," ",p2);
- }
- }
- for(var p = text3.indexOf("bitch"); p!=-1; p = text3.indexOf("bitch",p+3)) {
- var p2 = prevWhitespace(text,p);
- if(text2.substr(p,5)=="pussy") {
- text=insertAt(text," ",p2);
- text2=insertAt(text2," ",p2);
- text3=insertAt(text3," ",p2);
- }
- }
- for(var p = text3.indexOf("pussy"); p!=-1; p = text3.indexOf("pussy",p+3)) {
- var p2 = prevWhitespace(text,p);
- if(text2.substr(p,5)=="bitch") {
- text=insertAt(text," ",p2);
- text2=insertAt(text2," ",p2);
- text3=insertAt(text3," ",p2);
- }
- }
- return censor(text,true);
- }
-
- function initRecensor() {
- var textareas = doceval("//div[@id=\"content\"]//textarea");
- if(textareas && textareas.snapshotLength>0) {
- var postBox = textareas.snapshotItem(0);
- var timedValidate = function(event) {
- setTimeout(validateFunction,10);
- };
- var validateFunction = function() {
- var selStart = postBox.selectionStart;
- var newText1 = cleanUp(postBox.value.substring(0,selStart));
- var newText2 = cleanUp(postBox.value.substring(selStart));
- if(newText1+newText2!=postBox.value) {
- postBox.value=newText1+newText2;
- postBox.setSelectionRange(newText1.length,newText1.length);
- }
- };
- var validateFunction2 = function(event) {
- postBox.value = cleanUp(postBox.value);
- }
- postBox.addEventListener("focus",timedValidate,true);
- postBox.addEventListener("blur",validateFunction2,true);
- return 0;
- } else
- setTimeout(initRecensor,1000); // GameFOX hasn't added the quickpost box yet
- }
-
- function initRecensorTitle() {
- var topicTitle = doceval("//input[@name=\"topictitle\"]");
- if(topicTitle&&topicTitle.snapshotLength>0) {
- topicTitle = topicTitle.snapshotItem(0);
- var validateTitle = function(event) {
- topicTitle.value = cleanUp(topicTitle.value);
- }
- topicTitle.addEventListener("focus",validateTitle,true);
- topicTitle.addEventListener("blur",validateTitle,true);
- } else
- setTimeout(initRecensorTitle,1000);
- }
-
- initRecensor();
- initRecensorTitle();
-
-
- // --------------------------------------------------------------------------
- // Check for updates
- //
- // Much thanks to Jarett - http://userscripts.org/users/38602 - for the code
- //---------------------------------------------------------------------------
- var version_scriptNum = 97311; // Change this to the number given to the script by userscripts.org (check the address bar)
- var version_timestamp = 1298091840552; // Used to differentiate one version of the script from an older one. Use the Date.getTime() function to get a value for this.
- function updateCheck(forced) {if((forced)||(parseInt(GM_getValue("lastUpdate", "0")) + 86400000 <= (new Date().getTime()))) {try {GM_xmlhttpRequest({method: "GET",url: "http://userscripts.org/scripts/review/" + version_scriptNum + "?" + new Date().getTime(),headers: {'Cache-Control': 'no-cache'},onload: function(xhrResponse) {GM_setValue("lastUpdate", new Date().getTime() + ""); var rt = xhrResponse.responseText.replace(/ ?/gm, " ").replace(/
/g,"\n").replace(/<li>/gm, "\n").replace(/<[^>]*>/gm, ""); var scriptName = (/@name\s*(.*?)\s*$/m.exec(rt))[1]; GM_setValue("targetScriptName", scriptName); if (parseInt(/version_timestamp\s*=\s*([0-9]+)/.exec(rt)[1]) > version_timestamp) {if (confirm("There is an update available for the Greasemonkey script \"" + scriptName + ".\"\nWould you like to go to the install page now?")) {GM_openInTab("http://userscripts.org/scripts/show/" + version_scriptNum);}} else if (forced) {alert("No update is available for \"" + scriptName + ".\"");}}});} catch (err) {if (forced) {alert("An error occurred while checking for updates:\n" + err);}}}} GM_registerMenuCommand(GM_getValue("targetScriptName", "???") + " - Manual Update Check", function() {updateCheck(true);}); updateCheck(false);