1 /* event_neonspam_chanmsg.c - NeonServ v5.6
2 * Copyright (C) 2011-2012 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 static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message);
19 static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser);
20 static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message);
21 static int neonspam_capsscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message);
22 static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message);
23 static int neonspam_badwordscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message, int punish_now, int uaccess);
25 static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup);
26 static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, char *message, unsigned int warn, unsigned int punish);
28 struct neonspam_event_chanmsg_cache {
29 struct ClientSocket *client;
30 struct ChanUser *chanuser;
31 struct NeonSpamSettings *settings;
39 static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
40 struct ClientSocket *client = getChannelBot(chan, BOTID);
41 if(!client || (user->flags & USERFLAG_ISBOT)) return; //we can't "see" this event
42 loadNeonSpamSettings(chan);
43 struct NeonSpamSettings *settings = chan->spam_settings;
44 struct ChanUser *chanuser = getChanUser(user, chan);
45 if(!settings || !chanuser) return;
46 #define NEONSPAM_CHANMSG_DO_SCANOPS(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_OPPED))
47 #define NEONSPAM_CHANMSG_DO_SCANVOICE(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_VOICED))
48 #define NEONSPAM_CHANMSG_DO_EXCEPT(INDEX) (settings->exceptlevel[INDEX] != 0)
49 #define NEONSPAM_CHANMSG_NEED_WHO(INDEX) (settings->exceptlevel[INDEX] != 501)
52 unsigned int warn = 0;
53 unsigned int punish = 0;
55 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)) {
56 result = neonspam_spamscan(settings, chanuser, message);
58 case SPAMSERV_CHECK_IGNORE:
60 case SPAMSERV_CHECK_WARN:
61 warn |= SPAMSETTINGS_SPAMSCAN;
62 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX))
65 case SPAMSERV_CHECK_PUNISH:
66 punish |= SPAMSETTINGS_SPAMSCAN;
67 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX))
72 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)) {
73 result = neonspam_floodscan(settings, chanuser);
75 case SPAMSERV_CHECK_IGNORE:
77 case SPAMSERV_CHECK_WARN:
78 warn |= SPAMSETTINGS_FLOODSCAN;
79 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX))
82 case SPAMSERV_CHECK_PUNISH:
83 punish |= SPAMSETTINGS_FLOODSCAN;
84 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX))
89 if((settings->flags & SPAMSETTINGS_BOTNETSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_BOTNETSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_BOTNETSCAN_VOICE)) {
90 result = neonspam_botnetscan(client, settings, chanuser, message);
92 case SPAMSERV_CHECK_DEAD:
94 case SPAMSERV_CHECK_IGNORE:
98 if((settings->flags & SPAMSETTINGS_CAPSSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_CAPSSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_CAPSSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_CAPSEXCINDEX)) {
99 result = neonspam_capsscan(settings, chanuser, message);
101 case SPAMSERV_CHECK_IGNORE:
103 case SPAMSERV_CHECK_WARN:
104 warn |= SPAMSETTINGS_CAPSSCAN;
105 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_CAPSEXCINDEX))
108 case SPAMSERV_CHECK_PUNISH:
109 punish |= SPAMSETTINGS_CAPSSCAN;
110 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_CAPSEXCINDEX))
115 if((settings->flags & SPAMSETTINGS_DIGITSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_DIGITSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_DIGITSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_DIGITEXCINDEX)) {
116 result = neonspam_digitscan(settings, chanuser, message);
118 case SPAMSERV_CHECK_IGNORE:
120 case SPAMSERV_CHECK_WARN:
121 warn |= SPAMSETTINGS_DIGITSCAN;
122 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_DIGITEXCINDEX))
125 case SPAMSERV_CHECK_PUNISH:
126 punish |= SPAMSETTINGS_DIGITSCAN;
127 if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_DIGITEXCINDEX))
132 if((settings->flags & SPAMSETTINGS_BADWORDSCAN)) {
133 if(user->flags & USERFLAG_ISAUTHED) {
134 result = neonspam_badwordscan(client, settings, chanuser, message, 1, getChannelAccess(chanuser->user, chanuser->chan));
136 result = neonspam_badwordscan(client, settings, chanuser, message, 0, 0);
138 case SPAMSERV_CHECK_DEAD:
140 case SPAMSERV_CHECK_IGNORE:
142 case SPAMSERV_CHECK_PUNISH:
143 punish |= SPAMSETTINGS_BADWORDSCAN;
151 //whois the user to check against exceptlevel
152 if(!needwho || (user->flags & USERFLAG_ISAUTHED)) {
153 neonspam_event_chanmsg_punish(client, chanuser, settings, message, warn, punish);
155 struct neonspam_event_chanmsg_cache *cache = malloc(sizeof(*cache));
157 printf_log("neonspam", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__);
160 cache->client = client;
161 cache->chanuser = chanuser;
162 cache->settings = settings;
163 cache->message = strdup(message);
165 cache->punish = punish;
166 get_userauth(user, module_id, neonspam_event_chanmsg_nick_lookup, cache);
170 #undef NEONSPAM_CHANMSG_DO_SCANOPS
171 #undef NEONSPAM_CHANMSG_DO_SCANVOICE
172 #undef NEONSPAM_CHANMSG_DO_EXCEPT
173 #undef NEONSPAM_CHANMSG_NEED_WHO
176 static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup) {
177 struct neonspam_event_chanmsg_cache *cache = data;
178 neonspam_event_chanmsg_punish(cache->client, cache->chanuser, cache->settings, cache->message, cache->warn, cache->punish);
179 free(cache->message);
183 static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, char *message, unsigned int warn, unsigned int punish) {
185 MYSQL_ROW row, defaults;
186 loadChannelSettings(chanuser->chan);
188 if(chanuser->user->flags & USERFLAG_ISAUTHED)
189 uaccess = getChannelAccess(chanuser->user, chanuser->chan);
194 if(!punishment && (punish & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) {
195 printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
197 row = mysql_fetch_row(res);
198 if(!row[0] || !row[1]) {
199 printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'");
201 defaults = mysql_fetch_row(res);
203 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM);
204 punishment = atoi((row[0] ? row[0] : defaults[0])) + 1;
205 punish_time = atoi((row[1] ? row[1] : defaults[1]));
207 if(!punishment && (punish & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) {
208 printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
210 row = mysql_fetch_row(res);
211 if(!row[0] || !row[1]) {
212 printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'");
214 defaults = mysql_fetch_row(res);
216 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD);
217 punishment = atoi((row[0] ? row[0] : defaults[0])) + 1;
218 punish_time = atoi((row[1] ? row[1] : defaults[1]));
220 if(!punishment && (punish & SPAMSETTINGS_CAPSSCAN) && settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] > uaccess) {
221 printf_mysql_query("SELECT `channel_caps_reaction`, `channel_caps_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
223 row = mysql_fetch_row(res);
224 if(!row[0] || !row[1]) {
225 printf_mysql_query("SELECT `channel_caps_reaction`, `channel_caps_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'");
227 defaults = mysql_fetch_row(res);
229 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_CAPS);
230 punishment = atoi((row[0] ? row[0] : defaults[0])) + 1;
231 punish_time = atoi((row[1] ? row[1] : defaults[1]));
233 if(!punishment && (punish & SPAMSETTINGS_DIGITSCAN) && settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] > uaccess) {
234 printf_mysql_query("SELECT `channel_digit_reaction`, `channel_digit_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
236 row = mysql_fetch_row(res);
237 if(!row[0] || !row[1]) {
238 printf_mysql_query("SELECT `channel_digit_reaction`, `channel_digit_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'");
240 defaults = mysql_fetch_row(res);
242 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_DIGIT);
243 punishment = atoi((row[0] ? row[0] : defaults[0])) + 1;
244 punish_time = atoi((row[1] ? row[1] : defaults[1]));
246 if(!punishment && (punish & SPAMSETTINGS_BADWORDSCAN)) {
247 int result = neonspam_badwordscan(client, settings, chanuser, message, 1, uaccess);
249 case SPAMSERV_CHECK_DEAD:
251 case SPAMSERV_CHECK_IGNORE:
256 if(!punishment && (warn & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) {
257 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM);
259 if(!punishment && (warn & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) {
260 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD);
262 if(!punishment && (warn & SPAMSETTINGS_CAPSSCAN) && settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] > uaccess) {
263 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_CAPS);
265 if(!punishment && (warn & SPAMSETTINGS_DIGITSCAN) && settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] > uaccess) {
266 sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_DIGIT);
269 char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
270 char *banmask = NULL;
271 switch (punishment) {
273 banmask = generate_banmask(chanuser->user, banmaskBuf);
274 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));
276 int banid = (int) mysql_insert_id(get_mysql_conn());
277 char nameBuf[MAXLEN];
279 sprintf(nameBuf, "ban_%d", banid);
280 sprintf(banidBuf, "%d", banid);
281 timeq_add_name(nameBuf, punish_time, module_id, channel_ban_timeout, strdup(banidBuf));
285 banmask = generate_banmask(chanuser->user, banmaskBuf);
286 putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask);
288 putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, reason);
292 reply(client, chanuser->user, "%s", reason);
295 static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) {
296 //crc32 hash of the message
297 unsigned long msghash = crc32(message);
298 if(chanuser->spamnode) {
299 if(chanuser->spamnode->lastmsg == msghash) {
300 chanuser->spamnode->spamcount++;
301 if(chanuser->spamnode->spamcount == settings->spam_amount)
302 return SPAMSERV_CHECK_WARN;
303 else if(chanuser->spamnode->spamcount > settings->spam_amount)
304 return SPAMSERV_CHECK_PUNISH;
306 return SPAMSERV_CHECK_IGNORE;
309 createSpamNode(chanuser);
310 chanuser->spamnode->lastmsg = msghash;
311 chanuser->spamnode->spamcount = 1;
312 return SPAMSERV_CHECK_IGNORE;
315 static int neonspam_update_penalty(struct NeonSpamSettings *settings, struct ChanUser *chanuser, int addmsg) {
316 int last_update = time(0) - chanuser->spamnode->last_penalty_update;
318 if(last_update < MAX_FLOOD_TIME && chanuser->spamnode->floodpenalty) {
319 chanuser->spamnode->floodpenalty -= last_update * (MAX_FLOOD_TIME / settings->sensibility_time[SPAMSETTINGS_FLOODSENINDEX]);
320 if(chanuser->spamnode->floodpenalty < 0)
321 chanuser->spamnode->floodpenalty = 0;
323 chanuser->spamnode->floodpenalty = 0;
324 chanuser->spamnode->last_penalty_update = time(0);
326 chanuser->spamnode->floodpenalty += MAX_FLOOD_TIME * addmsg;
327 return chanuser->spamnode->floodpenalty / MAX_FLOOD_TIME + ((chanuser->spamnode->floodpenalty % MAX_FLOOD_TIME) ? 1 : 0);
330 static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser) {
331 if(!chanuser->spamnode)
332 createSpamNode(chanuser);
333 int messages_pending = neonspam_update_penalty(settings, chanuser, 1);
334 if(messages_pending == settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX])
335 return SPAMSERV_CHECK_WARN;
336 else if(messages_pending > settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX])
337 return SPAMSERV_CHECK_PUNISH;
339 return SPAMSERV_CHECK_IGNORE;
342 static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) {
343 //crc32 hash of the message
344 unsigned long msghash = crc32(message);
345 if((time(0) - settings->lastmsg_time) > BOTNETSCAN_TIME || settings->lastmsg != msghash) {
347 for(i = 0; i < BOTNETSCAN_USERS; i++) {
348 if(settings->botnicks[i]) {
349 free(settings->botnicks[i]);
350 settings->botnicks[i] = NULL;
353 settings->flags &= ~SPAMSETTINGS_KICKEDBOTQUEUE;
354 settings->lastmsg = msghash;
355 } else if(settings->lastmsg == msghash) {
357 for(i = 0; i < BOTNETSCAN_USERS; i++) {
358 if(!settings->botnicks[i]) {
359 settings->botnicks[i] = strdup(chanuser->user->nick);
361 } else if(!stricmp(chanuser->user->nick, settings->botnicks[i])) {
362 return SPAMSERV_CHECK_IGNORE;
365 if(i == BOTNETSCAN_USERS) {
366 //BOTNETSCAN_USERS exceeded
367 if(!(settings->flags & SPAMSETTINGS_KICKEDBOTQUEUE)) {
368 for(i = 0; i < BOTNETSCAN_USERS; i++) {
369 putsock(client, "KICK %s %s :%s", chanuser->chan->name, settings->botnicks[i], SPAMSERV_MSG_BOTNET);
371 settings->flags |= SPAMSETTINGS_KICKEDBOTQUEUE;
373 putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, SPAMSERV_MSG_BOTNET);
374 return SPAMSERV_CHECK_DEAD;
377 settings->lastmsg_time = time(0);
378 return SPAMSERV_CHECK_IGNORE;
381 static int neonspam_capsscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) {
382 int caps = 0, msglen = strlen(message);
384 if(msglen <= 4) return SPAMSERV_CHECK_IGNORE;
385 for(i = 0; i < msglen; i++) {
386 if(isupper(message[i])) caps++;
388 caps = 100*caps/msglen;
389 if(caps >= settings->percent[SPAMSETTINGS_CAPSPERCENTINDEX]) {
390 if(!chanuser->spamnode)
391 createSpamNode(chanuser);
392 if(chanuser->spamnode->flags & NEONSPAMNODE_FLAG_CAPSSCAN_WARNED)
393 return SPAMSERV_CHECK_PUNISH;
395 chanuser->spamnode->flags |= NEONSPAMNODE_FLAG_CAPSSCAN_WARNED;
396 return SPAMSERV_CHECK_WARN;
399 return SPAMSERV_CHECK_IGNORE;
402 static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) {
403 int digit = 0, msglen = strlen(message);
405 if(msglen <= 4) return SPAMSERV_CHECK_IGNORE;
406 for(i = 0; i < msglen; i++) {
407 if(isdigit(message[i])) digit++;
409 digit = 100*digit/msglen;
410 if(digit >= settings->percent[SPAMSETTINGS_DIGITPERCENTINDEX]) {
411 if(!chanuser->spamnode)
412 createSpamNode(chanuser);
413 if(chanuser->spamnode->flags & NEONSPAMNODE_FLAG_DIGITSCAN_WARNED)
414 return SPAMSERV_CHECK_PUNISH;
416 chanuser->spamnode->flags |= NEONSPAMNODE_FLAG_DIGITSCAN_WARNED;
417 return SPAMSERV_CHECK_WARN;
420 return SPAMSERV_CHECK_IGNORE;
423 static int neonspam_badwordscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message, int punish_now, int uaccess) {
424 struct NeonSpamBadword *badword;
427 int staticban_user = 0;
428 int ban_duration = 0;
429 int checked_defaults = 0;
430 int apply_default_reaction = 0;
431 for(badword = settings->badwords; badword; badword = badword->next) {
432 if(!match(badword->badword, message)) {
433 if(badword->use_defaults) {
434 if(checked_defaults == 2) continue;
435 else if(!checked_defaults) {
436 if(!(settings->flags & SPAMSETTINGS_BADWORDSCAN_OPS) && (chanuser->flags & CHANUSERFLAG_OPPED)) {
437 checked_defaults = 2;
440 if(!(settings->flags & SPAMSETTINGS_BADWORDSCAN_VOICE) && (chanuser->flags & CHANUSERFLAG_VOICED)) {
441 checked_defaults = 2;
444 if(settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX] && settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX] < 501) {
446 return SPAMSERV_CHECK_PUNISH;
447 if(settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX] <= uaccess) {
448 checked_defaults = 2;
452 checked_defaults = 1;
455 if(!badword->scan_ops && (chanuser->flags & CHANUSERFLAG_OPPED)) continue;
456 if(!badword->scan_voice && (chanuser->flags & CHANUSERFLAG_VOICED)) continue;
457 if(badword->exceptlevel && badword->exceptlevel < 501) {
459 return SPAMSERV_CHECK_PUNISH;
460 if(badword->exceptlevel <= uaccess) {
461 checked_defaults = 2;
466 if(badword->use_default_reaction) {
467 apply_default_reaction = 1;
469 switch(badword->reaction) {
472 if(badword->reaction_time > ban_duration)
473 ban_duration = badword->reaction_time;
482 if(apply_default_reaction) {
484 MYSQL_ROW row, defaults;
485 loadChannelSettings(chanuser->chan);
486 printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id);
488 row = mysql_fetch_row(res);
489 if(!row[0] || !row[1]) {
490 printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'");
492 defaults = mysql_fetch_row(res);
494 int reaction = atoi((row[0] ? row[0] : defaults[0]));
495 int reaction_time = atoi((row[1] ? row[1] : defaults[1]));
499 if(reaction_time > ban_duration)
500 ban_duration = reaction_time;
507 if(!kick_user) return SPAMSERV_CHECK_IGNORE;
508 char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
509 char *banmask = NULL;
511 banmask = generate_banmask(chanuser->user, banmaskBuf);
512 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) (ban_duration ? (time(0) + ban_duration) : 0), 0, escape_string(SPAMSERV_MSG_BADWORD));
514 int banid = (int) mysql_insert_id(get_mysql_conn());
515 char nameBuf[MAXLEN];
517 sprintf(nameBuf, "ban_%d", banid);
518 sprintf(banidBuf, "%d", banid);
519 timeq_add_name(nameBuf, ban_duration, module_id, channel_ban_timeout, strdup(banidBuf));
524 banmask = generate_banmask(chanuser->user, banmaskBuf);
525 putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask);
527 putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, SPAMSERV_MSG_BADWORD);
528 return SPAMSERV_CHECK_DEAD;