1 /* cmd_neonspam_set.c - NeonServ v5.1
2 * Copyright (C) 2011 Philipp Kreil (pk910)
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.
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.
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/>.
18 #include "cmd_neonspam.h"
20 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);
21 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);
22 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);
23 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);
24 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);
25 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);
26 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);
27 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);
28 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);
30 static MYSQL_ROW neonspam_settings_row, neonspam_settings_defaults;
31 #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`"
32 #define SPAMSERV_SETTINGS_RESET "\
33 `channel_scanner` = NULL, \
34 `channel_spam_limit` = NULL, \
35 `channel_spam_reaction` = NULL, \
36 `channel_spam_reaction_duration` = NULL, \
37 `channel_spam_except` = NULL, \
38 `channel_flood_limit` = NULL, \
39 `channel_flood_time` = NULL, \
40 `channel_flood_reaction` = NULL, \
41 `channel_flood_reaction_duration` = NULL, \
42 `channel_flood_except` = NULL, \
43 `channel_join_limit` = NULL, \
44 `channel_join_time` = NULL, \
45 `channel_join_reaction` = NULL, \
46 `channel_join_reaction_duration` = NULL, \
47 `channel_join_except` = NULL, \
48 `channel_botnet_bantime` = NULL, \
49 `channel_botnet_except` = NULL, \
50 `channel_caps_percent` = NULL, \
51 `channel_caps_reaction` = NULL, \
52 `channel_caps_reaction_duration` = NULL, \
53 `channel_caps_except` = NULL,\
54 `channel_digit_percent` = NULL, \
55 `channel_digit_reaction` = NULL, \
56 `channel_digit_reaction_duration` = NULL, \
57 `channel_digit_except` = NULL "
66 } neonspam_settings[] = {
67 {0, 0, "Trigger", neonspam_cmd_set_trigger, 0, NULL},
69 {0, 0, "SpamScan", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN, NULL},
70 {SPAMSETTINGS_SPAMSCAN, 2, "SpamLimit", neonspam_cmd_set_spamlimit, 0, NULL},
71 {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "SpamReaction", neonspam_cmd_set_reaction, 0, "channel_spam_reaction"},
72 {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "SpamBanDuration", neonspam_cmd_set_reaction_time, 1, "channel_spam_reaction_duration"},
73 {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN_OPS, NULL},
74 {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN_VOICE, NULL},
75 {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_SPAMEXCINDEX, "channel_spam_except"},
77 {0, 0, "FloodScan", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN, NULL},
78 {SPAMSETTINGS_FLOODSCAN, 2, "FloodSensibility", neonspam_cmd_setsensibility, SPAMSETTINGS_FLOODSENINDEX, "channel_flood_"},
79 {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "FloodReaction", neonspam_cmd_set_reaction, 2, "channel_flood_reaction"},
80 {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "FloodBanDuration", neonspam_cmd_set_reaction_time, 3, "channel_flood_reaction_duration"},
81 {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN_OPS, NULL},
82 {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN_VOICE, NULL},
83 {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_FLOODEXCINDEX, "channel_flood_except"},
85 {0, 0, "JoinScan", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN, NULL},
86 {SPAMSETTINGS_JOINSCAN, 2, "JoinSensibility", neonspam_cmd_setsensibility, SPAMSETTINGS_JOINSENINDEX, "channel_join_"},
87 {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "JoinReaction", neonspam_cmd_set_reaction, 4, "channel_join_reaction"},
88 {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "JoinBanDuration", neonspam_cmd_set_reaction_time, 5, "channel_join_reaction_duration"},
89 {SPAMSETTINGS_JOINSCAN, 2, "JoinScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN_OPS, NULL},
90 {SPAMSETTINGS_JOINSCAN, 2, "JoinScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN_VOICE, NULL},
91 {SPAMSETTINGS_JOINSCAN, 2, "JoinScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_JOINEXCINDEX, "channel_join_except"},
93 {0, 0, "BotNetScan", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN, NULL},
94 {SPAMSETTINGS_BOTNETSCAN, 4, "BotNetBanDuration", neonspam_cmd_set_reaction_time, 6, "channel_botnet_bantime"},
95 {SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN_OPS, NULL},
96 {SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN_VOICE, NULL},
97 //{SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_BOTNETEXCINDEX, "channel_botnet_except"},
99 {0, 0, "CapsScan", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN, NULL},
100 {SPAMSETTINGS_CAPSSCAN, 2, "CapsPercent", neonspam_cmd_setpercent, SPAMSETTINGS_CAPSPERCENTINDEX, "channel_caps_percent"},
101 {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "CapsReaction", neonspam_cmd_set_reaction, 7, "channel_caps_reaction"},
102 {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "CapsBanDuration", neonspam_cmd_set_reaction_time, 8, "channel_caps_reaction_duration"},
103 {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN_OPS, NULL},
104 {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN_VOICE, NULL},
105 {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_CAPSEXCINDEX, "channel_caps_except"},
107 {0, 0, "DigitScan", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN, NULL},
108 {SPAMSETTINGS_DIGITSCAN, 2, "DigitPercent", neonspam_cmd_setpercent, SPAMSETTINGS_DIGITPERCENTINDEX, "channel_digit_percent"},
109 {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "DigitReaction", neonspam_cmd_set_reaction, 9, "channel_digit_reaction"},
110 {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "DigitBanDuration", neonspam_cmd_set_reaction_time, 10, "channel_digit_reaction_duration"},
111 {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN_OPS, NULL},
112 {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN_VOICE, NULL},
113 {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_DIGITEXCINDEX, "channel_digit_except"},
115 {0, 0, NULL, NULL, 0, NULL}
118 #define MAX_QUERY_LEN 1024
119 CMD_BIND(neonspam_cmd_set) {
121 if(argc && !strcmp(argv[0], "defaults")) {
122 //reset channel settings
123 int uaccess = getChannelAccess(user, chan, 0);
125 if(isGodMode(user)) {
126 event->flags |= CMDFLAG_OPLOG;
128 reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name);
134 static char defaultskey[16];
135 for(tmp = user->auth; *tmp; tmp++)
136 seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
137 for(tmp = chan->name; *tmp; tmp++)
138 seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
139 sprintf(defaultskey, "%08x", seed);
140 if(argc > 1 && !strcmp(argv[1], defaultskey)) {
141 printf_mysql_query("UPDATE `channels` SET " SPAMSERV_SETTINGS_RESET " WHERE `channel_id` = '%d'", chan->channel_id);
142 reply(getTextBot(), user, "NS_SET_DEFAULTS_DONE", chan->name);
145 reply(getTextBot(), user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey);
147 } else if(argc && strcmp(argv[0], "help")) {
148 //find the correct command
151 char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
152 neonspam_settings_row = NULL;
153 neonspam_settings_defaults = NULL;
154 while(neonspam_settings[i].setting) {
155 if(!stricmp(neonspam_settings[i].setting, argv[0])) {
157 char valueBuf[MAXLEN];
159 neonspam_cmd_set_function *func = neonspam_settings[i].function;
160 value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, args, valueBuf);
162 reply(getTextBot(), user, "\002%s\002 %s", neonspam_settings[i].setting, value);
163 //TODO: reply valid options
172 reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]);
175 char valueBuf[MAXLEN], nameBuf[MAXLEN];
177 int namePos, boolflag = 0;
178 MYSQL_RES *res, *defaults_res;
182 while(neonspam_settings[i].setting)
184 table = table_init(2, i, 0);
185 table_set_bold(table, 0, 1);
186 printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_name` = 'defaults'");
187 defaults_res = mysql_use();
188 neonspam_settings_defaults = mysql_fetch_row(defaults_res);
189 printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
191 neonspam_settings_row = mysql_fetch_row(res);
193 reply(getTextBot(), user, "NS_SET_HEADER", chan->name);
194 while(neonspam_settings[++i].setting) {
195 if((chan->spam_settings->flags & (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS)) != (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS))
197 if((neonspam_settings[i].if_flag & SPAMSETTINGS_ISTIMEBAN) && !boolflag)
200 for(j = 0; j < neonspam_settings[i].indent; j++) {
201 nameBuf[namePos++] = ' ';
203 neonspam_cmd_set_function *func = neonspam_settings[i].function;
204 value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, NULL, valueBuf);
205 if(neonspam_settings[i].if_flag & SPAMSETTINGS_SETTIMEBAN)
206 boolflag = !strcmp(value, "2");
207 //TODO: append option or help info
208 sprintf(nameBuf + namePos, "%s", neonspam_settings[i].setting);
209 content[0] = nameBuf;
211 table_add(table, content);
213 char **table_lines = table_end(table);
214 for(i = 0; i < table->entrys; i++) {
215 reply(getTextBot(), user, table_lines[i]);
221 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) {
223 //get current trigger
226 printf_mysql_query("SELECT `trigger` FROM `bot_channels` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid);
228 row = mysql_fetch_row(res);
231 int uaccess = getChannelAccess(user, chan, 0);
233 if(isGodMode(user)) {
234 event->flags |= CMDFLAG_OPLOG;
236 reply(getTextBot(), user, "NS_SET_TRIGGER_OWNER", chan->name);
240 if(strlen(argument) > 15)
242 printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `chanid` = '%d' AND `botid` = '%d'", escape_string(argument), chan->channel_id, client->clientid);
244 changeChannelTrigger(client->botid, chan, trigger);
250 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) {
251 char *value = ((chan->spam_settings->flags & flag) ? "1" : "0");
254 if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) {
255 chan->spam_settings->flags &= ~flag;
256 } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) {
257 chan->spam_settings->flags |= flag;
259 reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument);
263 convertNeonSpamSettingsToString(chan->spam_settings->flags, str_flags);
264 printf_mysql_query("UPDATE `channels` SET `channel_scanner` = '%s' WHERE `channel_id` = '%d' ", str_flags, chan->channel_id);
270 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) {
271 unsigned int value = chan->spam_settings->exceptlevel[exceptlvl_index];
273 //numeric argument... (access)
274 int caccess = atoi(argument);
275 if(caccess < 0 || caccess > 501) {
276 reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
279 int uaccess = getChannelAccess(user, chan, 0);
280 if(uaccess == 500) uaccess++;
281 if(caccess > uaccess) {
282 if(isGodMode(user)) {
283 event->flags |= CMDFLAG_OPLOG;
285 reply(getTextBot(), user, "NS_SET_CANNOT_SET");
289 if(caccess > uaccess) {
290 if(isGodMode(user)) {
291 event->flags |= CMDFLAG_OPLOG;
293 reply(getTextBot(), user, "NS_SET_BADLEVEL");
298 chan->spam_settings->exceptlevel[exceptlvl_index] = value;
299 printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", field, value, chan->channel_id);
301 sprintf(retBuf, "%u", value);
305 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) {
309 * 1/kickban - kickban
312 if(!strcmp(argument, "0") || !stricmp(argument, "kick")) {
314 } else if(!strcmp(argument, "1") || !stricmp(argument, "kickban")) {
316 } else if(!strcmp(argument, "2") || !stricmp(argument, "ban")) {
319 reply(getTextBot(), user, "NS_SET_INVALID_OPTION_STR", argument);
322 printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id);
325 if(neonspam_settings_row) {
326 return (neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]);
330 printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id);
332 row = mysql_fetch_row(res);
338 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) {
341 duration = strToTime(user, argument);
343 reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30);
346 printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id);
348 if(neonspam_settings_row) {
349 duration = atoi(neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]);
353 printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id);
355 row = mysql_fetch_row(res);
356 duration = atoi(row[0]);
359 timeToStr(user, duration, 3, retBuf);
363 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) {
364 unsigned int value = chan->spam_settings->percent[percent_index];
366 //numeric argument... (access)
367 value = atoi(argument);
368 if(value < 0 || value > 100) {
369 //invalid percent value
372 chan->spam_settings->percent[percent_index] = value;
373 printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", mysqlfield, value, chan->channel_id);
375 sprintf(retBuf, "%u", value);
379 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) {
382 char *delimiter = strstr(argument, ":");
389 int amount = atoi(argument);
390 int timep = atoi(delimiter);
391 if(amount > MAX_FLOOD_AMOUNT || amount < MIN_FLOOD_AMOUNT) {
395 if(timep > MAX_FLOOD_TIME || timep < 0) {
396 //invalid time period
399 char amountfield[50], timefield[50];
400 sprintf(amountfield, "%s%s", mysqlfield, "limit");
401 sprintf(timefield, "%s%s", mysqlfield, "time");
402 printf_mysql_query("UPDATE `channels` SET `%s` = '%d', `%s` = '%d' WHERE `channel_id` = '%d' ", amountfield, amount, timefield, timep, chan->channel_id);
403 sprintf(retBuf, "%d:%d", amount, timep);
404 chan->spam_settings->sensibility_amount[sensibility_index] = amount;
405 chan->spam_settings->sensibility_time[sensibility_index] = timep;
407 sprintf(retBuf, "%d:%d", chan->spam_settings->sensibility_amount[sensibility_index], chan->spam_settings->sensibility_time[sensibility_index]);
412 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) {
415 int amount = atoi(argument);
416 if(amount > MAX_FLOOD_AMOUNT || amount < MIN_FLOOD_AMOUNT) {
420 printf_mysql_query("UPDATE `channels` SET `channel_maxrepeat` = '%d' WHERE `channel_id` = '%d' ", amount, chan->channel_id);
421 sprintf(retBuf, "%d", amount);
422 chan->spam_settings->spam_amount = amount;
424 sprintf(retBuf, "%d", chan->spam_settings->spam_amount);