completely changed the NeonSpam settings / scanner management
authorpk910 <philipp@zoelle1.de>
Sat, 22 Oct 2011 22:13:34 +0000 (00:13 +0200)
committerpk910 <philipp@zoelle1.de>
Sat, 22 Oct 2011 22:52:55 +0000 (00:52 +0200)
database.upgrade.sql
src/bot_NeonSpam.c
src/bot_NeonSpam.h
src/cmd_neonspam_set.c
src/event_neonspam_chanmsg.c
src/event_neonspam_join.c
src/mysqlConn.c

index f44c5eed6e8bf7534eff384798aba6ada552411e..dbd063d0f8ce8148f665dffa3886bbd32ecfc2a1 100644 (file)
@@ -18,3 +18,44 @@ ALTER TABLE `owner_history` CHANGE `owner_history_uid` `owner_history_to_uid` IN
 ALTER TABLE `owner_history` ADD `owner_history_from_uid` INT( 11 ) NOT NULL AFTER `owner_history_to_uid`;
 
 -- version: 3
+
+ALTER TABLE `channels`
+  DROP `channel_scanstate`,
+  DROP `channel_scanexcept`,
+  DROP `channel_maxrepeat`,
+  DROP `channel_repeatreaction`,
+  DROP `channel_maxflood`,
+  DROP `channel_floodtime`,
+  DROP `channel_floodreaction`,
+  DROP `channel_maxjoin`,
+  DROP `channel_jointime`,
+  DROP `channel_joinreaction`;
+
+ALTER TABLE `channels`  
+  ADD `channel_scanner` VARCHAR(50) NULL,  
+  ADD `channel_spam_limit` SMALLINT(3) NULL,  
+  ADD `channel_spam_reaction` TINYINT(1) NULL,  
+  ADD `channel_spam_reaction_duration` MEDIUMINT(7) NULL,  
+  ADD `channel_spam_except` SMALLINT(3) NULL,  
+  ADD `channel_flood_limit` SMALLINT(3) NULL,  
+  ADD `channel_flood_time` SMALLINT(3) NULL,  
+  ADD `channel_flood_reaction` TINYINT(1) NULL,  
+  ADD `channel_flood_reaction_duration` MEDIUMINT(7) NULL,  
+  ADD `channel_flood_except` SMALLINT(3) NULL,  
+  ADD `channel_join_limit` SMALLINT(3) NULL,  
+  ADD `channel_join_time` SMALLINT(3) NULL,  
+  ADD `channel_join_reaction` TINYINT(1) NULL,  
+  ADD `channel_join_reaction_duration` MEDIUMINT(7) NULL,  
+  ADD `channel_join_except` SMALLINT(3) NULL,  
+  ADD `channel_botnet_bantime` MEDIUMINT(7) NULL,  
+  ADD `channel_botnet_except` SMALLINT(3) NULL,  
+  ADD `channel_caps_percent` TINYINT(3) NULL,  
+  ADD `channel_caps_reaction` TINYINT(1) NULL,  
+  ADD `channel_caps_reaction_duration` MEDIUMINT(7) NULL,  
+  ADD `channel_caps_except` SMALLINT(3) NULL,  
+  ADD `channel_digit_percent` TINYINT(3) NULL,  
+  ADD `channel_digit_reaction` TINYINT(1) NULL,  
+  ADD `channel_digit_reaction_duration` MEDIUMINT(7) NULL,  
+  ADD `channel_digit_except` SMALLINT(3) NULL;
+  
+-- version: 4
\ No newline at end of file
index fdfd9147a7ab947742757cd755a42423f19ce52e..911c9b8cad4cac7f0cffdf836a18b4da0bd81be0 100644 (file)
@@ -44,6 +44,7 @@ static const struct default_language_entry msgtab[] = {
     {NULL, NULL}
 };
 
+static unsigned int convertNeonSpamSettingsToFlags(char *str);
 static int loadNeonSpamSettings(struct ChanNode *chan);
 static void createSpamNode(struct ChanUser *chanuser);
 static void freeJoinNode(struct NeonSpamJoinNode *joinnode);
@@ -131,6 +132,38 @@ static void start_bots() {
     }
 }
 
+char* convertNeonSpamSettingsToString(unsigned int flags, char *buffer) {
+    int pos = 0;
+    unsigned int i;
+    int j = 0;
+    char *chars = SPAMSETTINGS_CHARS;
+    for(i = 1; i <= SPAMSETTINGS_FLAGS; i = i << 1) {
+        if(flags & i)
+            buffer[pos++] = chars[j];
+        j++;
+    }
+    buffer[pos] = '\0';
+    return buffer;
+}
+
+static unsigned int convertNeonSpamSettingsToFlags(char *str) {
+    unsigned int i = 1, flags = 0;
+    int j = 0;
+    char *chars = SPAMSETTINGS_CHARS;
+    while(*str) {
+        for(; i <= SPAMSETTINGS_FLAGS; i = i << 1) {
+            if(*str == chars[j]) {
+                flags |= i;
+                j++;
+                break;
+            }
+            j++;
+        }
+        str++;
+    }
+    return flags;
+}
+
 static int loadNeonSpamSettings(struct ChanNode *chan) {
     if(chan->spam_settings) return 0;
     struct NeonSpamSettings *settings = malloc(sizeof(*settings));
@@ -141,21 +174,27 @@ static int loadNeonSpamSettings(struct ChanNode *chan) {
     MYSQL_RES *res;
     MYSQL_ROW row, defaults = NULL;
     loadChannelSettings(chan);
-    printf_mysql_query("SELECT `channel_scanstate`, `channel_maxrepeat`, `channel_maxflood`, `channel_floodtime`, `channel_maxjoin`, `channel_jointime`, `channel_scanexcept` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+    printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
     res = mysql_use();
     row = mysql_fetch_row(res);
-    if(!row[0] || !row[1] || !row[2] || !row[3] || !row[4] || !row[5]) {
-        printf_mysql_query("SELECT `channel_scanstate`, `channel_maxrepeat`, `channel_maxflood`, `channel_floodtime`, `channel_maxjoin`, `channel_jointime`, `channel_scanexcept` FROM `channels` WHERE `channel_name` = 'defaults'");
+    if(!row[0] || !row[1] || !row[2] || !row[3] || !row[4] || !row[5] || !row[6] || !row[7] || !row[8] || !row[9] || !row[10] || !row[11] || !row[12]) {
+        printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_name` = 'defaults'");
         res = mysql_use();
         defaults = mysql_fetch_row(res);
     }
-    settings->flags = atoi(row[0] ? row[0] : defaults[0]);
+    settings->flags = convertNeonSpamSettingsToFlags(row[0] ? row[0] : defaults[0]);
     settings->spam_amount = atoi(row[1] ? row[1] : defaults[1]);
-    settings->flood_amount = atoi(row[2] ? row[2] : defaults[2]);
-    settings->flood_time = atoi(row[3] ? row[3] : defaults[3]);
-    settings->join_amount = atoi(row[4] ? row[4] : defaults[4]);
-    settings->join_time = atoi(row[5] ? row[5] : defaults[5]);
-    settings->exceptlevel = atoi(row[6] ? row[6] : defaults[6]);
+    settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] = atoi(row[2] ? row[2] : defaults[2]);
+    settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX] = atoi(row[3] ? row[3] : defaults[3]);
+    settings->sensibility_time[SPAMSETTINGS_FLOODSENINDEX] = atoi(row[4] ? row[4] : defaults[4]);
+    settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] = atoi(row[5] ? row[5] : defaults[5]);
+    settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX] = atoi(row[6] ? row[6] : defaults[6]);
+    settings->sensibility_time[SPAMSETTINGS_JOINSENINDEX] = atoi(row[7] ? row[7] : defaults[7]);
+    settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] = atoi(row[8] ? row[8] : defaults[8]);
+    settings->percent[SPAMSETTINGS_CAPSPERCENTINDEX] = atoi(row[9] ? row[9] : defaults[9]);
+    settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] = atoi(row[10] ? row[10] : defaults[10]);
+    settings->percent[SPAMSETTINGS_DIGITPERCENTINDEX] = atoi(row[11] ? row[11] : defaults[11]);
+    settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] = atoi(row[12] ? row[12] : defaults[12]);
     settings->join_nodes = NULL;
     settings->lastmsg_time = 0;
     int i;
index 77fb4eefc07da03771581e14480a60fe7ab85be8..e3a32ef9884108a822480e33b603a1f86786fc28 100644 (file)
 
 #include "main.h"
 
-#define SPAMSETTINGS_SPAMSCAN       0x0001
-#define SPAMSETTINGS_FLOODSCAN      0x0002
-#define SPAMSETTINGS_JOINSCAN       0x0004
-#define SPAMSETTINGS_SCANOPS        0x0008
-#define SPAMSETTINGS_SCANVOICE      0x0010
-#define SPAMSETTINGS_BOTNETSCAN     0x0020
-#define SPAMSETTINGS_KICKEDBOTQUEUE 0x0040
+//SPAMSCAN
+#define SPAMSETTINGS_SPAMSCAN           0x000001
+#define SPAMSETTINGS_SPAMSCAN_OPS       0x000002
+#define SPAMSETTINGS_SPAMSCAN_VOICE     0x000004
+#define SPAMSETTINGS_SPAMCHARS          "abc"
+#define SPAMSETTINGS_SPAMEXCINDEX       0
+
+//FLOODSCAN
+#define SPAMSETTINGS_FLOODSCAN          0x000008
+#define SPAMSETTINGS_FLOODSCAN_OPS      0x000010
+#define SPAMSETTINGS_FLOODSCAN_VOICE    0x000020
+#define SPAMSETTINGS_FLOODCHARS         "def"
+#define SPAMSETTINGS_FLOODEXCINDEX      1
+#define SPAMSETTINGS_FLOODSENINDEX      0
+
+//JOINSCAN
+#define SPAMSETTINGS_JOINSCAN           0x000040
+#define SPAMSETTINGS_JOINSCAN_OPS       0x000080
+#define SPAMSETTINGS_JOINSCAN_VOICE     0x000100
+#define SPAMSETTINGS_JOINCHARS          "ghi"
+#define SPAMSETTINGS_JOINEXCINDEX       2
+#define SPAMSETTINGS_JOINSENINDEX       1
+
+//BOTNET SCAN
+#define SPAMSETTINGS_BOTNETSCAN         0x000200
+#define SPAMSETTINGS_BOTNETSCAN_OPS     0x000400
+#define SPAMSETTINGS_BOTNETSCAN_VOICE   0x000800
+#define SPAMSETTINGS_BOTNETSCAN_STRIPCC 0x001000
+#define SPAMSETTINGS_BOTNETCHARS        "jklm"
+#define SPAMSETTINGS_BOTNETEXCINDEX     3
+
+//CAPSSCAN
+#define SPAMSETTINGS_CAPSSCAN           0x002000
+#define SPAMSETTINGS_CAPSSCAN_OPS       0x004000
+#define SPAMSETTINGS_CAPSSCAN_VOICE     0x008000
+#define SPAMSETTINGS_CAPSCHARS          "nop"
+#define SPAMSETTINGS_CAPSEXCINDEX       4
+#define SPAMSETTINGS_CAPSPERCENTINDEX   0
+
+//DIGITSCAN
+#define SPAMSETTINGS_DIGITSCAN          0x010000
+#define SPAMSETTINGS_DIGITSCAN_OPS      0x020000
+#define SPAMSETTINGS_DIGITSCAN_VOICE    0x040000
+#define SPAMSETTINGS_DIGITCHARS         "qrs"
+#define SPAMSETTINGS_DIGITEXCINDEX      5
+#define SPAMSETTINGS_DIGITPERCENTINDEX  1
+
+
+#define SPAMSETTINGS_CHARS     SPAMSETTINGS_SPAMCHARS SPAMSETTINGS_FLOODCHARS SPAMSETTINGS_JOINCHARS SPAMSETTINGS_BOTNETCHARS SPAMSETTINGS_CAPSCHARS SPAMSETTINGS_DIGITCHARS
+#define SPAMSETTINGS_FLAGS              0x07ffff /* all flags that can be stored in the database */
+#define SPAMSETTINGS_EXCEPTINDEXES      6
+#define SPAMSETTINGS_SENSIBILITYINDEXES 2
+#define SPAMSETTINGS_PERCENTINDEXES     2
+
+//SCRIPT FLAGS
+#define SPAMSETTINGS_KICKEDBOTQUEUE     0x080000
+#define SPAMSETTINGS_ISTIMEBAN          0x100000
+#define SPAMSETTINGS_SETTIMEBAN         0x200000
 
 #define MAX_FLOOD_AMOUNT 300
 #define MIN_FLOOD_AMOUNT 2
 struct NeonSpamSettings {
     unsigned int flags;
     unsigned char spam_amount;
-    unsigned char flood_amount;
-    unsigned char flood_time;
-    unsigned char join_amount;
-    unsigned char join_time;
-    unsigned int exceptlevel : 10;
+    unsigned char sensibility_amount[SPAMSETTINGS_SENSIBILITYINDEXES];
+    unsigned char sensibility_time[SPAMSETTINGS_SENSIBILITYINDEXES];
+    unsigned int exceptlevel[SPAMSETTINGS_EXCEPTINDEXES];
+    unsigned char percent[SPAMSETTINGS_PERCENTINDEXES];
     
     //joinflood
     struct NeonSpamJoinNode *join_nodes;
@@ -88,5 +138,6 @@ void loop_NeonSpam();
 void free_NeonSpam();
 
 void freeNeonSpamSettings(struct NeonSpamSettings *settings);
+char* convertNeonSpamSettingsToString(unsigned int flags, char *buffer);
 
 #endif
\ No newline at end of file
index 41e78253c473421a2a52a2703fa9c5b8fa56ab99..9890a6272493150a56f4082fcf59fbc9391a1e3f 100644 (file)
 
 #include "cmd_neonspam.h"
 
-typedef char* neonspam_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static void neonspam_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *argument);
-static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_set_spamreaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_set_floodreaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setjoinfloodreaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setspamscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setfloodscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setjoinfloodscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setbotnetscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setscanchanops(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setscanvoiced(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setexceptlevel(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setfloodsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-static char* neonspam_cmd_setjoinsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument);
-
-#define NS_VALID_FUNCTION 0x01
-#define NS_VALID_STRING   0x02
-#define NS_VALID_ACCESS   0x04
-#define NS_VALID_NO501    0x08
-#define NS_VALID_OPTIONS  0x10
-#define NS_VALID_NUMERIC  0x20
-#define NS_VALID_BOOLEAN  0x40
-
-#define NS_HAS_OPT  0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */
-#define NS_HAS_HELP 0x200 /* help    (SET_HELP_{NAME}) - only shown if help is requested */
+typedef char* neonspam_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_setflags(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
+static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
 
 static MYSQL_ROW neonspam_settings_row, neonspam_settings_defaults;
-#define SPAMSERV_SETTINGS_QUERY "`channel_scanstate`, `channel_scanexcept`, `channel_maxrepeat`, `channel_repeatreaction`, `channel_maxflood`, `channel_floodtime`, `channel_floodreaction`, `channel_maxjoin`, `channel_jointime`, `channel_joinreaction`"
-#define SPAMSERV_SETTINGS_RESET "`channel_scanstate` = NULL, `channel_scanexcept` = NULL, `channel_maxrepeat` = NULL, `channel_repeatreaction` = NULL, `channel_maxflood` = NULL, `channel_floodtime` = NULL, `channel_floodreaction` = NULL, `channel_maxjoin` = NULL, `channel_jointime` = NULL, `channel_joinreaction` = NULL"
+#define SPAMSERV_SETTINGS_QUERY "`channel_spam_reaction`, `channel_spam_reaction_duration`, `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_join_reaction`, `channel_join_reaction_duration`, `channel_botnet_bantime`, `channel_caps_reaction`, `channel_caps_reaction_duration`, `channel_digit_reaction`, `channel_digit_reaction_duration`"
+#define SPAMSERV_SETTINGS_RESET "\
+`channel_scanner` = NULL, \
+`channel_spam_limit` = NULL, \
+`channel_spam_reaction` = NULL, \
+`channel_spam_reaction_duration` = NULL, \
+`channel_spam_except` = NULL, \
+`channel_flood_limit` = NULL, \
+`channel_flood_time` = NULL, \
+`channel_flood_reaction` = NULL, \
+`channel_flood_reaction_duration` = NULL, \
+`channel_flood_except` = NULL, \
+`channel_join_limit` = NULL, \
+`channel_join_time` = NULL, \
+`channel_join_reaction` = NULL, \
+`channel_join_reaction_duration` = NULL, \
+`channel_join_except` = NULL, \
+`channel_botnet_bantime` = NULL, \
+`channel_botnet_except` = NULL, \
+`channel_caps_percent` = NULL, \
+`channel_caps_reaction` = NULL, \
+`channel_caps_reaction_duration` = NULL, \
+`channel_caps_except` = NULL,\
+`channel_digit_percent` = NULL, \
+`channel_digit_reaction` = NULL, \
+`channel_digit_reaction_duration` = NULL, \
+`channel_digit_except` = NULL "
 
 static const struct {
+    unsigned int if_flag;
+    unsigned int indent;
     const char *setting;
-    const char *chanfield;
-    unsigned int valid;
-    void *parameter;
     void *function;
+    int intparam;
+    char *charparam;
 } neonspam_settings[] = {
-    {"Trigger",           NULL,  NS_VALID_FUNCTION,                                 NULL, neonspam_cmd_set_trigger},
-    {"SpamLimit",         NULL,  NS_VALID_OPTIONS | NS_VALID_FUNCTION | NS_HAS_OPT, "5",  neonspam_cmd_set_spamlimit},
-    {"SpamReaction",      NULL,  NS_VALID_OPTIONS | NS_VALID_FUNCTION | NS_HAS_OPT, "3",  neonspam_cmd_set_spamreaction},
-    {"FloodReaction",     NULL,  NS_VALID_OPTIONS | NS_VALID_FUNCTION | NS_HAS_OPT, "3",  neonspam_cmd_set_floodreaction},
-    {"JoinFloodReaction", NULL,  NS_VALID_OPTIONS | NS_VALID_FUNCTION | NS_HAS_OPT, "3",  neonspam_cmd_setjoinfloodreaction},
-    {"SpamScan",          NULL,  NS_VALID_BOOLEAN | NS_VALID_FUNCTION,              NULL, neonspam_cmd_setspamscan},
-    {"FloodScan",         NULL,  NS_VALID_BOOLEAN | NS_VALID_FUNCTION,              NULL, neonspam_cmd_setfloodscan},
-    {"JoinFloodScan",     NULL,  NS_VALID_BOOLEAN | NS_VALID_FUNCTION,              NULL, neonspam_cmd_setjoinfloodscan},
-    {"BotNetScan",        NULL,  NS_VALID_BOOLEAN | NS_VALID_FUNCTION,              NULL, neonspam_cmd_setbotnetscan},
-    {"ScanChanOps",       NULL,  NS_VALID_BOOLEAN | NS_VALID_FUNCTION,              NULL, neonspam_cmd_setscanchanops},
-    {"ScanVoiced",        NULL,  NS_VALID_BOOLEAN | NS_VALID_FUNCTION,              NULL, neonspam_cmd_setscanvoiced},
-    {"ExceptLevel",       NULL,  NS_VALID_ACCESS | NS_VALID_FUNCTION,               NULL, neonspam_cmd_setexceptlevel},
-    {"FloodSensibility",  NULL,  NS_VALID_FUNCTION,                                 NULL, neonspam_cmd_setfloodsensibility},
-    {"JoinSensibility",   NULL,  NS_VALID_FUNCTION,                                 NULL, neonspam_cmd_setjoinsensibility},
-    {NULL, NULL, 0, NULL}
+    {0,                                                0,  "Trigger",           neonspam_cmd_set_trigger,         0,                              NULL},
+    
+    {0,                                                0,  "SpamScan",          neonspam_cmd_setflags,            SPAMSETTINGS_SPAMSCAN,          NULL},
+    {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamLimit",         neonspam_cmd_set_spamlimit,       0,                              NULL},
+    {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_SETTIMEBAN,  2,  "SpamReaction",      neonspam_cmd_set_reaction,        0,                              "channel_spam_reaction"},
+    {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_ISTIMEBAN,   4,  "SpamBanDuration",   neonspam_cmd_set_reaction_time,   1,                              "channel_spam_reaction_duration"},
+    {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamScanChanOps",   neonspam_cmd_setflags,            SPAMSETTINGS_SPAMSCAN_OPS,      NULL},
+    {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamScanVoiced",    neonspam_cmd_setflags,            SPAMSETTINGS_SPAMSCAN_VOICE,    NULL},
+    {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamScanExcept",    neonspam_cmd_setexcept,           SPAMSETTINGS_SPAMEXCINDEX,      "channel_spam_except"},
+    
+    {0,                                                0,  "FloodScan",         neonspam_cmd_setflags,            SPAMSETTINGS_FLOODSCAN,         NULL},
+    {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodSensibility",  neonspam_cmd_setsensibility,      SPAMSETTINGS_FLOODSENINDEX,     "channel_flood_"},
+    {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_SETTIMEBAN, 2,  "FloodReaction",     neonspam_cmd_set_reaction,        2,                              "channel_flood_reaction"},
+    {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_ISTIMEBAN,  4,  "FloodBanDuration",  neonspam_cmd_set_reaction_time,   3,                              "channel_flood_reaction_duration"},
+    {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodScanChanOps",  neonspam_cmd_setflags,            SPAMSETTINGS_FLOODSCAN_OPS,     NULL},
+    {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodScanVoiced",   neonspam_cmd_setflags,            SPAMSETTINGS_FLOODSCAN_VOICE,   NULL},
+    {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodScanExcept",   neonspam_cmd_setexcept,           SPAMSETTINGS_FLOODEXCINDEX,     "channel_flood_except"},
+    
+    {0,                                                0,  "JoinScan",          neonspam_cmd_setflags,            SPAMSETTINGS_JOINSCAN,          NULL},
+    {SPAMSETTINGS_JOINSCAN,                            2,  "JoinSensibility",   neonspam_cmd_setsensibility,      SPAMSETTINGS_JOINSENINDEX,      "channel_join_"},
+    {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_SETTIMEBAN,  2,  "JoinReaction",      neonspam_cmd_set_reaction,        4,                              "channel_join_reaction"},
+    {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_ISTIMEBAN,   4,  "JoinBanDuration",   neonspam_cmd_set_reaction_time,   5,                              "channel_join_reaction_duration"},
+    {SPAMSETTINGS_JOINSCAN,                            2,  "JoinScanChanOps",   neonspam_cmd_setflags,            SPAMSETTINGS_JOINSCAN_OPS,      NULL},
+    {SPAMSETTINGS_JOINSCAN,                            2,  "JoinScanVoiced",    neonspam_cmd_setflags,            SPAMSETTINGS_JOINSCAN_VOICE,    NULL},
+    {SPAMSETTINGS_JOINSCAN,                            2,  "JoinScanExcept",    neonspam_cmd_setexcept,           SPAMSETTINGS_JOINEXCINDEX,      "channel_join_except"},
+    
+    {0,                                                0,  "BotNetScan",        neonspam_cmd_setflags,            SPAMSETTINGS_BOTNETSCAN,        NULL},
+    {SPAMSETTINGS_BOTNETSCAN,                          4,  "BotNetBanDuration", neonspam_cmd_set_reaction_time,   6,                              "channel_botnet_bantime"},
+    {SPAMSETTINGS_BOTNETSCAN,                          2,  "BotNetScanChanOps", neonspam_cmd_setflags,            SPAMSETTINGS_BOTNETSCAN_OPS,    NULL},
+    {SPAMSETTINGS_BOTNETSCAN,                          2,  "BotNetScanVoiced",  neonspam_cmd_setflags,            SPAMSETTINGS_BOTNETSCAN_VOICE,  NULL},
+    //{SPAMSETTINGS_BOTNETSCAN,                          2,  "BotNetScanExcept",  neonspam_cmd_setexcept,           SPAMSETTINGS_BOTNETEXCINDEX,    "channel_botnet_except"},
+    
+    {0,                                                0,  "CapsScan",          neonspam_cmd_setflags,            SPAMSETTINGS_CAPSSCAN,          NULL},
+    {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsPercent",       neonspam_cmd_setpercent,          SPAMSETTINGS_CAPSPERCENTINDEX,  "channel_caps_percent"},
+    {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_SETTIMEBAN,  2,  "CapsReaction",      neonspam_cmd_set_reaction,        7,                              "channel_caps_reaction"},
+    {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_ISTIMEBAN,   4,  "CapsBanDuration",   neonspam_cmd_set_reaction_time,   8,                              "channel_caps_reaction_duration"},
+    {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsScanChanOps",   neonspam_cmd_setflags,            SPAMSETTINGS_CAPSSCAN_OPS,      NULL},
+    {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsScanVoiced",    neonspam_cmd_setflags,            SPAMSETTINGS_CAPSSCAN_VOICE,    NULL},
+    {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsScanExcept",    neonspam_cmd_setexcept,           SPAMSETTINGS_CAPSEXCINDEX,      "channel_caps_except"},
+    
+    {0,                                                0,  "DigitScan",         neonspam_cmd_setflags,            SPAMSETTINGS_DIGITSCAN,         NULL},
+    {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitPercent",      neonspam_cmd_setpercent,          SPAMSETTINGS_DIGITPERCENTINDEX, "channel_digit_percent"},
+    {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_SETTIMEBAN, 2,  "DigitReaction",     neonspam_cmd_set_reaction,        9,                              "channel_digit_reaction"},
+    {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_ISTIMEBAN,  4,  "DigitBanDuration",  neonspam_cmd_set_reaction_time,   10,                             "channel_digit_reaction_duration"},
+    {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitScanChanOps",  neonspam_cmd_setflags,            SPAMSETTINGS_DIGITSCAN_OPS,     NULL},
+    {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitScanVoiced",   neonspam_cmd_setflags,            SPAMSETTINGS_DIGITSCAN_VOICE,   NULL},
+    {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitScanExcept",   neonspam_cmd_setexcept,           SPAMSETTINGS_DIGITEXCINDEX,     "channel_digit_except"},
+    
+    {0, 0, NULL, NULL, 0, NULL}
 };
 
 #define MAX_QUERY_LEN 1024
@@ -107,10 +149,19 @@ CMD_BIND(neonspam_cmd_set) {
         i = 0;
         j = 0;
         char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
+        neonspam_settings_row = NULL;
+        neonspam_settings_defaults = NULL;
         while(neonspam_settings[i].setting) {
             if(!stricmp(neonspam_settings[i].setting, argv[0])) {
                 //setting found
-                neonspam_cmd_set_setting(client, user, chan, event, i, args);
+                char valueBuf[MAXLEN];
+                char *value;
+                neonspam_cmd_set_function *func = neonspam_settings[i].function;
+                value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, args, valueBuf);
+                if(value) {
+                    reply(getTextBot(), user, "\002%s\002 %s", neonspam_settings[i].setting, value);
+                    //TODO: reply valid options
+                }
                 j = 1;
                 break;
             }
@@ -121,12 +172,12 @@ CMD_BIND(neonspam_cmd_set) {
             reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]);
         }
     } else {
-        char *value, *org_value, *tmp, nameBuf[64];
+        char valueBuf[MAXLEN], nameBuf[MAXLEN];
+        char *value;
+        int namePos, boolflag = 0;
         MYSQL_RES *res, *defaults_res;
         struct Table *table;
         char *content[2];
-        char query[MAXLEN];
-        int querypos;
         i = 0;
         while(neonspam_settings[i].setting)
             i++;
@@ -138,43 +189,26 @@ CMD_BIND(neonspam_cmd_set) {
         printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
         res = mysql_use();
         neonspam_settings_row = mysql_fetch_row(res);
-        i = 0;
-        j = 0;
+        i = -1;
         reply(getTextBot(), user, "NS_SET_HEADER", chan->name);
-        while(neonspam_settings[i].setting) {
-            char valueBuf[MAXLEN];
-            if(neonspam_settings[i].valid & NS_VALID_FUNCTION) {
-                neonspam_cmd_set_function *func = neonspam_settings[i].function;
-                org_value = func(client, user, chan, event, NULL, NULL, valueBuf);
-            } else
-                org_value = "0";
-            value = org_value;
-            if(neonspam_settings[i].valid & NS_VALID_BOOLEAN) {
-                if(!strcmp(value, "0"))
-                    value = get_language_string(user, "NS_SET_OFF");
-                else
-                    value = get_language_string(user, "NS_SET_ON");
+        while(neonspam_settings[++i].setting) {
+            if((chan->spam_settings->flags & (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS)) != (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS))
+                continue;
+            if((neonspam_settings[i].if_flag & SPAMSETTINGS_ISTIMEBAN) && !boolflag)
+                continue;
+            namePos = 0;
+            for(j = 0; j < neonspam_settings[i].indent; j++) {
+                nameBuf[namePos++] = ' ';
             }
-            strcpy(query, value);
-            querypos = strlen(query);
-            if(neonspam_settings[i].valid & NS_HAS_OPT) {
-                sprintf(nameBuf, "NS_SET_OPTION_%s_%s", neonspam_settings[i].setting, org_value);
-                tmp = get_language_string(user, nameBuf);
-                if(tmp) {
-                    querypos += sprintf(query+querypos, " - %s", tmp);
-                }
-            }
-            if(argc && neonspam_settings[i].valid & NS_HAS_HELP) {
-                sprintf(nameBuf, "NS_SET_HELP_%s", neonspam_settings[i].setting);
-                tmp = get_language_string(user, nameBuf);
-                if(tmp) {
-                    querypos += sprintf(query+querypos, " - %s", tmp);
-                }
-            }
-            content[0] = (char*)neonspam_settings[i].setting;
-            content[1] = query;
+            neonspam_cmd_set_function *func = neonspam_settings[i].function;
+            value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, NULL, valueBuf);
+            if(neonspam_settings[i].if_flag & SPAMSETTINGS_SETTIMEBAN)
+                boolflag = !strcmp(value, "2");
+            //TODO: append option or help info
+            sprintf(nameBuf + namePos, "%s", neonspam_settings[i].setting);
+            content[0] = nameBuf;
+            content[1] = value;
             table_add(table, content);
-            i++;
         }
         char **table_lines = table_end(table);
         for(i = 0; i < table->entrys; i++) {
@@ -184,115 +218,7 @@ CMD_BIND(neonspam_cmd_set) {
     }
 }
 
-static void neonspam_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *args) {
-    char *value;
-    char valueBuf[MAXLEN];
-    char nameBuf[64];
-    //get current value
-    MYSQL_RES *res;
-    printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
-    res = mysql_use();
-    neonspam_settings_row = mysql_fetch_row(res);
-    printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_name` = 'defaults'");
-    res = mysql_use();
-    neonspam_settings_defaults = mysql_fetch_row(res);
-    if(neonspam_settings[setting].valid & NS_VALID_FUNCTION) {
-        neonspam_cmd_set_function *func = neonspam_settings[setting].function;
-        if(!(value = func(client, user, chan, event, NULL, NULL, valueBuf)))
-            return;
-    } else
-        value = "0";
-    if(args) {
-        //change the channel setting
-        //check the new argument
-        int valid = neonspam_settings[setting].valid;
-        if(valid & NS_VALID_STRING) {
-            if(!strcmp(args, "*")) {
-                args = "";
-            }
-        }
-        if(valid & NS_VALID_ACCESS) {
-            int caccess = atoi(args);
-            int max = ((valid & NS_VALID_NO501) ? 500 : 501);
-            if(caccess < 0 || caccess > max) {
-                reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
-                return;
-            }
-            int uaccess = getChannelAccess(user, chan, 0);
-            if(uaccess == 500) uaccess++;
-            if(atoi(value) > uaccess) {
-                if(isGodMode(user)) {
-                    event->flags |= CMDFLAG_OPLOG;
-                } else {
-                    reply(getTextBot(), user, "NS_SET_CANNOT_SET");
-                    return;
-                }
-            }
-            if(caccess > uaccess) {
-                if(isGodMode(user)) {
-                    event->flags |= CMDFLAG_OPLOG;
-                } else {
-                    reply(getTextBot(), user, "NS_SET_BADLEVEL");
-                    return;
-                }
-            }
-            sprintf(nameBuf, "%d", caccess);
-            args = nameBuf;
-        }
-        if(valid & NS_VALID_OPTIONS) {
-            int options = atoi((char *) neonspam_settings[setting].parameter);
-            int coption = atoi(args);
-            if(coption < 0 || coption >= options) {
-                reply(getTextBot(), user, "NS_SET_INVALID_OPTION", coption);
-                int i;
-                int nameBufPos = 0;
-                if(valid & NS_HAS_OPT) {
-                    for(i = 0; i < options; i++) {
-                        sprintf(nameBuf, "NS_SET_OPTION_%s_%d", neonspam_settings[setting].setting, i);
-                        reply(getTextBot(), user, "\002%d\002 - %s", i, get_language_string(user, nameBuf));
-                    }
-                } else {
-                    for(i = 0; i < options; i++) {
-                        nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i);
-                    }
-                    if(nameBufPos) {
-                        nameBuf[nameBufPos-2] = '\0';
-                        reply(getTextBot(), user, nameBuf);
-                    }
-                }
-                return;
-            }
-        }
-        if(valid & NS_VALID_NUMERIC) {
-            sprintf(nameBuf, "%d", atoi(args));
-            args = nameBuf;
-        }
-        if(valid & NS_VALID_BOOLEAN) {
-            if(!strcmp(args, "0") || !stricmp(args, "off") || !stricmp(args, get_language_string(user, "NS_SET_OFF"))) {
-                args = "0";
-            } else if(!strcmp(args, "1") || !stricmp(args, "on") || !stricmp(args, get_language_string(user, "NS_SET_ON"))) {
-                args = "1";
-            } else {
-                reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", args);
-                return;
-            }
-        }
-        //valid - set it
-        if(valid & NS_VALID_FUNCTION) {
-            neonspam_cmd_set_function *func = neonspam_settings[setting].function;
-            strcpy(valueBuf, value);
-            if(!(value = func(client, user, chan, event, neonspam_settings[setting].setting, valueBuf, args)))
-                return;
-        }
-    }
-    reply(getTextBot(), user, "\002%s\002 %s", neonspam_settings[setting].setting, value);
-    if(neonspam_settings[setting].valid & NS_HAS_HELP) {
-         sprintf(nameBuf, "NS_SET_HELP_%s", neonspam_settings[setting].setting);
-         reply(getTextBot(), user, "  %s", get_language_string(user, nameBuf));
-    }
-}
-
-static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
+static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) {
     char *trigger;
     //get current trigger
     MYSQL_RES *res;
@@ -301,7 +227,7 @@ static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNo
     res = mysql_use();
     row = mysql_fetch_row(res);
     trigger = row[0];
-    if(cvalue && argument) {
+    if(argument) {
         int uaccess = getChannelAccess(user, chan, 0);
         if(uaccess < 500) {
             if(isGodMode(user)) {
@@ -321,202 +247,137 @@ static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNo
     return trigger;
 }
 
-static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = (neonspam_settings_row[2] ? neonspam_settings_row[2] : neonspam_settings_defaults[2]);
-    }
-    else if(argument) {
-        //change value
-        printf_mysql_query("UPDATE `channels` SET `channel_maxrepeat` = '%d' WHERE `channel_id` = '%d' ", atoi(argument), chan->channel_id);
-        sprintf(cvalue, "%d", atoi(argument));
-        if(chan->spam_settings)
-            chan->spam_settings->spam_amount = atoi(argument);
-    }
-    return cvalue;
-}
-
-static char* neonspam_cmd_set_spamreaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = (neonspam_settings_row[3] ? neonspam_settings_row[3] : neonspam_settings_defaults[3]);
-    }
-    else if(argument) {
-        //change value
-        printf_mysql_query("UPDATE `channels` SET `channel_repeatreaction` = '%d' WHERE `channel_id` = '%d' ", atoi(argument), chan->channel_id);
-        sprintf(cvalue, "%d", atoi(argument));
-    }
-    return cvalue;
-}
-
-static char* neonspam_cmd_set_floodreaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = (neonspam_settings_row[6] ? neonspam_settings_row[6] : neonspam_settings_defaults[6]);
-    }
-    else if(argument) {
-        //change value
-        printf_mysql_query("UPDATE `channels` SET `channel_floodreaction` = '%d' WHERE `channel_id` = '%d' ", atoi(argument), chan->channel_id);
-        sprintf(cvalue, "%d", atoi(argument));
-    }
-    return cvalue;
-}
-
-static char* neonspam_cmd_setjoinfloodreaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = (neonspam_settings_row[9] ? neonspam_settings_row[9] : neonspam_settings_defaults[9]);
-    }
-    else if(argument) {
-        //change value
-        printf_mysql_query("UPDATE `channels` SET `channel_joinreaction` = '%d' WHERE `channel_id` = '%d' ", atoi(argument), chan->channel_id);
-        sprintf(cvalue, "%d", atoi(argument));
-    }
-    return cvalue;
-}
-
-static char* neonspam_cmd_setspamscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = ((atoi(neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]) & SPAMSETTINGS_SPAMSCAN) ? "1" : "0");
-    }
-    else if(argument) {
-        //change value
-        int cflags = atoi((neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]));
-        if(!strcmp(argument, "0"))
-            cflags &= ~SPAMSETTINGS_SPAMSCAN;
-        else
-            cflags |= SPAMSETTINGS_SPAMSCAN;
-        printf_mysql_query("UPDATE `channels` SET `channel_scanstate` = '%d' WHERE `channel_id` = '%d' ", cflags, chan->channel_id);
-        cvalue = argument;
-        if(chan->spam_settings)
-            chan->spam_settings->flags = cflags;
-    }
-    return cvalue;
-}
-
-static char* neonspam_cmd_setfloodscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = ((atoi(neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]) & SPAMSETTINGS_FLOODSCAN) ? "1" : "0");
-    }
-    else if(argument) {
-        //change value
-        int cflags = atoi((neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]));
-        if(!strcmp(argument, "0"))
-            cflags &= ~SPAMSETTINGS_FLOODSCAN;
-        else
-            cflags |= SPAMSETTINGS_FLOODSCAN;
-        printf_mysql_query("UPDATE `channels` SET `channel_scanstate` = '%d' WHERE `channel_id` = '%d' ", cflags, chan->channel_id);
-        cvalue = argument;
-        if(chan->spam_settings)
-            chan->spam_settings->flags = cflags;
-    }
-    return cvalue;
-}
-
-static char* neonspam_cmd_setjoinfloodscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = ((atoi(neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]) & SPAMSETTINGS_JOINSCAN) ? "1" : "0");
-    }
-    else if(argument) {
-        //change value
-        int cflags = atoi((neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]));
-        if(!strcmp(argument, "0"))
-            cflags &= ~SPAMSETTINGS_JOINSCAN;
-        else
-            cflags |= SPAMSETTINGS_JOINSCAN;
-        printf_mysql_query("UPDATE `channels` SET `channel_scanstate` = '%d' WHERE `channel_id` = '%d' ", cflags, chan->channel_id);
-        cvalue = argument;
-        if(chan->spam_settings)
-            chan->spam_settings->flags = cflags;
+static char* neonspam_cmd_setflags(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) {
+    char *value = ((chan->spam_settings->flags & flag) ? "1" : "0");
+    if(argument) {
+        //binary argument...
+        if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) {
+            chan->spam_settings->flags &= ~flag;
+        } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) {
+            chan->spam_settings->flags |= flag;
+        } else {
+            reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument);
+            return NULL;
+        }
+        char str_flags[50];
+        convertNeonSpamSettingsToString(chan->spam_settings->flags, str_flags);
+        printf_mysql_query("UPDATE `channels` SET `channel_scanner` = '%s' WHERE `channel_id` = '%d' ", str_flags, chan->channel_id);
+        value = argument;
     }
-    return cvalue;
+    return value;
 }
 
-static char* neonspam_cmd_setbotnetscan(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = ((atoi(neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]) & SPAMSETTINGS_BOTNETSCAN) ? "1" : "0");
-    }
-    else if(argument) {
-        //change value
-        int cflags = atoi((neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]));
-        if(!strcmp(argument, "0"))
-            cflags &= ~SPAMSETTINGS_BOTNETSCAN;
-        else
-            cflags |= SPAMSETTINGS_BOTNETSCAN;
-        printf_mysql_query("UPDATE `channels` SET `channel_scanstate` = '%d' WHERE `channel_id` = '%d' ", cflags, chan->channel_id);
-        cvalue = argument;
-        if(chan->spam_settings)
-            chan->spam_settings->flags = cflags;
+static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int exceptlvl_index, char *field, char *argument, char *retBuf) {
+    unsigned int value = chan->spam_settings->exceptlevel[exceptlvl_index];
+    if(argument) {
+        //numeric argument... (access)
+        int caccess = atoi(argument);
+        if(caccess < 0 || caccess > 501) {
+            reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
+            return NULL;
+        }
+        int uaccess = getChannelAccess(user, chan, 0);
+        if(uaccess == 500) uaccess++;
+        if(caccess > uaccess) {
+            if(isGodMode(user)) {
+                event->flags |= CMDFLAG_OPLOG;
+            } else {
+                reply(getTextBot(), user, "NS_SET_CANNOT_SET");
+                return NULL;
+            }
+        }
+        if(caccess > uaccess) {
+            if(isGodMode(user)) {
+                event->flags |= CMDFLAG_OPLOG;
+            } else {
+                reply(getTextBot(), user, "NS_SET_BADLEVEL");
+                return NULL;
+            }
+        }
+        value = caccess;
+        chan->spam_settings->exceptlevel[exceptlvl_index] = value;
+        printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", field, value, chan->channel_id);
     }
-    return cvalue;
+    sprintf(retBuf, "%u", value);
+    return retBuf;
 }
 
-static char* neonspam_cmd_setscanchanops(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = ((atoi(neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]) & SPAMSETTINGS_SCANOPS) ? "1" : "0");
-    }
-    else if(argument) {
-        //change value
-        int cflags = atoi((neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]));
-        if(!strcmp(argument, "0"))
-            cflags &= ~SPAMSETTINGS_SCANOPS;
-        else
-            cflags |= SPAMSETTINGS_SCANOPS;
-        printf_mysql_query("UPDATE `channels` SET `channel_scanstate` = '%d' WHERE `channel_id` = '%d' ", cflags, chan->channel_id);
-        cvalue = argument;
-        if(chan->spam_settings)
-            chan->spam_settings->flags = cflags;
+static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) {
+    if(argument) {
+        /* valid options:
+        * 0/kick - kick
+        * 1/kickban - kickban
+        * 2/ban - timed ban
+        */
+        if(!strcmp(argument, "0") || !stricmp(argument, "kick")) {
+            argument = "0";
+        } else if(!strcmp(argument, "1") || !stricmp(argument, "kickban")) {
+            argument = "1";
+        } else if(!strcmp(argument, "2") || !stricmp(argument, "ban")) {
+            argument = "2";
+        } else {
+            reply(getTextBot(), user, "NS_SET_INVALID_OPTION_STR", argument);
+            return NULL;
+        }
+        printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id);
+        return argument;
+    } else {
+        if(neonspam_settings_row) {
+            return (neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]);
+        } else {
+            MYSQL_RES *res;
+            MYSQL_ROW row;
+            printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id);
+            res = mysql_use();
+            row = mysql_fetch_row(res);
+            return row[0];
+        }
     }
-    return cvalue;
 }
 
-static char* neonspam_cmd_setscanvoiced(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = ((atoi(neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]) & SPAMSETTINGS_SCANVOICE) ? "1" : "0");
-    }
-    else if(argument) {
-        //change value
-        int cflags = atoi((neonspam_settings_row[0] ? neonspam_settings_row[0] : neonspam_settings_defaults[0]));
-        if(!strcmp(argument, "0"))
-            cflags &= ~SPAMSETTINGS_SCANVOICE;
-        else
-            cflags |= SPAMSETTINGS_SCANVOICE;
-        printf_mysql_query("UPDATE `channels` SET `channel_scanstate` = '%d' WHERE `channel_id` = '%d' ", cflags, chan->channel_id);
-        cvalue = argument;
-        if(chan->spam_settings)
-            chan->spam_settings->flags = cflags;
+static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) {
+    int duration;
+    if(argument) {
+        duration = strToTime(user, argument);
+        if(duration < 30) {
+            reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30);
+            return NULL;
+        }
+        printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id);
+    } else {
+        if(neonspam_settings_row) {
+            duration = atoi(neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]);
+        } else {
+            MYSQL_RES *res;
+            MYSQL_ROW row;
+            printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id);
+            res = mysql_use();
+            row = mysql_fetch_row(res);
+            duration = atoi(row[0]);
+        }
     }
-    return cvalue;
+    timeToStr(user, duration, 3, retBuf);
+    return retBuf;
 }
 
-static char* neonspam_cmd_setexceptlevel(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        cvalue = (neonspam_settings_row[1] ? neonspam_settings_row[1] : neonspam_settings_defaults[1]);
-    }
-    else if(argument) {
-        //change value
-        printf_mysql_query("UPDATE `channels` SET `channel_scanexcept` = '%d' WHERE `channel_id` = '%d' ", atoi(argument), chan->channel_id);
-        sprintf(cvalue, "%d", atoi(argument));
-        if(chan->spam_settings)
-            chan->spam_settings->exceptlevel = atoi(argument);
+static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int percent_index, char *mysqlfield, char *argument, char *retBuf) {
+    unsigned int value = chan->spam_settings->percent[percent_index];
+    if(argument) {
+        //numeric argument... (access)
+        value = atoi(argument);
+        if(value < 0 || value > 100) {
+            //invalid percent value
+            return NULL;
+        }
+        chan->spam_settings->percent[percent_index] = value;
+        printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", mysqlfield, value, chan->channel_id);
     }
-    return cvalue;
+    sprintf(retBuf, "%u", value);
+    return retBuf;
 }
 
-static char* neonspam_cmd_setfloodsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        sprintf(argument, "%s:%s", (neonspam_settings_row[4] ? neonspam_settings_row[4] : neonspam_settings_defaults[4]), (neonspam_settings_row[5] ? neonspam_settings_row[5] : neonspam_settings_defaults[5]));
-        cvalue = argument;
-    }
-    else if(argument) {
+static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int sensibility_index, char *mysqlfield, char *argument, char *retBuf) {
+    if(argument) {
         //change value
         char *delimiter = strstr(argument, ":");
         if(!delimiter) {
@@ -535,50 +396,33 @@ static char* neonspam_cmd_setfloodsensibility(struct ClientSocket *client, struc
             //invalid time period
             return NULL;
         }
-        printf_mysql_query("UPDATE `channels` SET `channel_maxflood` = '%d', `channel_floodtime` = '%d' WHERE `channel_id` = '%d' ", amount, timep, chan->channel_id);
-        sprintf(cvalue, "%d:%d", amount, timep);
-        if(chan->spam_settings) {
-            chan->spam_settings->flood_amount = amount;
-            chan->spam_settings->flood_time = timep;
-        }
+        char amountfield[50], timefield[50];
+        sprintf(amountfield, "%s%s", mysqlfield, "limit");
+        sprintf(timefield, "%s%s", mysqlfield, "time");
+        printf_mysql_query("UPDATE `channels` SET `%s` = '%d', `%s` = '%d' WHERE `channel_id` = '%d' ", amountfield, amount, timefield, timep, chan->channel_id);
+        sprintf(retBuf, "%d:%d", amount, timep);
+        chan->spam_settings->sensibility_amount[sensibility_index] = amount;
+        chan->spam_settings->sensibility_time[sensibility_index] = timep;
+    } else {
+        sprintf(retBuf, "%d:%d", chan->spam_settings->sensibility_amount[sensibility_index], chan->spam_settings->sensibility_time[sensibility_index]);
     }
-    return cvalue;
+    return retBuf;
 }
 
-static char* neonspam_cmd_setjoinsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *cvalue, char *argument) {
-    if(!cvalue) {
-        //get current value
-        sprintf(argument, "%s:%s", (neonspam_settings_row[7] ? neonspam_settings_row[7] : neonspam_settings_defaults[7]), (neonspam_settings_row[8] ? neonspam_settings_row[8] : neonspam_settings_defaults[8]));
-        cvalue = argument;
-    }
-    else if(argument) {
+static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) {
+    if(argument) {
         //change value
-        char *delimiter = strstr(argument, ":");
-        if(!delimiter) {
-            //invalid format
-            return NULL;
-        }
-        *delimiter = '\0';
-        delimiter++;
         int amount = atoi(argument);
-        int timep = atoi(delimiter);
-        if(amount > MAX_JOIN_AMOUNT || amount < MIN_JOIN_AMOUNT) {
+        if(amount > MAX_FLOOD_AMOUNT || amount < MIN_FLOOD_AMOUNT) {
             //invalid amount
             return NULL;
         }
-        if(timep > MAX_JOIN_TIME || timep < 0) {
-            //invalid time period
-            return NULL;
-        }
-        printf_mysql_query("UPDATE `channels` SET `channel_maxjoin` = '%d', `channel_jointime` = '%d' WHERE `channel_id` = '%d' ", amount, timep, chan->channel_id);
-        sprintf(cvalue, "%d:%d", amount, timep);
-        if(chan->spam_settings) {
-            chan->spam_settings->join_amount = amount;
-            chan->spam_settings->join_time = timep;
-        }
-    }
-    return cvalue;
+        printf_mysql_query("UPDATE `channels` SET `channel_maxrepeat` = '%d' WHERE `channel_id` = '%d' ", amount, chan->channel_id);
+        sprintf(retBuf, "%d", amount);
+        chan->spam_settings->spam_amount = amount;
+    } else
+        sprintf(retBuf, "%d", chan->spam_settings->spam_amount);
+    return retBuf;
 }
 
-
 #undef MAX_QUERY_LEN
index 7bcd4b5016dcc6526cb31cee7f0d147c88791bed..b7f124fbf8154ed3f7f0069d5ab752e12674d4ac 100644 (file)
@@ -20,17 +20,18 @@ static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser
 static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message);
 
 static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup);
-static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action, char *reason, char *reaction);
+static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish);
 
 struct neonspam_event_chanmsg_cache {
     struct ClientSocket *client;
     struct ChanUser *chanuser;
     struct NeonSpamSettings *settings;
-    int action;
-    char *reason;
-    char *reaction;
+    unsigned int warn;
+    unsigned int punish;
 };
 
+
+
 static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
     struct ClientSocket *client = getChannelBot(chan, BOTID);
     if(!client) return; //we can't "see" this event
@@ -38,57 +39,50 @@ static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan,
     struct NeonSpamSettings *settings = chan->spam_settings;
     struct ChanUser *chanuser = getChanUser(user, chan);
     if(!settings || !chanuser) return;
-    
-    //ignore messages from ops/voices if we ignore them
-    if(!(settings->flags & SPAMSETTINGS_SCANOPS) && (chanuser->flags & CHANUSERFLAG_OPPED)) return;
-    if(!(settings->flags & SPAMSETTINGS_SCANVOICE) && (chanuser->flags & CHANUSERFLAG_VOICED)) return;
-    if(settings->exceptlevel == 0) return;
+    #define NEONSPAM_CHANMSG_DO_SCANOPS(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_OPPED))
+    #define NEONSPAM_CHANMSG_DO_SCANVOICE(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_VOICED))
+    #define NEONSPAM_CHANMSG_DO_EXCEPT(INDEX) (settings->exceptlevel[INDEX] != 0)
+    #define NEONSPAM_CHANMSG_NEED_WHO(INDEX) (settings->exceptlevel[INDEX] != 501)
     //scan the message
     int result = 0;
-    int action = SPAMSERV_CHECK_IGNORE;
-    char reason[MAXLEN];
-    char *reaction = NULL;
-    if(action != SPAMSERV_CHECK_PUNISH && (settings->flags & SPAMSETTINGS_SPAMSCAN)) {
+    unsigned int warn = 0;
+    unsigned int punish = 0;
+    int needwho = 0;
+    if((settings->flags & SPAMSETTINGS_SPAMSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_SPAMSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_SPAMSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_SPAMEXCINDEX)) {
         result = neonspam_spamscan(settings, chanuser, message);
         switch(result) {
             case SPAMSERV_CHECK_IGNORE:
                 break;
             case SPAMSERV_CHECK_WARN:
-                if(action == SPAMSERV_CHECK_IGNORE) {
-                    action = result;
-                    sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM);
-                }
+                warn |= SPAMSETTINGS_SPAMSCAN;
+                if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX))
+                    needwho = 1;
                 break;
             case SPAMSERV_CHECK_PUNISH:
-                if(action != SPAMSERV_CHECK_PUNISH) {
-                    action = result;
-                    sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM);
-                    reaction = "channel_repeatreaction";
-                }
+                punish |= SPAMSETTINGS_SPAMSCAN;
+                if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX))
+                    needwho = 1;
                 break;
         }
     }
-    if(action != SPAMSERV_CHECK_PUNISH && (settings->flags & SPAMSETTINGS_FLOODSCAN)) {
+    if((settings->flags & SPAMSETTINGS_FLOODSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_FLOODSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_FLOODSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_FLOODEXCINDEX)) {
         result = neonspam_floodscan(settings, chanuser);
         switch(result) {
             case SPAMSERV_CHECK_IGNORE:
                 break;
             case SPAMSERV_CHECK_WARN:
-                if(action == SPAMSERV_CHECK_IGNORE) {
-                    action = result;
-                    sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD);
-                }
+                warn |= SPAMSETTINGS_FLOODSCAN;
+                if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX))
+                    needwho = 1;
                 break;
             case SPAMSERV_CHECK_PUNISH:
-                if(action != SPAMSERV_CHECK_PUNISH) {
-                    action = result;
-                    sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD);
-                    reaction = "channel_floodreaction";
-                }
+                punish |= SPAMSETTINGS_FLOODSCAN;
+                if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX))
+                    needwho = 1;
                 break;
         }
     }
-    if(action != SPAMSERV_CHECK_PUNISH && (settings->flags & SPAMSETTINGS_BOTNETSCAN)) {
+    if((settings->flags & SPAMSETTINGS_BOTNETSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_BOTNETSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_BOTNETSCAN_VOICE)) {
         result = neonspam_botnetscan(client, settings, chanuser, message);
         switch(result) {
             case SPAMSERV_CHECK_DEAD:
@@ -99,10 +93,10 @@ static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan,
     }
     //some other checks?
     
-    if(action != SPAMSERV_CHECK_IGNORE) {
+    if(warn || punish) {
         //whois the user to check against exceptlevel
-        if((user->flags & USERFLAG_ISAUTHED) || settings->exceptlevel == 501) {
-            neonspam_event_chanmsg_punish(client, chanuser, settings, action, reason, reaction);
+        if(!needwho || (user->flags & USERFLAG_ISAUTHED)) {
+            neonspam_event_chanmsg_punish(client, chanuser, settings, warn, punish);
         } else {
             struct neonspam_event_chanmsg_cache *cache = malloc(sizeof(*cache));
             if (!cache) {
@@ -112,72 +106,92 @@ static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan,
             cache->client = client;
             cache->chanuser = chanuser;
             cache->settings = settings;
-            cache->action = action;
-            cache->reason = strdup(reason);
-            cache->reaction = reaction;
+            cache->warn = warn;
+            cache->punish = punish;
             get_userauth(user, neonspam_event_chanmsg_nick_lookup, cache);
         }
         
     }
+    #undef NEONSPAM_CHANMSG_DO_SCANOPS
+    #undef NEONSPAM_CHANMSG_DO_SCANVOICE
+    #undef NEONSPAM_CHANMSG_DO_EXCEPT
+    #undef NEONSPAM_CHANMSG_NEED_WHO
 }
 
 static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup) {
     struct neonspam_event_chanmsg_cache *cache = data;
-    neonspam_event_chanmsg_punish(cache->client, cache->chanuser, cache->settings, cache->action, cache->reason, cache->reaction);
-    free(cache->reason);
+    neonspam_event_chanmsg_punish(cache->client, cache->chanuser, cache->settings, cache->warn, cache->punish);
     free(cache);
 }
 
-static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action, char *reason, char *reaction) {
+static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish) {
+    MYSQL_RES *res;
+    MYSQL_ROW row;
+    loadChannelSettings(chanuser->chan);
     int uaccess = 0;
     if(chanuser->user->flags & USERFLAG_ISAUTHED)
         uaccess = getChannelAccess(chanuser->user, chanuser->chan, 0);
-    if(uaccess >= settings->exceptlevel) return;
-    if(action == SPAMSERV_CHECK_WARN) {
-        reply(client, chanuser->user, "%s", reason);
-    } else if(action == SPAMSERV_CHECK_PUNISH) {
-        loadChannelSettings(chanuser->chan);
-        int reactionid;
-        if(!(reactionid = atoi(reaction))) {
-            MYSQL_RES *res;
-            MYSQL_ROW row;
-            printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", reaction, chanuser->chan->channel_id);
+    char reason[MAXLEN];
+    reason[0] = '\0';
+    int punishment = 0;
+    int punish_time = 0;
+    if(!punishment && (punish & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) {
+        printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
+        res = mysql_use();
+        row = mysql_fetch_row(res);
+        if(!row[0]) {
+            printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'");
             res = mysql_use();
             row = mysql_fetch_row(res);
-            if(!row[0]) {
-                printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", reaction);
-                res = mysql_use();
-                row = mysql_fetch_row(res);
-            }
-            reactionid = atoi(row[0]);
         }
-            
-        int duration = 0;
+        sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM);
+        punishment = atoi(row[0]) + 1;
+        punish_time = atoi(row[1]);
+    }
+    if(!punishment && (punish & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) {
+        printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
+        res = mysql_use();
+        row = mysql_fetch_row(res);
+        if(!row[0]) {
+            printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'");
+            res = mysql_use();
+            row = mysql_fetch_row(res);
+        }
+        sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD);
+        punishment = atoi(row[0]) + 1;
+        punish_time = atoi(row[1]);
+    }
+    if(!punishment && (warn & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) {
+        sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM);
+    }
+    if(!punishment && (warn & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) {
+        sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD);
+    }
+    if(punishment) {
         char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
         char *banmask = NULL;
-        switch (reactionid) {
-            case 2: //TIMEBAN: 3min
-                duration = 180;
+        switch (punishment) {
             case 3: //TIMEBAN: 1h
-                if(!duration)
-                    duration = 3600;
                 banmask = generate_banmask(chanuser->user, banmaskBuf);
-                printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason));
-                int banid = (int) mysql_insert_id(mysql_conn);
-                char nameBuf[MAXLEN];
-                char banidBuf[20];
-                sprintf(nameBuf, "ban_%d", banid);
-                sprintf(banidBuf, "%d", banid);
-                timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
-            case 1: //KICKBAN
+                printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (punish_time ? (time(0) + punish_time) : 0), 0, escape_string(reason));
+                if(punish_time) {
+                    int banid = (int) mysql_insert_id(mysql_conn);
+                    char nameBuf[MAXLEN];
+                    char banidBuf[20];
+                    sprintf(nameBuf, "ban_%d", banid);
+                    sprintf(banidBuf, "%d", banid);
+                    timeq_add_name(nameBuf, punish_time, channel_ban_timeout, strdup(banidBuf));
+                }
+            case 2: //KICKBAN
                 if(!banmask)
                     banmask = generate_banmask(chanuser->user, banmaskBuf);
                 putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask);
-            case 0: //KICK
+            case 1: //KICK
                 putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, reason);
                 break;
         }
-    }
+    } else if(*reason)
+        reply(client, chanuser->user, "%s", reason);
 }
 
 static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) {
@@ -204,7 +218,7 @@ static int neonspam_update_penalty(struct NeonSpamSettings *settings, struct Cha
     int last_update = time(0) - chanuser->spamnode->last_penalty_update;
     if(last_update) {
         if(last_update < MAX_FLOOD_TIME && chanuser->spamnode->floodpenalty) {
-            chanuser->spamnode->floodpenalty -= last_update * (MAX_FLOOD_TIME / settings->flood_time);
+            chanuser->spamnode->floodpenalty -= last_update * (MAX_FLOOD_TIME / settings->sensibility_time[SPAMSETTINGS_FLOODSENINDEX]);
             if(chanuser->spamnode->floodpenalty < 0)
                 chanuser->spamnode->floodpenalty = 0;
         } else
@@ -219,9 +233,9 @@ static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser
     if(!chanuser->spamnode)
         createSpamNode(chanuser);
     int messages_pending = neonspam_update_penalty(settings, chanuser, 1);
-    if(messages_pending == settings->flood_amount)
+    if(messages_pending == settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX])
         return SPAMSERV_CHECK_WARN;
-    else if(messages_pending > settings->flood_amount)
+    else if(messages_pending > settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX])
         return SPAMSERV_CHECK_PUNISH;
     else
         return SPAMSERV_CHECK_IGNORE;
index b2639035f75ca6e73593b4c07628eea4b17f73b0..2ef8dbd6d735694a17019e076b1425609eb8f8ae 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 static USERAUTH_CALLBACK(neonspam_event_join_nick_lookup);
-static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action, char *reason, char *reaction);
+static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action);
 static int neonspam_joinfloodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser);
 
 struct neonspam_event_join_cache {
@@ -24,8 +24,6 @@ struct neonspam_event_join_cache {
     struct ChanUser *chanuser;
     struct NeonSpamSettings *settings;
     int action;
-    char *reason;
-    char *reaction;
 };
 
 static void neonspam_event_join(struct ChanUser *chanuser) {
@@ -33,38 +31,13 @@ static void neonspam_event_join(struct ChanUser *chanuser) {
     if(!client) return; //we can't "see" this event
     loadNeonSpamSettings(chanuser->chan);
     struct NeonSpamSettings *settings = chanuser->chan->spam_settings;
-    if(!settings) return;
-    if(settings->exceptlevel == 0) return;
-    //scan the message
-    int result = 0;
-    int action = SPAMSERV_CHECK_IGNORE;
-    char reason[MAXLEN];
-    char *reaction = NULL;
-    if(action != SPAMSERV_CHECK_PUNISH && (settings->flags & SPAMSETTINGS_JOINSCAN)) {
-        result = neonspam_joinfloodscan(settings, chanuser);
-        switch(result) {
-            case SPAMSERV_CHECK_IGNORE:
-                break;
-            case SPAMSERV_CHECK_WARN:
-                if(action == SPAMSERV_CHECK_IGNORE) {
-                    action = result;
-                    sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_JOINFLOOD);
-                }
-                break;
-            case SPAMSERV_CHECK_PUNISH:
-                if(action != SPAMSERV_CHECK_PUNISH) {
-                    action = result;
-                    sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_JOINFLOOD);
-                    reaction = "channel_joinreaction";
-                }
-                break;
-        }
-    }
-    //some other checks?
-    if(action != SPAMSERV_CHECK_IGNORE) {
+    if(!settings || !(settings->flags & SPAMSETTINGS_JOINSCAN)) return;
+    if(settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] == 0) return;
+    int result = neonspam_joinfloodscan(settings, chanuser);
+    if(result != SPAMSERV_CHECK_IGNORE) {
         //whois the user to check against exceptlevel
-        if((chanuser->user->flags & USERFLAG_ISAUTHED) || settings->exceptlevel == 501) {
-            neonspam_event_join_punish(client, chanuser, settings, action, reason, reaction);
+        if((chanuser->user->flags & USERFLAG_ISAUTHED) || settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] == 501) {
+            neonspam_event_join_punish(client, chanuser, settings, result);
         } else {
             struct neonspam_event_join_cache *cache = malloc(sizeof(*cache));
             if (!cache) {
@@ -74,61 +47,57 @@ static void neonspam_event_join(struct ChanUser *chanuser) {
             cache->client = client;
             cache->chanuser = chanuser;
             cache->settings = settings;
-            cache->action = action;
-            cache->reason = strdup(reason);
-            cache->reaction = reaction;
+            cache->action = result;
             get_userauth(chanuser->user, neonspam_event_join_nick_lookup, cache);
         }
-        
     }
 }
 
 static USERAUTH_CALLBACK(neonspam_event_join_nick_lookup) {
     struct neonspam_event_join_cache *cache = data;
-    neonspam_event_join_punish(cache->client, cache->chanuser, cache->settings, cache->action, cache->reason, cache->reaction);
-    free(cache->reason);
+    neonspam_event_join_punish(cache->client, cache->chanuser, cache->settings, cache->action);
     free(cache);
 }
 
-static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action, char *reason, char *reaction) {
+static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action) {
     int uaccess = 0;
     if(chanuser->user->flags & USERFLAG_ISAUTHED)
         uaccess = getChannelAccess(chanuser->user, chanuser->chan, 0);
-    if(uaccess >= settings->exceptlevel) return;
+    if(uaccess >= settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX]) return;
     //scanops / scanvoiced
     MYSQL_RES *res;
     MYSQL_ROW row, defaults = NULL;
     loadChannelSettings(chanuser->chan);
-    printf_mysql_query("SELECT `%s`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", reaction, chanuser->chan->channel_id);
+    printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
     res = mysql_use();
     row = mysql_fetch_row(res);
-    if(!row[0] || !row[1] || !row[2]) {
-        printf_mysql_query("SELECT `%s`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'", reaction);
+    if(!row[0] || !row[1] || !row[2] || !row[3]) {
+        printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
         res = mysql_use();
         defaults = mysql_fetch_row(res);
     }
-    if(!(settings->flags & SPAMSETTINGS_SCANOPS) && uaccess >= atoi((row[1] ? row[1] : defaults[1]))) return;
-    if(!(settings->flags & SPAMSETTINGS_SCANVOICE) && uaccess >= atoi((row[2] ? row[2] : defaults[2]))) return;
+    if(!(settings->flags & SPAMSETTINGS_JOINSCAN_OPS) && uaccess >= atoi((row[2] ? row[2] : defaults[2]))) return;
+    if(!(settings->flags & SPAMSETTINGS_JOINSCAN_VOICE) && uaccess >= atoi((row[3] ? row[3] : defaults[3]))) return;
+    char reason[MAXLEN];
+    sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_JOINFLOOD);
     if(action == SPAMSERV_CHECK_WARN) {
         reply(client, chanuser->user, "%s", reason);
     } else if(action == SPAMSERV_CHECK_PUNISH) {
-        int duration = 0;
+        int duration = atoi((row[1] ? row[1] : defaults[1]));
         char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
         char *banmask = NULL;
         switch (atoi((row[0] ? row[0] : defaults[0]))) {
-            case 2: //TIMEBAN: 3min
-                duration = 180;
             case 3: //TIMEBAN: 1h
-                if(!duration)
-                    duration = 3600;
                 banmask = generate_banmask(chanuser->user, banmaskBuf);
-                printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason));
-                int banid = (int) mysql_insert_id(mysql_conn);
-                char nameBuf[MAXLEN];
-                char banidBuf[20];
-                sprintf(nameBuf, "ban_%d", banid);
-                sprintf(banidBuf, "%d", banid);
-                timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
+                printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (duration ? (time(0) + duration) : 0), 0, escape_string(reason));
+                if(duration) {
+                    int banid = (int) mysql_insert_id(mysql_conn);
+                    char nameBuf[MAXLEN];
+                    char banidBuf[20];
+                    sprintf(nameBuf, "ban_%d", banid);
+                    sprintf(banidBuf, "%d", banid);
+                    timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
+                }
             case 1: //KICKBAN
                 if(!banmask)
                     banmask = generate_banmask(chanuser->user, banmaskBuf);
@@ -144,7 +113,7 @@ static int neonspam_update_join_penalty(struct NeonSpamSettings *settings, struc
     int last_update = time(0) - joinnode->last_penalty_update;
     if(last_update) {
         if(last_update < MAX_JOIN_TIME && joinnode->joinpenalty) {
-            joinnode->joinpenalty -= last_update * (MAX_JOIN_TIME / settings->join_time);
+            joinnode->joinpenalty -= last_update * (MAX_JOIN_TIME / settings->sensibility_time[SPAMSETTINGS_JOINSENINDEX]);
             if(joinnode->joinpenalty < 0)
                 joinnode->joinpenalty = 0;
         } else
@@ -159,9 +128,9 @@ static int neonspam_joinfloodscan(struct NeonSpamSettings *settings, struct Chan
     if(!chanuser->spamnode)
         createSpamNode(chanuser);
     int joins_pending = neonspam_update_join_penalty(settings, getNeonSpamJoinNode(chanuser), 1);
-    if(joins_pending == settings->join_amount)
+    if(joins_pending == settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX])
         return SPAMSERV_CHECK_WARN;
-    else if(joins_pending > settings->join_amount)
+    else if(joins_pending > settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX])
         return SPAMSERV_CHECK_PUNISH;
     else
         return SPAMSERV_CHECK_IGNORE;
index 437821a5bf81f21ed1c9b3fc7906a14e1081c90b..dfc65a9f042742bc1c5013380b5de71f0834c300 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #include "mysqlConn.h"
-#define DATABASE_VERSION "3"
+#define DATABASE_VERSION "4"
 
 struct used_result {
     MYSQL_RES *result;