Skip to content

Instantly share code, notes, and snippets.

@kotarou3
Created April 28, 2012 10:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kotarou3/2517950 to your computer and use it in GitHub Desktop.
Save kotarou3/2517950 to your computer and use it in GitHub Desktop.
Pokemon Showdown Moderation Tool
var dingSound = null;
socket.on("update", function(data)
{
if (data.room !== "lobby" || !data.logUpdate || data.logUpdate.length === 0 || !data.logUpdate[0].name)
return;
if (data.logUpdate[0].message.toLowerCase().replace(/[^a-z0-9]/, "").indexOf(me.userid) !== -1)
if (dingSound)
dingSound.play();
else
dingSound = soundManager.createSound({id:"ding",url: "http://soundjax.com/reddo/99652%5EDING1.mp3",autoPlay: true,volume: 100});
});
// Add a few hooks
socket.origEmit = socket.emit;
socket.emit = function(message, data)
{
var result = onSocketSend(message, data);
if (!result) return;
if (result === true)
return socket.origEmit(message, data);
return socket.origEmit(result.message, result.data);
}
socket.origOnPacket = socket.onPacket;
socket.onPacket = function(packet)
{
if (packet.type !== "event") return socket.origOnPacket(packet);
var result = onSocketRecv(packet.name, packet.args[0]);
if (!result) return;
if (result === true)
return socket.origOnPacket(packet);
packet.name = result.message;
packet.args[0] = result.data;
return socket.origOnPacket(packet);
}
socket.recv = function(message, data)
{
var packet = {type:"event",name:message,args:[data]};
return socket.onPacket(packet);
}
// Actual code
function addRaw(room, message)
{
var room = rooms[room];
if (!room) return;
if (room.id === "lobby")
socket.recv("update", {room:"lobby",logUpdate:[{rawMessage:message}]});
else
socket.recv("update", {room:room.id,updates:["| chatmsg-raw | " + message]});
}
var autoFrList =
{
".*isgay": "Names are not allowed to contain directed insults.",
"ipunchkids": "Your name was inappropiate.",
"duma": "Your name was inappropiate because it contained words of sexual nature.",
".*bitch.*": "Your name was inappropiate.",
".*molester.*": "Your name was inappropiate because it contained words of sexual nature.",
".*cock?.*": "Your name was inappropiate because it contained words of sexual nature.",
".*penis.*": "Your name was inappropiate because it contained words of sexual nature.",
".*chode.*": "Your name was inappropiate because it contained words of sexual nature.",
".*creampie.*": "Your name was inappropiate because it contained words of sexual nature.",
".*8+=+D+.*": "Your name was inappropiate because it contained words of sexual nature.",
".*dick.*": "Your name was inappropiate because it contained words of sexual nature.",
".*scrotum.*": "Your name was inappropiate because it contained words of sexual nature.",
".*(nut|nad)s.*": "Your name was inappropiate because it contained words of sexual nature.",
".*cunt.*": "Your name was inappropiate because it contained words of sexual nature.",
".*(ball|nut)sack.*": "Your name was inappropiate because it contained words of sexual nature.",
".*douche.*": "Your name was inappropiate because it contained words of sexual nature.",
".*hitler.*": "Your name was inappropiate because it was anti-semitic.",
".*holocaust.*": "Your name was inappropiate because it was anti-semitic.",
".*n[il]gg(er|a).*": "Your name was inappropiate because it used a derogatory term.",
".*fag(g[oe]t)?.*": "Your name was inappropiate because it used a derogatory term.",
".*anus.*": "Your name was inappropiate.",
".*fu(ck|x).*": "Your name was inappropiate.",
".*shit.*": "Your name was inappropiate.",
".*milf.*": "Your name was inappropiate because it contained words of sexual nature.",
".*wetback.*": "Your name was inappropiate because it used a derogatory term.",
".*rapist.*": "Your name was inappropiate because it contained words of sexual nature.",
".*rape.*": "Your name was inappropiate because it contained words of sexual nature.",
"adrainpussy": "Your name was inappropiate.",
"ihatejews": "Your name was inappropiate because it was anti-semitic.",
"porchmonkey": "Your name was inappropiate.",
"niglet": "Your name was inappropiate because it used a derogatory term.",
"nigtrio": "Your name was inappropiate because it used a derogatory term.",
"assface": "Your name was inappropiate.",
"diggernick": "Your name was inappropiate because it used a derogatory term.",
"nillerkigger": "Your name was inappropiate because it used a derogatory term.",
"kkk": "Your name was inappropiate.",
"hairytits": "Your name was inappropiate because it contained words of sexual nature.",
"masterbaiter" : "Your name was inappropiate because it contained words of sexual nature.",
"yourgay" : "Your name was inappropiate to contain directed insults.",
".*wank.*" : "Your name was inappropiate because it contained words of sexual nature.",
".*jizz.*" : "Your name was inappropiate.",
".*paska.*" : "Your name was inappropiate.",
".*anaali.*" : "Your name was inappropiate.",
".*perse.*" : "Your name was inappropiate.",
".*berse.*" : "Your name was inappropiate.",
".*kakka.*" : "Your name was inappropiate.",
".*pippeli.*": "Your name was inappropiate because it contained words of sexual nature.",
".*kikkeli.*": "Your name was inappropiate because it contained words of sexual nature.",
".*vittu.*": "Your name was inappropiate.",
".+sucks": "Names are not allowed to contain directed insults.",
".*admins.*": "Your name was inappropiate.",
".*mods.*": "Your name was inappropiate.",
// ".*kota.+": "Your name contained the name of a moderator.",
// ".+kota.*": "Your name contained the name of a moderator.",
".*mikel.+": "Your name contained the name of a moderator.",
".+mikel.*": "Your name contained the name of a moderator.",
"mik.+nub": "Your name contained the name of a moderator.",
".*pharen.+": "Your name contained the name of a moderator.",
".+pharen.*": "Your name contained the name of a moderator."
};
var autoBanList = {
/* "96.224.180.0/24": "Cheating on ladder. (Scumbag)",
"123.98.0.0/16": "Cheating on ladder.", // SennheiserHD1000 aka 800KgAfrican
"101.103.4.0/24": "Cheating on ladder.",
"66.87.4.0/24": "Linking to porn in chat. (Omnicient Legacy)",
"79.177.0.0/16": "COPPA (KarinaPaley)",
"79.176.0.0/16": "COPPA (KarinaPaley)",
"193.167.114.0/24": "Repeated offenses of spamming, anti-semitism and insulting moderators. (HEIL HITLER people)",
"74.12.0.0/14": "Spamming link to porn (lol50)",
"69.156.0.0/14": "Spamming link to porn (lol50)",
"70.48.0.0/13": "Spamming link to porn (lol50)",
"69.158.0.0/22": "Spamming link to porn (lol50)"*/
};
function onSocketSend(message, data)
{
switch (message)
{
case "chat" :
if (data.message.toLowerCase().indexOf("/showautofr") === 0)
{
if (Object.keys(autoFrList).length > 0)
for (var a in autoFrList)
addRaw(curRoom.id, "\"" + a + "\": \"" + autoFrList[a] + "\"");
else
addRaw(curRoom.id, "Nobody is on the auto rename list.");
return false;
}
break;
}
return true;
}
var ipPendingList = new Object();
var spamMuterData = new Object();
function onSocketRecv(message, data)
{
switch (message)
{
case "command" :
if (data.command === "userdetails" && ipPendingList[data.userid] && data.ip) {
delete ipPendingList[data.userid];
var user = data.userid;
var ip = data.ip;
if (autoBanList[ip]) {
socket.emit("chat", {message:"/ban " + user + "," + autoBanList[ip], room:curRoom.id});
} else {
for (var i in autoBanList) {
if (i.indexOf("/") === -1) continue;
var ipSubnet = i.split("/");
if ((IPnumber(ip) & IPmask(parseInt(ipSubnet[1], 10))) === IPnumber(ipSubnet[0])) {
socket.emit("chat", {message:"/ban " + user + "," + autoBanList[i], room:curRoom.id});
break;
}
}
}
return false;
}
break;
case "console" :
if (data.action === "join" || data.action === "rename")
{
var user = data.name.toLowerCase().replace(/[^a-z0-9]+/g, "");
ipPendingList[user] = true;
socket.emit("command", {command:"userdetails", userid:user, room:"lobby"});
user = removeAccents(data.name).toLowerCase().replace(/[^a-z0-9]+/g, "");
var match = ObjectRegexMatch(user, autoFrList);
if (!match)
match = ObjectRegexMatch(user.split("").reverse().join(""), autoFrList);
if (match)
addPossibleRenameQueue(data.name, match, autoFrList[match]);
}
else if (data.pm)
{
// Auto pm spam muter
var user = data.name.toLowerCase().replace(/[^a-z0-9]+/g, "");
var message = data.message.toLowerCase().replace(/\s+/g, "");
var now = Math.floor((new Date()).getTime() / 1000);
if (!spamMuterData[user])
spamMuterData[user] = new Array();
spamMuterData[user].push([now, message]);
if (spamMuterData[user].length > 4 &&
message === spamMuterData[user][spamMuterData[user].length - 1][1] &&
message === spamMuterData[user][spamMuterData[user].length - 2][1] &&
message === spamMuterData[user][spamMuterData[user].length - 3][1] &&
message === spamMuterData[user][spamMuterData[user].length - 4][1] &&
message === spamMuterData[user][spamMuterData[user].length - 5][1])
{
delete spamMuterData[user];
socket.emit("chat", {message:"/redir " + user + ",nyan.cat", room:curRoom.id});
}
else if (spamMuterData[user].length > 6)
{
if (spamMuterData[user][0][0] + 6 > now)
{
delete spamMuterData[user];
socket.emit("chat", {message:"/redir " + user + ",nyan.cat", room:curRoom.id});
}
else
spamMuterData[user].shift();
}
}
break;
case "update" :
if (data.room !== "lobby" || !data.logUpdate || data.logUpdate.length === 0 || !data.logUpdate[0].name)
break;
// Auto spam muter
var user = data.logUpdate[0].name.toLowerCase().replace(/[^a-z0-9]+/g, "");
var message = data.logUpdate[0].message.toLowerCase().replace(/\s+/g, "");
var now = Math.floor((new Date()).getTime() / 1000);
if (!spamMuterData[user])
spamMuterData[user] = new Array();
spamMuterData[user].push([now, message]);
if (spamMuterData[user].length > 4 &&
message === spamMuterData[user][spamMuterData[user].length - 1][1] &&
message === spamMuterData[user][spamMuterData[user].length - 2][1] &&
message === spamMuterData[user][spamMuterData[user].length - 3][1] &&
message === spamMuterData[user][spamMuterData[user].length - 4][1] &&
message === spamMuterData[user][spamMuterData[user].length - 5][1])
{
delete spamMuterData[user];
socket.emit("chat", {message:"/mute " + user + ", Automatically muted for spamming.", room:curRoom.id});
}
else if (spamMuterData[user].length > 6)
{
if (spamMuterData[user][0][0] + 6 > now)
{
delete spamMuterData[user];
socket.emit("chat", {message:"/mute " + user + ", Automatically muted for spamming.", room:curRoom.id});
}
else
spamMuterData[user].shift();
}
break;
}
return true;
}
var possibleRenameQueue = new Array();
var isCurrentlyDisplaying = false;
var dingSound = null;
function addPossibleRenameQueue(name, match, message)
{
function callback()
{
possibleRenameQueue.shift();
isCurrentlyDisplaying = false;
}
function callback2()
{
if (isCurrentlyDisplaying)
return;
if (possibleRenameQueue.length > 0)
{
isCurrentlyDisplaying = true;
toolOverlay("<strong>Possible Bad Name Found</strong><br>\
Name: " + possibleRenameQueue[0][0] + "<br>\
Matches: " + possibleRenameQueue[0][1] + "<br>\
Reason/Message:<br>\
<input type=\"text\" id=\"possible-rename-message\" value=\"" + possibleRenameQueue[0][2] + "\"><br>\
<input type=\"hidden\" id=\"possible-rename-name\" value=\"" + possibleRenameQueue[0][0].toLowerCase().replace(/[^a-z0-9]+/g, "") + "\">\
<button id=\"possible-rename-rename\">Fr</button>\
<button id=\"possible-rename-pm\">PM</button>\
<button id=\"possible-rename-alts\">Alts</button>\
<button id=\"possible-rename-whois\">Whois</button><br />\
<button id=\"possible-rename-nyan1\">Nyan 1</button>\
<button id=\"possible-rename-nyan2\">Nyan 2</button>\
<button id=\"possible-rename-ban\">Ban</button>", callback, callback2);
document.getElementById("possible-rename-rename").onclick = function()
{
var message = document.getElementById("possible-rename-message").value;
var name = document.getElementById("possible-rename-name").value;
socket.emit("chat", {message:"/fr " + name + "," + message, room:curRoom.id});
callback();
toolOverlayClose();
callback2();
};
document.getElementById("possible-rename-nyan1").onclick = function()
{
var name = document.getElementById("possible-rename-name").value;
socket.emit("chat", {message:"/redir " + name + ",nyan.cat", room:curRoom.id});
callback();
toolOverlayClose();
callback2();
};
document.getElementById("possible-rename-nyan2").onclick = function()
{
var name = document.getElementById("possible-rename-name").value;
socket.emit("chat", {message:"/redir " + name + ",http://nyanit.com/play.pokemonshowdown.com/~~pokemonshowdown.com:0/lobby", room:curRoom.id});
callback();
toolOverlayClose();
callback2();
};
document.getElementById("possible-rename-ban").onclick = function()
{
var name = document.getElementById("possible-rename-name").value;
socket.emit("chat", {message:"/br " + name + ",nyan.cat", room:curRoom.id});
callback();
toolOverlayClose();
callback2();
};
document.getElementById("possible-rename-pm").onclick = function()
{
var message = document.getElementById("possible-rename-message").value;
var name = document.getElementById("possible-rename-name").value;
socket.emit("chat", {message:"/pm " + name + "," + message, room:curRoom.id});
callback();
toolOverlayClose();
callback2();
};
document.getElementById("possible-rename-alts").onclick = function()
{
var name = document.getElementById("possible-rename-name").value;
socket.emit("chat", {message:"/alts " + name, room:curRoom.id});
};
document.getElementById("possible-rename-whois").onclick = function()
{
var name = document.getElementById("possible-rename-name").value;
socket.emit("chat", {message:"/whois " + name, room:curRoom.id});
};
}
}
possibleRenameQueue.push([name, match, message]);
if (dingSound)
dingSound.play();
else
dingSound = soundManager.createSound({id:"ding",url: "http://soundjax.com/reddo/99652%5EDING1.mp3",autoPlay: true,volume: 100});
callback2();
}
function ObjectRegexMatch(s, object)
{
var keys = Object.keys(object);
for (var k = 0; k < keys.length; ++k)
if (s.match(new RegExp("^" + keys[k] + "$")))
return keys[k];
return null;
}
function removeAccents(s)
{
var torem = s.split('');
toremout = new Array();
toremlen = torem.length;
var sec = '0123456@ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž';
var rep = ['o', 'i', 'z', 'e', 'a', 's', 'g', 'a', 'A', 'A', 'A', 'A', 'A', 'A', 'a', 'a', 'a', 'a', 'a', 'a', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'o', 'o', 'o', 'o', 'o', 'o', 'E', 'E', 'E', 'E', 'e', 'e', 'e', 'e', 'e', 'C', 'c', 'D', 'I', 'I', 'I', 'I', 'i', 'i', 'i', 'i', 'U', 'U', 'U', 'U', 'u', 'u', 'u', 'u', 'N', 'n', 'S', 's', 'Y', 'y', 'y', 'Z', 'z'];
for (var y = 0; y < toremlen; y++)
if (sec.indexOf(torem[y]) != -1)
toremout[y] = rep[sec.indexOf(torem[y])];
else
toremout[y] = torem[y];
toascout = toremout.join('');
return toascout;
}
var isStylesInjected = false;
function injectStyles()
{
if (isStylesInjected)
return;
var style = document.createElement("style");
styles = "#tool-overlay \
{ \
position: absolute; \
right: 50px; \
top: 50px; \
display: inline-block; \
min-height: 100px; \
min-width: 250px; \
background-color: #fff; \
border: 1px solid #aaa; \
padding: 5px; \
padding-top: 10px; \
} \
#tool-overlay-close \
{ \
position: absolute; \
right: 2px; \
top: 2px; \
border: 1px solid #aaa; \
line-height: 8px; \
height: 10px; \
width: 10px; \
color: #aaa; \
cursor: pointer; \
}";
style.innerHTML = styles;
document.getElementsByTagName("head")[0].appendChild(style);
isStylesInjected = true;
}
function toolOverlay(contents, callback, callback2)
{
injectStyles();
if(document.getElementById("tool-overlay-close"))
document.getElementById("tool-overlay-close").onclick();
var overlay = document.createElement("div");
overlay.id = "tool-overlay";
var innerHTML = contents;
innerHTML += "<div id=\"tool-overlay-close\">&times;</div>";
overlay.innerHTML = innerHTML;
document.body.appendChild(overlay);
document.getElementById("tool-overlay-close").onclick = function() { if (callback) callback(); toolOverlayClose(); if (callback2) callback2(); };
}
function toolOverlayClose()
{
var toolOverlay = document.getElementById("tool-overlay");
if (toolOverlay)
toolOverlay.parentNode.removeChild(toolOverlay);
}
// pilfered from http://stackoverflow.com/a/503238/359653
function IPnumber(IPaddress) {
var ip = IPaddress.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
if(ip) {
return (+ip[1]<<24) + (+ip[2]<<16) + (+ip[3]<<8) + (+ip[4]);
}
// else ... ?
return null;
}
function IPmask(maskSize) {
return -1<<(32-maskSize)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment