1############################################################################### 2# badword.pl 3# Copyright (C) 2002 Jan 'fissie' Sembera <fis@ji.cz> 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 2 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, write to the Free Software 17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18############################################################################### 19# This is configurable badword script. It may be configured to ban immediately 20# when first badword is detected, or it may count badwords and if number of 21# badwords of given nick exceeds limit, ban him. Badword count may also be 22# expired if no badword is seen for specified period of time. Optional 23# verbosity (let's call it logging) may be enabled as well 24# 25# Runtime variables: 26# 27# badword_channels = list of channels where script is active, separated by space 28# badword_words = list of 'bad words' that trigger this, separated by space 29# badword_reason = reason used in kick when count exceeds permitted limit 30# badword_limit = if number of detected badwords reaches this number, ban'em. 31# Set 1 to immediately kickban. 32# badword_clear_delay = if no badword is detected from user for time specified 33# here (in seconds), clear his counter. Set 0 to disable. 34# badword_verbose = turns on/off logging features 35# badword_ban_delay = ban after number of kicks specified here. 0 - disables 36# banning, 1 - ban immediately, ... 37############################################################################### 38# 39# Changelog: 40# 41# Jun 4 2002 42# - added ban delaying feature 43# 44############################################################################### 45use Irssi; 46use Irssi::Irc; 47use strict; 48use vars qw($VERSION %IRSSI); 49 50$VERSION = "0.0.3"; 51 52%IRSSI = ( 53 authors => "Jan 'fissie' Sembera", 54 contact => "fis\@ji.cz", 55 name => "badword", 56 description => "Configurable badword kickbanning script", 57 license => "GPL v2 and any later", 58 url => "http://fis.bofh.cz/devel/irssi/", 59); 60 61my %nick_dbase; 62 63sub sig_public { 64 my ($server, $msg, $nick, $address, $target) = @_; 65 my $watch_channels = Irssi::settings_get_str('badword_channels'); 66 my $watch_words = Irssi::settings_get_str('badword_words'); 67 68 my @chanz = split (/ /, $watch_channels); 69 my @wordz = split (/ /, $watch_words); 70 71 my $nickrec = $server->channel_find($target)->nick_find($nick); 72 my $nickmode = $nickrec->{op} ? "@" : $nickrec->{voice} ? "+" : ""; 73 74 my $aux = 0; 75 76 if (! ($nickmode eq "")) { 77 return; 78 } 79 80 foreach my $ch (@chanz) { 81 if ($ch eq $target) { 82 $aux = 1; 83 } 84 } 85 86 if ($aux == 0) { 87 return; 88 } 89 90 $aux = 0; 91 foreach my $bw (@wordz) { 92# if (($msg =~ /\ $bw/) || ($msg =~ /^$bw/)) { 93 if ($msg =~ /$bw/) { 94 $aux = 1; 95 } 96 } 97 98 if ($aux == 0) { 99 return; 100 } 101 102 # Ok, here comes badword, check record 103 104 my $luser = $nick_dbase{$nick}{$target}; 105 106 if (!$luser) { 107 $nick_dbase{$nick}{$target}{'count'} = 1; 108 $nick_dbase{$nick}{$target}{'kcount'} = 0; 109 $nick_dbase{$nick}{$target}{'stamp'} = time(); 110 } else { 111 if ((Irssi::settings_get_int('badword_clear_delay') != 0) && (($nick_dbase{$nick}{$target}{'stamp'})+(Irssi::settings_get_int('badword_clear_delay'))) < time()) { 112 $nick_dbase{$nick}{$target}{'count'} = 1; 113 if (Irssi::settings_get_bool('badword_verbose') == 1) { Irssi::print('BW: Expired for '.$nick.' with hostmask '.$address.' on channel '.$target); } 114 } else { 115 $nick_dbase{$nick}{$target}{'count'} = ($nick_dbase{$nick}{$target}{'count'})+1; 116 } 117 $nick_dbase{$nick}{$target}{'stamp'} = time(); 118 } 119 120 $luser = $nick_dbase{$nick}{$target}{'count'}; 121 122 if (Irssi::settings_get_bool('badword_verbose') == 1) { Irssi::print('BW: Detected badword from nick '.$nick.' with hostmask '.$address.' on channel '.$target.' - '.$nick_dbase{$nick}{$target}{'count'}.' times'); } 123 124 if ($luser == Irssi::settings_get_int('badword_limit')) { 125 $nick_dbase{$nick}{$target}{'count'} = 0; 126 # Ban'em! 127 my @host = split(/\@/, $address); 128 if (($host[0] =~ /\~/) || ($host[0] =~ /\-/) || ($host[0] =~ /\=/) || ($host[0] =~ /\^/)) { $host[0] = "*"; } 129 my $mask = '*!'.$host[0].'@'.$host[1]; 130 $nick_dbase{$nick}{$target}{'kcount'} = ($nick_dbase{$nick}{$target}{'kcount'})+1; 131 if ((Irssi::settings_get_int('badword_ban_delay') > 0) && (Irssi::settings_get_int('badword_ban_delay') == $nick_dbase{$nick}{$target}{'kcount'})) { 132 $server->command('mode '.$target.' +b '.$mask); 133 $nick_dbase{$nick}{$target}{'kcount'} = 0; 134 if (Irssi::settings_get_bool('badword_verbose') == 1) { Irssi::print('BW: Nick '.$nick.' with mask '.$mask.' punished for badwording on channel '.$target.' - banned'); } 135 } else { 136 if (Irssi::settings_get_bool('badword_verbose') == 1) { Irssi::print('BW: Nick '.$nick.' with mask '.$mask.' punished for badwording on channel '.$target.' - kicked'); } 137 } 138 $server->command('quote kick '.$target.' '.$nick.' :'.Irssi::settings_get_str('badword_reason')); 139 } 140} 141 142sub sig_nick { 143 my ($server, $newnick, $nick, $address) = @_; 144 145 $newnick = substr ($newnick, 1) if ($newnick =~ /^:/); 146 my $count = $nick_dbase{$nick}; 147 if ($count) { 148 $nick_dbase{$nick} = undef; 149 $nick_dbase{$newnick} = $count; 150 if (Irssi::settings_get_bool('badword_verbose') == 1) { Irssi::print('BW: Tranferred badwords from '.$nick.' to '.$newnick); } 151 } 152} 153 154Irssi::settings_add_str("misc", "badword_channels", ""); 155Irssi::settings_add_str("misc", "badword_words", ""); 156Irssi::settings_add_str("misc", "badword_reason", "BW: badword limit exceeded"); 157Irssi::settings_add_int("misc", "badword_limit", 3); 158Irssi::settings_add_int("misc", "badword_clear_delay", 3600); 159Irssi::settings_add_int("misc", "badword_ban_delay", 1); 160Irssi::settings_add_bool("misc", "badword_verbose", 0); 161 162Irssi::signal_add_last('message public', 'sig_public'); 163Irssi::signal_add_last('event nick', 'sig_nick'); 164