add kick counter list to chatcleaner to kickban disturbing players after multiple kicks for chat offence

This commit is contained in:
doitux
2010-07-13 13:50:43 +00:00
parent a70ae9ddfb
commit a78a9e80ea
3 changed files with 193 additions and 133 deletions
+4 -1
View File
@@ -43,7 +43,7 @@ using namespace std;
CleanerConfig::CleanerConfig() CleanerConfig::CleanerConfig()
{ {
// !!!! Revisionsnummer der Configdefaults !!!!! // !!!! Revisionsnummer der Configdefaults !!!!!
configRev = 7; configRev = 8;
// Pfad und Dateinamen setzen // Pfad und Dateinamen setzen
#ifdef _WIN32 #ifdef _WIN32
@@ -121,6 +121,9 @@ CleanerConfig::CleanerConfig()
configList.push_back(ConfigInfo("TextFloodLevelToTrigger", CONFIG_TYPE_INT, "3")); configList.push_back(ConfigInfo("TextFloodLevelToTrigger", CONFIG_TYPE_INT, "3"));
configList.push_back(ConfigInfo("CapsFloodCapsNumberToTrigger", CONFIG_TYPE_INT, "10")); configList.push_back(ConfigInfo("CapsFloodCapsNumberToTrigger", CONFIG_TYPE_INT, "10"));
configList.push_back(ConfigInfo("LetterRepeatingNumberToTrigger", CONFIG_TYPE_INT, "10")); configList.push_back(ConfigInfo("LetterRepeatingNumberToTrigger", CONFIG_TYPE_INT, "10"));
configList.push_back(ConfigInfo("KickNumberToBan", CONFIG_TYPE_INT, "2"));
configList.push_back(ConfigInfo("SecondsToForgetAboutKick", CONFIG_TYPE_INT, "1800"));
list<string> badWordsList; list<string> badWordsList;
badWordsList.push_back("arsch"); badWordsList.push_back("arsch");
+177 -132
View File
@@ -10,156 +10,201 @@
#include "urlcheck.h" #include "urlcheck.h"
enum ActionType { enum ActionType {
NOTHING, NOTHING,
WARN, WARN,
KICK }; KICK,
KICKBAN
};
enum OffenceType { enum OffenceType {
NONE, NONE,
BAD_WORD, BAD_WORD,
TEXT_FLOOD_LINES, TEXT_FLOOD_LINES,
CAPS_FLOOD, CAPS_FLOOD,
LETTER_REPEATING, LETTER_REPEATING,
URL URL
}; };
MessageFilter::MessageFilter(CleanerConfig *c): config(c) MessageFilter::MessageFilter(CleanerConfig *c): config(c)
{ {
myBadWordCheck = new BadWordCheck; myBadWordCheck = new BadWordCheck;
myTextFloodCheck = new TextFloodCheck; myTextFloodCheck = new TextFloodCheck;
myCapsFloodCheck = new CapsFloodCheck; myCapsFloodCheck = new CapsFloodCheck;
myLetterRepeatingCheck = new LetterRepeatingCheck; myLetterRepeatingCheck = new LetterRepeatingCheck;
myUrlCheck = new UrlCheck; myUrlCheck = new UrlCheck;
cleanTimer = new QTimer();
connect(cleanTimer, SIGNAL(timeout()), this, SLOT(cleanKickCounterList()));
cleanTimer->start(30000);
} }
MessageFilter::~MessageFilter() { MessageFilter::~MessageFilter() {
delete myBadWordCheck; delete myBadWordCheck;
delete myTextFloodCheck; delete myTextFloodCheck;
delete myCapsFloodCheck; delete myCapsFloodCheck;
delete myLetterRepeatingCheck; delete myLetterRepeatingCheck;
delete myUrlCheck; delete myUrlCheck;
delete cleanTimer;
} }
QStringList MessageFilter::check(unsigned playerId, QString nick, QString msg) QStringList MessageFilter::check(unsigned playerId, QString nick, QString msg)
{ {
QStringList returnList; QStringList returnList;
QString returnMessage; QString returnMessage;
QString returnAction; QString returnAction;
OffenceType offence = NONE;
ActionType action = NOTHING;
if(myBadWordCheck->run(msg)) offence = BAD_WORD;
if(myCapsFloodCheck->run(msg)) offence = CAPS_FLOOD;
if(myLetterRepeatingCheck->run(msg)) offence = LETTER_REPEATING;
if(myUrlCheck->run(msg)) offence = URL;
if(myTextFloodCheck->run(playerId)) offence = TEXT_FLOOD_LINES;
if(offence){
QMap<unsigned, ClientWarnInfos>::const_iterator i = myClientWarnLevelList.find(playerId);
if(i == myClientWarnLevelList.end()) {
ClientWarnInfos tmpInfos;
tmpInfos.warnLevel = 1;
tmpInfos.lastWarnType = offence;
tmpInfos.nick = nick;
myClientWarnLevelList.insert(playerId, tmpInfos);
action = WARN;
}
else {
if(i.value().warnLevel == warnLevelToKick || i.value().lastWarnType == offence) {
// Kick Command
action = KICK;
//remove playerId from all lists and as LAST from myClientWarnLevelList
myTextFloodCheck->removeNickFromList(i.key());
myClientWarnLevelList.remove(i.key());
}
else {
ClientWarnInfos tmpInfos;
tmpInfos.warnLevel = i.value().warnLevel+1;
tmpInfos.lastWarnType = offence;
tmpInfos.nick = nick;
myClientWarnLevelList.insert(playerId, tmpInfos);
action = WARN;
}
}
if(action == KICK) {
returnMessage = QString("Kick: %1\n").arg(nick);
returnAction = QString("kick");
}
if(action == WARN) {
switch(offence) {
case BAD_WORD: {
returnMessage = QString ("%1: Warning! No racial, religious, or sexually inflammatory language!\n").arg(nick);
}
break;
case TEXT_FLOOD_LINES: {
returnMessage = QString ("%1: Warning! You've triggered text flood (lines) protection, slow down your typing!\n").arg(nick);
}
break;
case CAPS_FLOOD: {
returnMessage = QString ("%1: Warning: You've triggered caps flood protection, release your caps!\n").arg(nick);
}
break;
case LETTER_REPEATING: {
returnMessage = QString ("%1: Warning: You've triggered letter repeating protection, stop repeating!\n").arg(nick);
}
break;
case URL: {
returnMessage = QString ("%1: Warning: You've triggered url spam protection, stop posting urls!\n").arg(nick);
}
break;
default:;
}
returnAction = QString("warn");
}
}
else {
returnAction = QString("");
returnMessage = QString("");
}
returnList << returnAction << returnMessage; OffenceType offence = NONE;
return returnList; ActionType action = NOTHING;
if(myBadWordCheck->run(msg)) offence = BAD_WORD;
if(myCapsFloodCheck->run(msg)) offence = CAPS_FLOOD;
if(myLetterRepeatingCheck->run(msg)) offence = LETTER_REPEATING;
if(myUrlCheck->run(msg)) offence = URL;
if(myTextFloodCheck->run(playerId)) offence = TEXT_FLOOD_LINES;
if(offence){
QMap<unsigned, ClientWarnInfos>::const_iterator i = myClientWarnLevelList.find(playerId);
if(i == myClientWarnLevelList.end()) {
ClientWarnInfos tmpInfos;
tmpInfos.warnLevel = 1;
tmpInfos.lastWarnType = offence;
tmpInfos.nick = nick;
myClientWarnLevelList.insert(playerId, tmpInfos);
action = WARN;
}
else {
if(i.value().warnLevel == warnLevelToKick || i.value().lastWarnType == offence) {
// Kick Command
action = KICK;
//remove playerId from all lists and as LAST from myClientWarnLevelList
myTextFloodCheck->removeNickFromList(i.key());
myClientWarnLevelList.remove(i.key());
//check if player is already on kickCounterList
QMap<QString, ClientKickInfos>::const_iterator j = myClientKickCounterList.find(nick);
if(j == myClientKickCounterList.end()) {
//if player is NOT on this list put the playerId on it to ban after multiple offence
ClientKickInfos tmpInfos;
tmpInfos.kickNumber = 1;
tmpInfos.lastKickTimestamp = timer.elapsed().total_seconds();
myClientKickCounterList.insert(nick, tmpInfos);
}
else {
//please is already on the list: either raise kickNumber or kickban when kickNumerToBan is reached
if(j.value().kickNumber == kickNumberToBan) {
action = KICKBAN;
}
else {
ClientKickInfos tmpInfos;
tmpInfos.kickNumber = j.value().kickNumber+1;
tmpInfos.lastKickTimestamp = timer.elapsed().total_seconds();
myClientKickCounterList.insert(nick, tmpInfos);
}
}
}
else {
ClientWarnInfos tmpInfos;
tmpInfos.warnLevel = i.value().warnLevel+1;
tmpInfos.lastWarnType = offence;
tmpInfos.nick = nick;
myClientWarnLevelList.insert(playerId, tmpInfos);
action = WARN;
}
}
if(action == WARN) {
switch(offence) {
case BAD_WORD: {
returnMessage = QString ("%1: Warning! No racial, religious, or sexually inflammatory language!\n").arg(nick);
}
break;
case TEXT_FLOOD_LINES: {
returnMessage = QString ("%1: Warning! You've triggered text flood (lines) protection, slow down your typing!\n").arg(nick);
}
break;
case CAPS_FLOOD: {
returnMessage = QString ("%1: Warning: You've triggered caps flood protection, release your caps!\n").arg(nick);
}
break;
case LETTER_REPEATING: {
returnMessage = QString ("%1: Warning: You've triggered letter repeating protection, stop repeating!\n").arg(nick);
}
break;
case URL: {
returnMessage = QString ("%1: Warning: You've triggered url spam protection, stop posting urls!\n").arg(nick);
}
break;
default:;
}
returnAction = QString("warn");
}
else if(action == KICK) {
returnMessage = QString("%1 kicked! Please respect: http://chatrules.pokerth.net\n").arg(nick);
returnAction = QString("kick");
}
else if(action == KICKBAN) {
returnMessage = QString("%1 kicked and banned! Please respect: http://chatrules.pokerth.net\n").arg(nick);
returnAction = QString("kickban");
}
}
else {
returnAction = QString("");
returnMessage = QString("");
}
returnList << returnAction << returnMessage;
return returnList;
} }
void MessageFilter::refreshConfig() { void MessageFilter::refreshConfig() {
// global settings // global settings
warnLevelToKick = config->readConfigInt("WarnLevelToKick"); warnLevelToKick = config->readConfigInt("WarnLevelToKick");
kickNumberToBan = config->readConfigInt("KickNumberToBan");
// special check settings
//Bad Words // special check settings
std::list<std::string> badWordsList = config->readConfigStringList("BadWordsList"); //Bad Words
std::list<std::string>::iterator it1; std::list<std::string> badWordsList = config->readConfigStringList("BadWordsList");
QStringList bwList; std::list<std::string>::iterator it1;
for(it1= badWordsList.begin(); it1 != badWordsList.end(); it1++) { QStringList bwList;
bwList << QString::fromUtf8(it1->c_str()); for(it1= badWordsList.begin(); it1 != badWordsList.end(); it1++) {
} bwList << QString::fromUtf8(it1->c_str());
myBadWordCheck->setBadWords(bwList); }
myBadWordCheck->setBadWords(bwList);
std::list<std::string> urlStringsList = config->readConfigStringList("UrlStringsList");
std::list<std::string>::iterator it2; std::list<std::string> urlStringsList = config->readConfigStringList("UrlStringsList");
QStringList urlList; std::list<std::string>::iterator it2;
for(it2= urlStringsList.begin(); it2 != urlStringsList.end(); it2++) { QStringList urlList;
urlList << QString::fromUtf8(it2->c_str()); for(it2= urlStringsList.begin(); it2 != urlStringsList.end(); it2++) {
} urlList << QString::fromUtf8(it2->c_str());
myUrlCheck->setUrlStrings(urlList); }
myUrlCheck->setUrlStrings(urlList);
std::list<std::string> urlExceptionStringsList = config->readConfigStringList("UrlExceptionStringsList");
std::list<std::string>::iterator it3; std::list<std::string> urlExceptionStringsList = config->readConfigStringList("UrlExceptionStringsList");
QStringList urlExceptionList; std::list<std::string>::iterator it3;
for(it3= urlExceptionStringsList.begin(); it3 != urlExceptionStringsList.end(); it3++) { QStringList urlExceptionList;
urlExceptionList << QString::fromUtf8(it3->c_str()); for(it3= urlExceptionStringsList.begin(); it3 != urlExceptionStringsList.end(); it3++) {
} urlExceptionList << QString::fromUtf8(it3->c_str());
myUrlCheck->setUrlExceptionStrings(urlExceptionList); }
myUrlCheck->setUrlExceptionStrings(urlExceptionList);
myTextFloodCheck->setTextFloodLevelToTrigger(config->readConfigInt("TextFloodLevelToTrigger"));
myCapsFloodCheck->setCapsNumberToTrigger(config->readConfigInt("CapsFloodCapsNumberToTrigger")); myTextFloodCheck->setTextFloodLevelToTrigger(config->readConfigInt("TextFloodLevelToTrigger"));
myLetterRepeatingCheck->setLetterNumberToTrigger(config->readConfigInt("LetterRepeatingNumberToTrigger")); myCapsFloodCheck->setCapsNumberToTrigger(config->readConfigInt("CapsFloodCapsNumberToTrigger"));
myLetterRepeatingCheck->setLetterNumberToTrigger(config->readConfigInt("LetterRepeatingNumberToTrigger"));
} }
void MessageFilter::cleanKickCounterList()
{
QMapIterator<QString, ClientKickInfos> it(myClientKickCounterList);
while (it.hasNext()) {
it.next();
if(timer.elapsed().total_seconds()-it.value().lastKickTimestamp > config->readConfigInt("SecondsToForgetAboutKick")) {
qDebug() << it.key() << "removed from kick counter list" << endl;
myClientKickCounterList.remove(it.key());
}
}
}
+12
View File
@@ -3,6 +3,7 @@
#include <QtCore> #include <QtCore>
#include <stdlib.h> #include <stdlib.h>
#include <third_party/boost/timers.hpp>
class BadWordCheck; class BadWordCheck;
class TextFloodCheck; class TextFloodCheck;
@@ -19,6 +20,7 @@ public:
QStringList check(unsigned, QString, QString); QStringList check(unsigned, QString, QString);
void refreshConfig(); void refreshConfig();
void cleanKickCounterList();
private: private:
BadWordCheck *myBadWordCheck; BadWordCheck *myBadWordCheck;
@@ -32,12 +34,22 @@ private:
int lastWarnType; int lastWarnType;
int warnLevel; int warnLevel;
}; };
struct ClientKickInfos {
size_t lastKickTimestamp;
int kickNumber;
};
QMap<unsigned, ClientWarnInfos> myClientWarnLevelList; QMap<unsigned, ClientWarnInfos> myClientWarnLevelList;
QMap<QString, ClientKickInfos> myClientKickCounterList;
int warnLevelToKick; int warnLevelToKick;
int kickNumberToBan;
CleanerConfig *config; CleanerConfig *config;
boost::timers::portable::second_timer timer;
QTimer *cleanTimer;
}; };
#endif // MESSAGEFILTER_H #endif // MESSAGEFILTER_H