Skip to content

Instantly share code, notes, and snippets.

@Villadelfia
Created September 6, 2023 21:02
Show Gist options
  • Save Villadelfia/19af3fbb1ff0959dc2f62392c35346eb to your computer and use it in GitHub Desktop.
Save Villadelfia/19af3fbb1ff0959dc2f62392c35346eb to your computer and use it in GitHub Desktop.
Pandora's Renamer
#define REDIRECT_CHANNEL 1346195572
string name = "Pandora";
list filter = [
4, "shitting me", "kidding this one", "kidding Pandora",
4, "am I", "is this one", "is Pandora",
4, "I haven't", "this one hasn't", "Pandora hasn't",
4, "I have", "this one has", "Pandora has",
4, "I don't", "this one doesn't", "Pandora doesn't",
4, "I do", "this one does", "Pandora does",
4, "I mean", "this one means", "Pandora means",
4, "I am", "this one is", "Pandora is",
4, "I like", "this one likes", "Pandora likes",
4, "I use", "this one uses", "Pandora uses",
4, "me", "this one", "Pandora",
4, "my", "this one's", "Pandora's",
4, "mine", "this one's", "Pandora's",
4, "I've", "this one has", "Pandora has",
4, "I'm", "this one is", "Pandora is",
4, "I'll", "this one will", "Pandora will",
4, "I'd", "this one would", "Pandora would",
4, "gonna", "this one is going to", "Pandora is going to",
4, "gotta", "this one has to", "Pandora has to",
4, "myself", "Pandora", "itself",
4, "I", "this one", "Pandora",
3, "oh my god", "goodness gracious",
3, "fuck off", "go away",
3, "fucking hell", "darn it",
3, "an asshole", "a butthole",
3, "bullshit", "poppycock",
3, "damn", "darn",
3, "damned", "darned",
3, "fucking", "flipping",
3, "fuck", "fudge",
3, "hell", "heck",
3, "curses", "cusses",
3, "curse", "cuss",
3, "cursing", "cussing",
3, "god", "gosh",
3, "shittier", "poopier",
3, "shitty", "poopy",
3, "shitting", "stinking",
3, "shit", "crud",
3, "crap", "crud",
3, "asses", "butts",
3, "ass", "butt",
3, "douches", "dummies",
3, "douche", "doofus",
3, "douchebags", "fudgebags",
3, "douchebag", "fudgebag",
3, "assholes", "buttholes",
3, "asshole", "butthole",
3, "motherfuckers", "poopyheads",
3, "motherfucker", "poopyhead",
3, "jesus", "geez",
3, "omg", "goodness gracious",
3, "bitches", "poopyheads",
3, "bitch", "poopyhead",
3, "cunts", "poopyheads",
3, "cunt", "poopyhead",
3, "piss", "pee",
3, "dicks", "peepees",
3, "cocks", "peepees",
3, "dick", "peepee",
3, "cock", "peepee",
3, "vaginas", "vajajays",
3, "vagina", "vajajay",
3, "pussy", "vajajay",
3, "pussies", "vajajays"
];
list suffixes = [" ", ",", "\"", ".", "?", "!", ":", ";"];
list endings = [". ", "? ", "! ", ": ", "; ", "\"", " "];
integer startsWith(string haystack, string needle) {
return llDeleteSubString(haystack, llStringLength(needle), 0x7FFFFFF0) == needle;
}
integer endsWith(string haystack, string needle) {
return llDeleteSubString(haystack, 0x8000000F, ~llStringLength(needle)) == needle;
}
integer contains(string haystack, string needle) {
return 0 <= llSubStringIndex(haystack, needle);
}
filterSpeech(string message) {
// Just output emotes.
if(startsWith(message, "/me") && !contains(message, "\"")) jump skip;
// Cache the lengths.
integer flen = llGetListLength(filter);
integer slen = llGetListLength(suffixes);
integer elen = llGetListLength(endings);
// Iterators.
integer f = 0;
integer s = 0;
integer e = 0;
// Work variables.
integer consume = TRUE;
integer stride = 0;
string output = "";
string checking = "";
string Checking = "";
string replace = "";
string Replace = "";
string suffix = "";
string ending = "";
integer checklength = 0;
integer lstart = FALSE;
integer ustart = FALSE;
integer hassuffix = FALSE;
integer wherenext1 = 0;
integer wherenext2 = 0;
integer unfiltered = 0;
// Mark URLS.
if(contains(message, "http://") || contains(message, "https://") || contains(message, "secondlife://")) {
output = message;
message = "";
while(output != "") {
if(unfiltered > 0) {
if(llGetSubString(output, 0, 0) == " ") {
message += "]]]";
unfiltered--;
}
} else {
if(startsWith(output, "http://") || startsWith(output, "https://") || startsWith(output, "secondlife://")) {
message += "[[[";
unfiltered++;
}
}
message += llGetSubString(output, 0, 0);
output = llDeleteSubString(output, 0, 0);
}
// This isn't strictly needed, but let's go for precision here.
while(unfiltered > 0) {
unfiltered--;
message += "]]]";
}
}
// Consume the message and filter.
while(message != "") {
// Assume we didn't consume anything.
consume = FALSE;
// Allow unfiltered stuff.
if(startsWith(message, "[[[")) {
unfiltered++;
message = llDeleteSubString(message, 0, 2);
while(unfiltered > 0 && message != "") {
if(startsWith(message, "[[[")) {
unfiltered++;
message = llDeleteSubString(message, 0, 2);
} else if(startsWith(message, "]]]")) {
unfiltered--;
message = llDeleteSubString(message, 0, 2);
} else if(unfiltered > 0) {
output += llGetSubString(message, 0, 0);
message = llDeleteSubString(message, 0, 0);
}
}
}
// Check all filters.
f = 0;
while(f < flen && !consume) {
// To find the next index.
stride = llList2Integer(filter, f);
// What to check.
checking = llList2String(filter, f+1);
Checking = llToUpper(llGetSubString(checking, 0, 0)) + llGetSubString(checking, 1, -1);
checklength = llStringLength(checking);
// Check if the string starts with what we're checking for.
lstart = startsWith(message, checking);
ustart = startsWith(message, Checking);
if(!lstart && !ustart) jump nomatch;
// A random replacement option.
replace = llList2String(llListRandomize(llList2List(filter, f+2, f+stride-1), 1), 0);
Replace = llToUpper(llGetSubString(replace, 0, 0)) + llGetSubString(replace, 1, -1);
// At this point we know that the remainder of the message at the very least starts with the thing we're filtering. There are still more checks to be done however.
// Iterate over the possible suffixes.
for(s = 0; s < slen && consume == FALSE; s++) {
suffix = llList2String(suffixes, s);
// Check if it has the suffix.
hassuffix = llSubStringIndex(llGetSubString(message, checklength, -1), suffix) == 0;
// If it doesn't have the suffix, check if what we're filtering is the entire rest of the message.
// Only check on the first suffix though. This only needs to be checked once.
// If that's the case, we can just set the suffix to nothing and allow a replacement. Otherwise we skip to the next suffix.
if(!hassuffix) {
if(s == 0) {
hassuffix = checklength == llStringLength(message);
if(hassuffix) suffix = "";
else jump nextsuffix;
} else {
jump nextsuffix;
}
}
// First we check if it's the start of the output.
if(output == "") {
output += Replace+suffix;
consume = TRUE;
} else {
for(e = 0; e < elen && consume == FALSE; e++) {
ending = llList2String(endings, e);
if(endsWith(output, ending)) {
if(ending == " ") {
// Or for normal words.
output += replace+suffix;
} else {
// Check if a sentence just ended.
output += Replace+suffix;
}
consume = TRUE;
}
}
}
// This shouldn't happen. Ever.
if(!consume) {
output += replace+suffix;
consume = TRUE;
}
@nextsuffix;
}
@nomatch;
f += stride;
}
if(!consume) {
// If we didn't consume anything, just chew up until the next space.
wherenext1 = -1;
for(s = 0; s < slen; s++) {
wherenext2 = llSubStringIndex(message, llList2String(suffixes, s));
if(wherenext1 == -1) wherenext1 = wherenext2;
else if(wherenext2 != -1 && wherenext2 < wherenext1) wherenext1 = wherenext2;
}
if(wherenext1 == -1) {
output += message;
message = "";
} else {
output += llGetSubString(message, 0, wherenext1);
message = llDeleteSubString(message, 0, wherenext1);
}
} else {
// Otherwise remove the consumed part from the input.
message = llDeleteSubString(message, 0, llStringLength(checking+suffix)-1);
}
}
message = output;
@skip;
string n = llGetObjectName();
llSetObjectName(name);
if(!startsWith(message, "https://") && !startsWith(message, "http://") && !startsWith(message, "secondlife://")) llSay(0, llToUpper(llGetSubString(message, 0, 0)) + llDeleteSubString(message, 0, 0));
else llSay(0, message);
llSetObjectName(n);
}
default {
state_entry() {
llOwnerSay("Bytes free: " + (string)llGetFreeMemory());
llListen(REDIRECT_CHANNEL, "", llGetOwner(), "");
llListen(0, "", llGetOwner(), "");
llOwnerSay("@redirchat:" + (string)REDIRECT_CHANNEL + "=add,rediremote:" + (string)REDIRECT_CHANNEL + "=add");
}
changed(integer change) {
if(change & CHANGED_OWNER) llResetScript();
}
on_rez(integer n) {
llOwnerSay("@redirchat:" + (string)REDIRECT_CHANNEL + "=add,rediremote:" + (string)REDIRECT_CHANNEL + "=add");
}
listen(integer c, string n, key id, string m) {
if(c == 0) {
if(startsWith(m, "((") || endsWith(m, "))")) return;
llOwnerSay("@redirchat:" + (string)REDIRECT_CHANNEL + "=add,rediremote:" + (string)REDIRECT_CHANNEL + "=add");
}
filterSpeech(m);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment