fixed cmd_neonspam_set.c neonspam_cmd_set_reaction_time: use converted value...
[NeonServV5.git] / src / modules / NeonSpam.mod / cmd_neonspam_set.c
1 /* cmd_neonspam_set.c - NeonServ v5.6
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "cmd_neonspam.h"
19
20 typedef char* neonspam_cmd_set_function(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
21 static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
22 static char* neonspam_cmd_setflags(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
23 static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
24 static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
25 static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
26 static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
27 static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
28 static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
29 static char* neonspam_cmd_setscanops(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
30 static char* neonspam_cmd_setscanvoice(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
31 static char* neonspam_cmd_setscanexcept(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf);
32
33 static MYSQL_ROW neonspam_settings_row, neonspam_settings_defaults;
34 #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`, `channel_badword_reaction`, `channel_badword_reaction_duration`"
35 #define SPAMSERV_SETTINGS_RESET "\
36 `channel_scanner` = NULL, \
37 `channel_spam_limit` = NULL, \
38 `channel_spam_reaction` = NULL, \
39 `channel_spam_reaction_duration` = NULL, \
40 `channel_spam_except` = NULL, \
41 `channel_flood_limit` = NULL, \
42 `channel_flood_time` = NULL, \
43 `channel_flood_reaction` = NULL, \
44 `channel_flood_reaction_duration` = NULL, \
45 `channel_flood_except` = NULL, \
46 `channel_join_limit` = NULL, \
47 `channel_join_time` = NULL, \
48 `channel_join_reaction` = NULL, \
49 `channel_join_reaction_duration` = NULL, \
50 `channel_join_except` = NULL, \
51 `channel_botnet_bantime` = NULL, \
52 `channel_botnet_except` = NULL, \
53 `channel_caps_percent` = NULL, \
54 `channel_caps_reaction` = NULL, \
55 `channel_caps_reaction_duration` = NULL, \
56 `channel_caps_except` = NULL,\
57 `channel_digit_percent` = NULL, \
58 `channel_digit_reaction` = NULL, \
59 `channel_digit_reaction_duration` = NULL, \
60 `channel_digit_except` = NULL, \
61 `channel_badword_reaction` = NULL, \
62 `channel_badword_reaction_duration` = NULL, \
63 `channel_badword_except` = NULL "
64
65 #define SET_HELP       0x0001
66 #define SET_BOOL       0x0002
67 #define SET_OPT        0x0004
68
69 #define SET_SCANOPS    0x0010
70 #define SET_SCANVOICE  0x0020
71 #define SET_SCANEXCEPT 0x0040
72
73 #define SET_OPT_MAX    0xff00
74 #define SET_OPT_SHIFT  8
75
76 static const struct {
77     unsigned int if_flag;
78     unsigned int indent;
79     const char *setting;
80     void *function;
81     int intparam;
82     char *charparam;
83     int flags;
84 } neonspam_settings[] = {
85     {0,                                                0,  "Trigger",           neonspam_cmd_set_trigger,         0,                              NULL,                             SET_HELP},
86     
87     {0,                                                0,  "SpamScan",          neonspam_cmd_setflags,            SPAMSETTINGS_SPAMSCAN,          NULL,                             SET_BOOL},
88     {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamLimit",         neonspam_cmd_set_spamlimit,       0,                              NULL,                             SET_HELP},
89     {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_SETTIMEBAN,  2,  "SpamReaction",      neonspam_cmd_set_reaction,        0,                              "channel_spam_reaction",          SET_OPT | (3 << SET_OPT_SHIFT)},
90     {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_ISTIMEBAN,   4,  "SpamBanDuration",   neonspam_cmd_set_reaction_time,   1,                              "channel_spam_reaction_duration", 0},
91     {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamScanChanOps",   neonspam_cmd_setflags,            SPAMSETTINGS_SPAMSCAN_OPS,      NULL,                             SET_BOOL | SET_SCANOPS},
92     {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamScanVoiced",    neonspam_cmd_setflags,            SPAMSETTINGS_SPAMSCAN_VOICE,    NULL,                             SET_BOOL | SET_SCANVOICE},
93     {SPAMSETTINGS_SPAMSCAN,                            2,  "SpamScanExcept",    neonspam_cmd_setexcept,           SPAMSETTINGS_SPAMEXCINDEX,      "channel_spam_except",            SET_HELP | SET_SCANEXCEPT},
94     
95     {0,                                                0,  "FloodScan",         neonspam_cmd_setflags,            SPAMSETTINGS_FLOODSCAN,         NULL,                             SET_BOOL},
96     {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodSensibility",  neonspam_cmd_setsensibility,      SPAMSETTINGS_FLOODSENINDEX,     "channel_flood_",                 SET_HELP},
97     {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_SETTIMEBAN, 2,  "FloodReaction",     neonspam_cmd_set_reaction,        2,                              "channel_flood_reaction",         SET_OPT | (3 << SET_OPT_SHIFT)},
98     {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_ISTIMEBAN,  4,  "FloodBanDuration",  neonspam_cmd_set_reaction_time,   3,                              "channel_flood_reaction_duration",0},
99     {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodScanChanOps",  neonspam_cmd_setflags,            SPAMSETTINGS_FLOODSCAN_OPS,     NULL,                             SET_BOOL | SET_SCANOPS},
100     {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodScanVoiced",   neonspam_cmd_setflags,            SPAMSETTINGS_FLOODSCAN_VOICE,   NULL,                             SET_BOOL | SET_SCANVOICE},
101     {SPAMSETTINGS_FLOODSCAN,                           2,  "FloodScanExcept",   neonspam_cmd_setexcept,           SPAMSETTINGS_FLOODEXCINDEX,     "channel_flood_except",           SET_HELP | SET_SCANEXCEPT},
102     
103     {0,                                                0,  "JoinScan",          neonspam_cmd_setflags,            SPAMSETTINGS_JOINSCAN,          NULL,                             SET_BOOL},
104     {SPAMSETTINGS_JOINSCAN,                            2,  "JoinSensibility",   neonspam_cmd_setsensibility,      SPAMSETTINGS_JOINSENINDEX,      "channel_join_",                  SET_HELP},
105     {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_SETTIMEBAN,  2,  "JoinReaction",      neonspam_cmd_set_reaction,        4,                              "channel_join_reaction",          SET_OPT | (3 << SET_OPT_SHIFT)},
106     {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_ISTIMEBAN,   4,  "JoinBanDuration",   neonspam_cmd_set_reaction_time,   5,                              "channel_join_reaction_duration", 0},
107     {SPAMSETTINGS_JOINSCAN,                            2,  "JoinScanChanOps",   neonspam_cmd_setflags,            SPAMSETTINGS_JOINSCAN_OPS,      NULL,                             SET_BOOL | SET_SCANOPS},
108     {SPAMSETTINGS_JOINSCAN,                            2,  "JoinScanVoiced",    neonspam_cmd_setflags,            SPAMSETTINGS_JOINSCAN_VOICE,    NULL,                             SET_BOOL | SET_SCANVOICE},
109     {SPAMSETTINGS_JOINSCAN,                            2,  "JoinScanExcept",    neonspam_cmd_setexcept,           SPAMSETTINGS_JOINEXCINDEX,      "channel_join_except",            SET_HELP | SET_SCANEXCEPT},
110     
111     {0,                                                0,  "BotNetScan",        neonspam_cmd_setflags,            SPAMSETTINGS_BOTNETSCAN,        NULL,                             SET_BOOL},
112     {SPAMSETTINGS_BOTNETSCAN,                          4,  "BotNetBanDuration", neonspam_cmd_set_reaction_time,   6,                              "channel_botnet_bantime",         0},
113     {SPAMSETTINGS_BOTNETSCAN,                          2,  "BotNetScanChanOps", neonspam_cmd_setflags,            SPAMSETTINGS_BOTNETSCAN_OPS,    NULL,                             SET_BOOL | SET_SCANOPS},
114     {SPAMSETTINGS_BOTNETSCAN,                          2,  "BotNetScanVoiced",  neonspam_cmd_setflags,            SPAMSETTINGS_BOTNETSCAN_VOICE,  NULL,                             SET_BOOL | SET_SCANVOICE},
115     //{SPAMSETTINGS_BOTNETSCAN,                          2,  "BotNetScanExcept",  neonspam_cmd_setexcept,           SPAMSETTINGS_BOTNETEXCINDEX,    "channel_botnet_except",          SET_HELP},
116     
117     {0,                                                0,  "CapsScan",          neonspam_cmd_setflags,            SPAMSETTINGS_CAPSSCAN,          NULL,                             SET_BOOL},
118     {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsPercent",       neonspam_cmd_setpercent,          SPAMSETTINGS_CAPSPERCENTINDEX,  "channel_caps_percent",           SET_HELP},
119     {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_SETTIMEBAN,  2,  "CapsReaction",      neonspam_cmd_set_reaction,        7,                              "channel_caps_reaction",          SET_OPT | (3 << SET_OPT_SHIFT)},
120     {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_ISTIMEBAN,   4,  "CapsBanDuration",   neonspam_cmd_set_reaction_time,   8,                              "channel_caps_reaction_duration", 0},
121     {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsScanChanOps",   neonspam_cmd_setflags,            SPAMSETTINGS_CAPSSCAN_OPS,      NULL,                             SET_BOOL | SET_SCANOPS},
122     {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsScanVoiced",    neonspam_cmd_setflags,            SPAMSETTINGS_CAPSSCAN_VOICE,    NULL,                             SET_BOOL | SET_SCANVOICE},
123     {SPAMSETTINGS_CAPSSCAN,                            2,  "CapsScanExcept",    neonspam_cmd_setexcept,           SPAMSETTINGS_CAPSEXCINDEX,      "channel_caps_except",            SET_HELP | SET_SCANEXCEPT},
124     
125     {0,                                                0,  "DigitScan",         neonspam_cmd_setflags,            SPAMSETTINGS_DIGITSCAN,         NULL,                             SET_BOOL},
126     {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitPercent",      neonspam_cmd_setpercent,          SPAMSETTINGS_DIGITPERCENTINDEX, "channel_digit_percent",          SET_HELP},
127     {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_SETTIMEBAN, 2,  "DigitReaction",     neonspam_cmd_set_reaction,        9,                              "channel_digit_reaction",         SET_OPT | (3 << SET_OPT_SHIFT)},
128     {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_ISTIMEBAN,  4,  "DigitBanDuration",  neonspam_cmd_set_reaction_time,   10,                             "channel_digit_reaction_duration", 0},
129     {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitScanChanOps",  neonspam_cmd_setflags,            SPAMSETTINGS_DIGITSCAN_OPS,     NULL,                             SET_BOOL | SET_SCANOPS},
130     {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitScanVoiced",   neonspam_cmd_setflags,            SPAMSETTINGS_DIGITSCAN_VOICE,   NULL,                             SET_BOOL | SET_SCANVOICE},
131     {SPAMSETTINGS_DIGITSCAN,                           2,  "DigitScanExcept",   neonspam_cmd_setexcept,           SPAMSETTINGS_DIGITEXCINDEX,     "channel_digit_except",           SET_HELP | SET_SCANEXCEPT},
132     
133     {0,                                                0,  "BadwordScan",       neonspam_cmd_setflags,            SPAMSETTINGS_BADWORDSCAN,       NULL,                             SET_BOOL},
134     {SPAMSETTINGS_BADWORDSCAN | SPAMSETTINGS_SETTIMEBAN,2, "BadwordReaction",   neonspam_cmd_set_reaction,        11,                             "channel_badword_reaction",       SET_OPT | (3 << SET_OPT_SHIFT)},
135     {SPAMSETTINGS_BADWORDSCAN | SPAMSETTINGS_ISTIMEBAN,4,  "BadwordBanDuration",neonspam_cmd_set_reaction_time,   12,                             "channel_badword_reaction_duration", 0},
136     {SPAMSETTINGS_BADWORDSCAN,                         2,  "BadwordScanChanOps",neonspam_cmd_setflags,            SPAMSETTINGS_BADWORDSCAN_OPS,   NULL,                             SET_BOOL | SET_SCANOPS},
137     {SPAMSETTINGS_BADWORDSCAN,                         2,  "BadwordScanVoiced", neonspam_cmd_setflags,            SPAMSETTINGS_BADWORDSCAN_VOICE, NULL,                             SET_BOOL | SET_SCANVOICE},
138     {SPAMSETTINGS_BADWORDSCAN,                         2,  "BadwordScanExcept", neonspam_cmd_setexcept,           SPAMSETTINGS_BADWORDEXCINDEX,   "channel_badword_except",         SET_HELP | SET_SCANEXCEPT},
139     
140     {0,                                                0,  "GlobalScanChanOps", neonspam_cmd_setscanops,          0,                              NULL,                             SET_BOOL},
141     {0,                                                0,  "GlobalScanVoice",   neonspam_cmd_setscanvoice,        0,                              NULL,                             SET_BOOL},
142     {0,                                                0,  "GlobalScanExcept",  neonspam_cmd_setscanexcept,       0,                              NULL,                             SET_HELP},
143     
144     {0, 0, NULL, NULL, 0, NULL, 0}
145 };
146
147 #define MAX_QUERY_LEN 1024
148 CMD_BIND(neonspam_cmd_set) {
149     int i, j;
150     loadNeonSpamSettings(chan);
151     if(argc && !strcmp(argv[0], "defaults")) {
152         //reset channel settings
153         int uaccess = getChannelAccess(user, chan);
154         if(uaccess < 500) {
155             if(isGodMode(user)) {
156                 event->flags |= CMDFLAG_OPLOG;
157             } else {
158                 reply(textclient, user, "NS_SET_DEFAULTS_OWNER", chan->name);
159                 return;
160             }
161         }
162         int seed = 0;
163         char *tmp;
164         static char defaultskey[16];
165         for(tmp = user->auth; *tmp; tmp++)
166             seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
167         for(tmp = chan->name; *tmp; tmp++)
168             seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
169         sprintf(defaultskey, "%08x", seed);
170         if(argc > 1 && !strcmp(argv[1], defaultskey)) {
171             printf_mysql_query("UPDATE `channels` SET " SPAMSERV_SETTINGS_RESET " WHERE `channel_id` = '%d'", chan->channel_id);
172             reply(textclient, user, "NS_SET_DEFAULTS_DONE", chan->name);
173             logEvent(event);
174         } else {
175             reply(textclient, user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey);
176         }
177     } else if(argc && strcmp(argv[0], "help")) {
178         //find the correct command
179         i = 0;
180         j = 0;
181         char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
182         neonspam_settings_row = NULL;
183         neonspam_settings_defaults = NULL;
184         while(neonspam_settings[i].setting) {
185             if(!stricmp(neonspam_settings[i].setting, argv[0])) {
186                 //setting found
187                 char valueBuf[MAXLEN], nameBuf[MAXLEN];
188                 char *value, *optimized_value, *option_help;
189                 neonspam_cmd_set_function *func = neonspam_settings[i].function;
190                 value = func(client, textclient, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, args, valueBuf);
191                 if(value) {
192                     optimized_value = value;
193                     if(neonspam_settings[i].flags & SET_BOOL) {
194                         if(!strcmp(value, "0"))
195                             optimized_value = get_language_string(user, "NS_SET_OFF");
196                         else if(!strcmp(value, "1"))
197                             optimized_value = get_language_string(user, "NS_SET_ON");
198                     }
199                     if(neonspam_settings[i].flags & SET_OPT) {
200                         sprintf(nameBuf, "SS_SET_OPTION_%s_%s", neonspam_settings[i].setting, value);
201                         option_help = get_language_string(user, nameBuf);
202                     } else
203                         option_help = NULL;
204                     reply(textclient, user, "\002%s\002 %s%s%s", neonspam_settings[i].setting, optimized_value, (option_help ? " - " : ""), (option_help ? option_help : ""));
205                     if(neonspam_settings[i].flags & SET_OPT) {
206                         int maxoption = (neonspam_settings[i].flags & SET_OPT_MAX) >> SET_OPT_SHIFT;
207                         for(j = 0; j < maxoption; j++) {
208                             sprintf(nameBuf, "SS_SET_OPTION_%s_%d", neonspam_settings[i].setting, j);
209                             option_help = get_language_string(user, nameBuf);
210                             reply(textclient, user, " \002%d\002 - %s", j, option_help);
211                         }
212                     }
213                     if((neonspam_settings[i].flags & SET_HELP) && argc && !strcmp(argv[0], "help")) {
214                         char *tmp;
215                         sprintf(nameBuf, "SS_SET_HELP_%s", neonspam_settings[i].setting);
216                         tmp = get_language_string(user, nameBuf);
217                         if(tmp) {
218                             reply(textclient, user, "  %s", tmp);
219                         }
220                     }
221                 }
222                 j = 1;
223                 break;
224             }
225             i++;
226         }
227         if(j == 0) {
228             //unknown setting
229             reply(textclient, user, "NS_SET_UNKNOWN_SETTING", argv[0]);
230         }
231     } else {
232         char valueBuf[MAXLEN], nameBuf[MAXLEN];
233         char *value;
234         int namePos, boolflag = 0;
235         MYSQL_RES *res, *defaults_res;
236         struct Table *table;
237         char *content[2];
238         i = 0;
239         while(neonspam_settings[i].setting)
240             i++;
241         table = table_init(2, i, 0);
242         table_set_bold(table, 0, 1);
243         printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_name` = 'defaults'");
244         defaults_res = mysql_use();
245         neonspam_settings_defaults = mysql_fetch_row(defaults_res);
246         printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
247         res = mysql_use();
248         neonspam_settings_row = mysql_fetch_row(res);
249         i = -1;
250         reply(textclient, user, "NS_SET_HEADER", chan->name);
251         while(neonspam_settings[++i].setting) {
252             if((chan->spam_settings->flags & (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS)) != (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS))
253                 continue;
254             if((neonspam_settings[i].if_flag & SPAMSETTINGS_ISTIMEBAN) && !boolflag)
255                 continue;
256             neonspam_cmd_set_function *func = neonspam_settings[i].function;
257             value = func(client, textclient, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, NULL, valueBuf);
258             if(neonspam_settings[i].if_flag & SPAMSETTINGS_SETTIMEBAN)
259                 boolflag = !strcmp(value, "2");
260             //TODO: append option or help info
261             strcpy(valueBuf, value);
262             if(neonspam_settings[i].flags & SET_BOOL) {
263                 if(!strcmp(value, "0"))
264                     strcpy(valueBuf, get_language_string(user, "NS_SET_OFF"));
265                 else if(!strcmp(value, "1"))
266                     strcpy(valueBuf, get_language_string(user, "NS_SET_ON"));
267             }
268             if(neonspam_settings[i].flags & SET_OPT) {
269                 char *tmp;
270                 sprintf(nameBuf, "SS_SET_OPTION_%s_%s", neonspam_settings[i].setting, value);
271                 tmp = get_language_string(user, nameBuf);
272                 if(tmp) {
273                     sprintf(valueBuf + strlen(valueBuf), " - %s", tmp);
274                 }
275             }
276             if((neonspam_settings[i].flags & SET_HELP) && argc && !strcmp(argv[0], "help")) {
277                 char *tmp;
278                 sprintf(nameBuf, "SS_SET_HELP_%s", neonspam_settings[i].setting);
279                 tmp = get_language_string(user, nameBuf);
280                 if(tmp) {
281                     sprintf(valueBuf + strlen(valueBuf), " - %s", tmp);
282                 }
283             }
284             namePos = 0;
285             for(j = 0; j < neonspam_settings[i].indent; j++) {
286                 nameBuf[namePos++] = ' ';
287             }
288             sprintf(nameBuf + namePos, "%s", neonspam_settings[i].setting);
289             content[0] = nameBuf;
290             content[1] = valueBuf;
291             table_add(table, content);
292         }
293         char **table_lines = table_end(table);
294         for(i = 0; i < table->entrys; i++) {
295             reply(textclient, user, table_lines[i]);
296         }
297         table_free(table);
298     }
299 }
300
301 static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) {
302     char *trigger;
303     //get current trigger
304     MYSQL_RES *res;
305     MYSQL_ROW row;
306     printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid);
307     res = mysql_use();
308     row = mysql_fetch_row(res);
309     trigger = (row[0] ? row[0] : row[1]);
310     if(argument) {
311         int uaccess = getChannelAccess(user, chan);
312         if(uaccess < 500) {
313             if(isGodMode(user)) {
314                 event->flags |= CMDFLAG_OPLOG;
315             } else {
316                 reply(textclient, user, "NS_SET_TRIGGER_OWNER", chan->name);
317                 return NULL;
318             }
319         }
320         if(strlen(argument) > 15)
321             argument[15] = '\0';
322         printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `chanid` = '%d' AND `botid` = '%d'", escape_string(argument), chan->channel_id, client->clientid);
323         trigger = argument;
324         changeChannelTrigger(client->botid, chan, trigger);
325         logEvent(event);
326     }
327     return trigger;
328 }
329
330 static char* neonspam_cmd_setflags(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) {
331     char *value = ((chan->spam_settings->flags & flag) ? "1" : "0");
332     if(argument) {
333         //binary argument...
334         if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) {
335             chan->spam_settings->flags &= ~flag;
336         } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) {
337             chan->spam_settings->flags |= flag;
338         } else {
339             reply(textclient, user, "NS_SET_INVALID_BOOLEAN", argument);
340             return NULL;
341         }
342         char str_flags[50];
343         convertNeonSpamSettingsToString(chan->spam_settings->flags, str_flags);
344         printf_mysql_query("UPDATE `channels` SET `channel_scanner` = '%s' WHERE `channel_id` = '%d' ", str_flags, chan->channel_id);
345         value = argument;
346     }
347     return value;
348 }
349
350 static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int exceptlvl_index, char *field, char *argument, char *retBuf) {
351     unsigned int value = chan->spam_settings->exceptlevel[exceptlvl_index];
352     if(argument) {
353         //numeric argument... (access)
354         int caccess = atoi(argument);
355         if(caccess < 0 || caccess > 501) {
356             reply(textclient, user, "NS_INVALID_ACCESS", caccess);
357             return NULL;
358         }
359         int uaccess = getChannelAccess(user, chan);
360         if(uaccess == 500) uaccess++;
361         if(value > uaccess) {
362             if(isGodMode(user)) {
363                 event->flags |= CMDFLAG_OPLOG;
364             } else {
365                 reply(textclient, user, "NS_SET_CANNOT_SET");
366                 return NULL;
367             }
368         }
369         if(caccess > uaccess) {
370             if(isGodMode(user)) {
371                 event->flags |= CMDFLAG_OPLOG;
372             } else {
373                 reply(textclient, user, "NS_SET_BADLEVEL");
374                 return NULL;
375             }
376         }
377         value = caccess;
378         chan->spam_settings->exceptlevel[exceptlvl_index] = value;
379         printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", field, value, chan->channel_id);
380     }
381     sprintf(retBuf, "%u", value);
382     return retBuf;
383 }
384
385 static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) {
386     if(argument) {
387         /* valid options:
388         * 0/kick - kick
389         * 1/kickban - kickban
390         * 2/ban - timed ban
391         */
392         if(!strcmp(argument, "0") || !stricmp(argument, "kick")) {
393             argument = "0";
394         } else if(!strcmp(argument, "1") || !stricmp(argument, "kickban")) {
395             argument = "1";
396         } else if(!strcmp(argument, "2") || !stricmp(argument, "ban")) {
397             argument = "2";
398         } else {
399             reply(textclient, user, "NS_SET_INVALID_OPTION_STR", argument);
400             return NULL;
401         }
402         printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id);
403         return argument;
404     } else {
405         if(neonspam_settings_row) {
406             return (neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]);
407         } else {
408             MYSQL_RES *res;
409             MYSQL_ROW row;
410             printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id);
411             res = mysql_use();
412             row = mysql_fetch_row(res);
413             return row[0];
414         }
415     }
416 }
417
418 static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) {
419     int duration;
420     if(argument) {
421         duration = strToTime(user, argument);
422         if(duration < 30) {
423             reply(textclient, user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30);
424             return NULL;
425         }
426         printf_mysql_query("UPDATE `channels` SET `%s` = '%d' WHERE `channel_id` = '%d' ", mysqlfield, duration, chan->channel_id);
427     } else {
428         if(neonspam_settings_row) {
429             duration = atoi(neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]);
430         } else {
431             MYSQL_RES *res;
432             MYSQL_ROW row;
433             printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id);
434             res = mysql_use();
435             row = mysql_fetch_row(res);
436             duration = atoi(row[0]);
437         }
438     }
439     timeToStr(user, duration, 3, retBuf);
440     return retBuf;
441 }
442
443 static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int percent_index, char *mysqlfield, char *argument, char *retBuf) {
444     unsigned int value = chan->spam_settings->percent[percent_index];
445     if(argument) {
446         //numeric argument... (access)
447         value = atoi(argument);
448         if(value < 0 || value > 100) {
449             //invalid percent value
450             reply(textclient, user, "SS_SET_PERCENT", value);
451             return NULL;
452         }
453         chan->spam_settings->percent[percent_index] = value;
454         printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", mysqlfield, value, chan->channel_id);
455     }
456     sprintf(retBuf, "%u", value);
457     return retBuf;
458 }
459
460 static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int sensibility_index, char *mysqlfield, char *argument, char *retBuf) {
461     if(argument) {
462         //change value
463         char *delimiter = strstr(argument, ":");
464         if(!delimiter) {
465             //invalid format
466             reply(textclient, user, "SS_SET_SENSIBILITY", argument);
467             return NULL;
468         }
469         *delimiter = '\0';
470         delimiter++;
471         int amount = atoi(argument);
472         int timep = atoi(delimiter);
473         if(amount > MAX_FLOOD_AMOUNT || amount < MIN_FLOOD_AMOUNT) {
474             //invalid amount
475             reply(textclient, user, "SS_SET_SENSIBILITY_AMOUNT", amount, MIN_FLOOD_AMOUNT, MAX_FLOOD_AMOUNT);
476             return NULL;
477         }
478         if(timep > MAX_FLOOD_TIME || timep < 0) {
479             //invalid time period
480             reply(textclient, user, "SS_SET_SENSIBILITY_TIME", timep, 0, MAX_FLOOD_TIME);
481             return NULL;
482         }
483         char amountfield[50], timefield[50];
484         sprintf(amountfield, "%s%s", mysqlfield, "limit");
485         sprintf(timefield, "%s%s", mysqlfield, "time");
486         printf_mysql_query("UPDATE `channels` SET `%s` = '%d', `%s` = '%d' WHERE `channel_id` = '%d' ", amountfield, amount, timefield, timep, chan->channel_id);
487         sprintf(retBuf, "%d:%d", amount, timep);
488         chan->spam_settings->sensibility_amount[sensibility_index] = amount;
489         chan->spam_settings->sensibility_time[sensibility_index] = timep;
490     } else {
491         sprintf(retBuf, "%d:%d", chan->spam_settings->sensibility_amount[sensibility_index], chan->spam_settings->sensibility_time[sensibility_index]);
492     }
493     return retBuf;
494 }
495
496 static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) {
497     if(argument) {
498         //change value
499         int amount = atoi(argument);
500         if(amount > 10 || amount < 2) {
501             //invalid amount
502             reply(textclient, user, "SS_SET_SPAMLIMIT", amount, 2, 10);
503             return NULL;
504         }
505         printf_mysql_query("UPDATE `channels` SET `channel_maxrepeat` = '%d' WHERE `channel_id` = '%d' ", amount, chan->channel_id);
506         sprintf(retBuf, "%d", amount);
507         chan->spam_settings->spam_amount = amount;
508     } else
509         sprintf(retBuf, "%d", chan->spam_settings->spam_amount);
510     return retBuf;
511 }
512
513 static char* neonspam_cmd_setscanops(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) {
514     int i = 0;
515     int value = -1;
516     int identical = 1;
517     while(neonspam_settings[i].setting) {
518         if(neonspam_settings[i].flags & SET_SCANOPS) {
519             if(value == -1)
520                 value = ((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0);
521             else {
522                 if(((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0) != value) {
523                     identical = 0;
524                     break;
525                 }
526             }
527         }
528         i++;
529     }
530     if(argument) {
531         //binary argument...
532         if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) {
533             value = 0;
534         } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) {
535             value = 1;
536         } else {
537             reply(textclient, user, "NS_SET_INVALID_BOOLEAN", argument);
538             return NULL;
539         }
540         i = 0;
541         char valueBuf[MAXLEN];
542         while(neonspam_settings[i].setting) {
543             if(neonspam_settings[i].flags & SET_SCANOPS) {
544                 neonspam_cmd_set_function *func = neonspam_settings[i].function;
545                 func(client, textclient, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, (value ? "1" : "0"), valueBuf);
546             }
547             i++;
548         }
549         identical = 1;
550     }
551     if(identical && value)
552         return "1";
553     if(identical && !value)
554         return "0";
555     return "?";
556 }
557
558 static char* neonspam_cmd_setscanvoice(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) {
559     int i = 0;
560     int value = -1;
561     int identical = 1;
562     while(neonspam_settings[i].setting) {
563         if(neonspam_settings[i].flags & SET_SCANVOICE) {
564             if(value == -1)
565                 value = ((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0);
566             else {
567                 if(((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0) != value) {
568                     identical = 0;
569                     break;
570                 }
571             }
572         }
573         i++;
574     }
575     if(argument) {
576         //binary argument...
577         if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) {
578             value = 0;
579         } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) {
580             value = 1;
581         } else {
582             reply(textclient, user, "NS_SET_INVALID_BOOLEAN", argument);
583             return NULL;
584         }
585         i = 0;
586         char valueBuf[MAXLEN];
587         while(neonspam_settings[i].setting) {
588             if(neonspam_settings[i].flags & SET_SCANVOICE) {
589                 neonspam_cmd_set_function *func = neonspam_settings[i].function;
590                 func(client, textclient, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, (value ? "1" : "0"), valueBuf);
591             }
592             i++;
593         }
594         identical = 1;
595     }
596     if(identical && value)
597         return "1";
598     if(identical && !value)
599         return "0";
600     return "?";
601 }
602
603 static char* neonspam_cmd_setscanexcept(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) {
604     int i = 0;
605     int value = -1;
606     int identical = 1;
607     while(neonspam_settings[i].setting) {
608         if(neonspam_settings[i].flags & SET_SCANEXCEPT) {
609             if(value == -1)
610                 value = chan->spam_settings->exceptlevel[neonspam_settings[i].intparam];
611             else {
612                 if(chan->spam_settings->exceptlevel[neonspam_settings[i].intparam] != value) {
613                     identical = 0;
614                     break;
615                 }
616             }
617         }
618         i++;
619     }
620     if(argument) {
621         //numeric argument... (access)
622         int caccess = atoi(argument);
623         if(caccess < 0 || caccess > 501) {
624             reply(textclient, user, "NS_INVALID_ACCESS", caccess);
625             return NULL;
626         }
627         int uaccess = getChannelAccess(user, chan);
628         if(uaccess == 500) uaccess++;
629         if(identical && value > uaccess) {
630             if(isGodMode(user)) {
631                 event->flags |= CMDFLAG_OPLOG;
632             } else {
633                 reply(textclient, user, "NS_SET_CANNOT_SET");
634                 return NULL;
635             }
636         }
637         if(caccess > uaccess) {
638             if(isGodMode(user)) {
639                 event->flags |= CMDFLAG_OPLOG;
640             } else {
641                 reply(textclient, user, "NS_SET_BADLEVEL");
642                 return NULL;
643             }
644         }
645         i = 0;
646         char valueBuf[MAXLEN];
647         sprintf(retBuf, "%d", caccess);
648         while(neonspam_settings[i].setting) {
649             if(neonspam_settings[i].flags & SET_SCANEXCEPT) {
650                 neonspam_cmd_set_function *func = neonspam_settings[i].function;
651                 func(client, textclient, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, retBuf, valueBuf);
652             }
653             i++;
654         }
655         identical = 1;
656         value = caccess;
657     }
658     if(identical) {
659         sprintf(retBuf, "%d", value);
660         return retBuf;
661     }
662     return "?";
663 }
664
665 #undef MAX_QUERY_LEN