1 /* event_neonspam_chanmsg.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 #define SPAMSERV_CHECK_IGNORE 0
19 #define SPAMSERV_CHECK_WARN 1
20 #define SPAMSERV_CHECK_PUNISH 2
22 static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message);
23 static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser);
25 static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
26 struct ClientSocket *client = getChannelBot(chan, BOTID);
27 if(!client) return; //we can't "see" this event
28 loadNeonSpamSettings(chan);
29 struct NeonSpamSettings *settings = chan->spam_settings;
30 struct ChanUser *chanuser = getChanUser(user, chan);
31 if(!settings || !chanuser) return;
33 //ignore messages from ops/voices if we ignore them
34 if(!(settings->flags & SPAMSETTINGS_SCANOPS) && (chanuser->flags & CHANUSERFLAG_OPPED)) return;
35 if(!(settings->flags & SPAMSETTINGS_SCANVOICE) && (chanuser->flags & CHANUSERFLAG_VOICED)) return;
39 if(settings->flags & SPAMSETTINGS_SPAMSCAN) {
40 result = neonspam_spamscan(settings, chanuser, message);
42 case SPAMSERV_CHECK_IGNORE:
44 case SPAMSERV_CHECK_WARN:
45 reply(client, user, "SPAM WARNING!");
47 case SPAMSERV_CHECK_PUNISH:
48 reply(client, user, "SPAM PUNISHMENT!");
52 if(settings->flags & SPAMSETTINGS_FLOODSCAN) {
53 result = neonspam_floodscan(settings, chanuser);
55 case SPAMSERV_CHECK_IGNORE:
57 case SPAMSERV_CHECK_WARN:
58 reply(client, user, "FLOOD WARNING!");
60 case SPAMSERV_CHECK_PUNISH:
61 reply(client, user, "FLOOD PUNISHMENT!");
68 static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) {
69 //crc32 hash of the message
70 unsigned long msghash = crc32(message);
71 if(chanuser->spamnode) {
72 if(chanuser->spamnode->lastmsg == msghash) {
73 chanuser->spamnode->spamcount++;
74 if(chanuser->spamnode->spamcount == settings->spam_amount)
75 return SPAMSERV_CHECK_WARN;
76 else if(chanuser->spamnode->spamcount > settings->spam_amount)
77 return SPAMSERV_CHECK_PUNISH;
79 return SPAMSERV_CHECK_IGNORE;
82 createSpamNode(chanuser);
83 chanuser->spamnode->lastmsg = msghash;
84 chanuser->spamnode->spamcount = 1;
85 return SPAMSERV_CHECK_IGNORE;
88 static int neonspam_update_penalty(struct NeonSpamSettings *settings, struct ChanUser *chanuser, int addmsg) {
89 int last_update = time(0) - chanuser->spamnode->last_penalty_update;
91 if(last_update < MAX_FLOOD_TIME && chanuser->spamnode->floodpenalty) {
92 chanuser->spamnode->floodpenalty -= last_update * (MAX_FLOOD_TIME / settings->flood_time);
93 if(chanuser->spamnode->floodpenalty < 0)
94 chanuser->spamnode->floodpenalty = 0;
96 chanuser->spamnode->floodpenalty = 0;
97 chanuser->spamnode->last_penalty_update = time(0);
99 chanuser->spamnode->floodpenalty += MAX_FLOOD_TIME * addmsg;
100 return chanuser->spamnode->floodpenalty / MAX_FLOOD_TIME + ((chanuser->spamnode->floodpenalty % MAX_FLOOD_TIME) ? 1 : 0);
103 static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser) {
104 if(!chanuser->spamnode)
105 createSpamNode(chanuser);
106 int messages_pending = neonspam_update_penalty(settings, chanuser, 1);
107 if(messages_pending == settings->flood_amount)
108 return SPAMSERV_CHECK_WARN;
109 else if(messages_pending > settings->flood_amount)
110 return SPAMSERV_CHECK_PUNISH;
112 return SPAMSERV_CHECK_IGNORE;