1#!/usr/local/bin/perl -w 2# various kick and ban commands 3# by c0ffee 4# - http://www.penguin-breeder.org/irssi/ 5 6#<scriptinfo> 7use strict; 8use vars qw($VERSION %IRSSI); 9 10use Irssi 20020120; 11$VERSION = "0.27"; 12%IRSSI = ( 13 authors => "c0ffee", 14 contact => "c0ffee\@penguin-breeder.org", 15 name => "Various kick and ban commands", 16 description => "Enhances /k /kb and /kn with some nice options.", 17 license => "Public Domain", 18 url => "http://www.penguin-breeder.org/irssi/", 19 changed => "2017-03-31", 20); 21#</scriptinfo> 22 23my %kickreasons = ( 24 default => ["random kick victim", 25 "no", 26 "are you stupid?", 27 "i don't like you, go away!", 28 "oh, fsck off", 29 "waste other ppls time, elsewhere", 30 "get out and STAY OUT", 31 "don't come back", 32 "no thanks", 33 "on popular demand, you are now leaving the channel", 34 "\$N", 35 "*void*", 36 "/part is the command you're looking for", 37 "this is the irssi of borg. your mIRC will be assimilated. resistance is futile.", 38 "Autokick! mwahahahah!" 39 ], 40 none => [""], 41 topic => ["\$topic"], 42); 43 44 45# fine tune the script for different chatnets 46# cmdline_k regular expr that matches a correct cmdline for /k 47# req_chan 0/1 whether the channel is always part of the cmdline 48# num_nicks number of nicks ... (-1 = inf) 49# start_with_dash 0/1 whether the normal cmdline may start with a dash 50# match_chn matches channels 51# match_n match nicks 52# match_reason matches reasons 53# default_reason reason to give as "no reason" 54my %cfg = ( 55 IRC => { 56 cmdline_k => '\s*([!#+&][^\x0\a\n\r ]*)\s+[-\[\]\\\\\`{}\w_|^\'~]+(,[-\[\]\\\\\`{}\w_|^\'~]+)*\s+\S.*', 57 req_chan => 0, 58 num_nicks => 3, # actually, /k takes more, but 59 # normal irc servers only take 60 # three in a row 61 start_with_dash => 1, 62 match_chn => '([!#+&][^\x0\a\n\r ]*)\s', 63 match_n => '(?:^|\s+)([-\[\]\\\\\`{}\w_|^\'~]+(?:,[-\[\]\\\\\`{}\w_|^\']+)*)', 64 match_reason => '^\s*[!#+&][^\x0\a\n\r ]*\s+[-\[\]\\\\\`{}\w_|^\'~]+(?:,[-\[\]\\\\\`{}\w_|^\'~]+)*\s+(\S.*)$', 65 default_reason => '$N' 66 }, 67 68 SILC => { 69 cmdline_k => '\s*[^\x0-\x20\*\?,@!]+\s+[^\x0-\x20\*\?,@!]+\s+\S.*', 70 req_chan => 1, 71 num_nicks => 1, 72 start_with_dash => 0, 73 match_chn => '\s*([^\x0-\x20\*\?,@!]+)\s+[^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*', 74 match_n => '\s*(?:[^\x0-\x20\*\?,@!]+\s+)?([^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*)', 75 match_reason => '\s*[^\x0-\x20\*\?,@!]+\s+[^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*\s+(\S.*)', 76 default_reason => '$N' 77 } 78); 79 80sub initialize { 81 82 my $conf_file = Irssi::settings_get_str("kicks_configuration"); 83 $conf_file =~ s/~/$ENV{HOME}/; 84 my ($basedir) = $conf_file =~ /^(.*\/).*?/; 85 86 if (-f $conf_file) { 87 open CONF, '<', $conf_file; 88 89 my $line=0; 90 91 while (<CONF>) { 92 $line++; 93 94 next if /^\s*#/; 95 96 chomp; 97 my ($key, $reasons) = /^(\S+)\s+(.+)\s*$/ or next; 98 99 if ($reasons =~ /\`([^\s]+).*?\`/) { 100 $kickreasons{$key} = "$reasons"; 101 Irssi::print("Added executable $1 as $key..."); 102 next; 103 } 104 105 $reasons =~ s/^"(.*)"$/$1/; 106 $reasons =~ s/~/$ENV{HOME}/; 107 $reasons =~ s/^([^\/])/$basedir$1/; 108 109 if (-f $reasons) { 110 111 $kickreasons{$key} = []; 112 113 open REASON, '<', $reasons; 114 115 while (<REASON>) { 116 chomp; 117 push @{$kickreasons{$key}}, $_; 118 } 119 120 close REASON; 121 Irssi::print("Loaded $reasons as $key..."); 122 } else { 123 Irssi::print("can't parse config line $line..."); 124 } 125 } 126 close CONF; 127 } else { 128 Irssi::print("Could not find configuration file for kicks..."); 129 Irssi::print("... use /set kicks_configuration <file>"); 130 } 131} 132 133 134sub get_a_reason { 135 my ($topic) = @_; 136 137 138 return "" if not defined $kickreasons{$topic}; 139 140 $_ = eval $kickreasons{$topic}, chomp, s/[\n\t]+/ /mg, return $_ 141 if ref($kickreasons{$topic}) ne "ARRAY"; 142 143 return $kickreasons{$topic}[rand @{$kickreasons{$topic}}]; 144 145} 146 147sub cmd_realkick { 148 my ($data, $server, $channel, $cmd) = @_; 149 my $reasons = "default"; 150 151 return if not $server 152 or not defined $cfg{$server->{chat_type}} 153 or not $channel 154 or $data =~ /^$cfg{$server->{chat_type}}{cmdline_k}$/; 155 156 Irssi::signal_stop(); 157 158 # let's see whether some options where supplied 159 my $default = Irssi::settings_get_str("default_kick_options"); 160 $data = "$default $data" if not $default =~ /^\s*$/; 161 my @opts = split /\s+/, $data; 162 my $opt; 163 my $fail=0; 164 165 while (($opt) = (shift @opts) =~ /^\s*-(\S+)/) { 166 167 $data =~ s/^\s*--\s+//, last if $opt eq "-"; 168 169 $data =~ s/^\s*-$opt\s+//, 170 $reasons = lc $opt, 171 next if defined $kickreasons{lc $opt}; 172 173 last if $cfg{$server->{chat_type}}{start_with_dash}; 174 175 Irssi::print("Unknown option -$opt"); 176 $fail = 1; 177 178 } 179 180 return if $fail; 181 182 my $chn = ""; 183 ($chn) = $data =~ /^$cfg{$server->{chat_type}}{match_chn}/; 184 185 if ($cfg{$server->{chat_type}}{req_chan} && ($chn eq "")) { 186 Irssi::print "Not joined to any channel"; 187 return; 188 } 189 190 # do we need to add a channel? 191 if ($chn eq "") { 192 Irssi::print("Not joined to any channel"), return 193 if $channel->{type} ne "CHANNEL"; 194 $chn = $channel->{name}; 195 196 $data = "$chn $data"; 197 } 198 199 # is a reason already supplied? 200 my $reason; 201 $reason = get_a_reason($reasons) 202 if not (($reason) = $data =~ /$cfg{$server->{chat_type}}{match_reason}/); 203 204 $reason = $cfg{$server->{chat_type}}{default_reason} 205 if $reason =~ /^\s*$/; 206 207 my @nicks = split /,/, ($data =~ /$cfg{$server->{chat_type}}{match_n}/)[0]; 208 my $num_nicks = $cfg{$server->{chat_type}}{num_nicks}; 209 $num_nicks = @nicks if $num_nicks <= 0; 210 211 my @commands; 212 undef @commands; 213 214 while (@nicks) { 215 my $tmp = ($chn ne "" ? "$chn " : "") . 216 join ",", (splice @nicks,0,$num_nicks); 217 $tmp =~ s/([;\\\$])/\\$1/g; 218 push @commands, "$tmp $reason"; 219 } 220 221 foreach (@commands) { 222 if ($_ =~ /^$cfg{$server->{chat_type}}{cmdline_k}$/) { 223 s/\s+$//; 224 $channel->command("EVAL $cmd $_"); 225 } else { 226 Irssi::print("BUG: generated invalid $cmd command: $_"); 227 } 228 } 229} 230 231sub cmd_kick { 232 my ($data, $server, $channel) = @_; 233 234 cmd_realkick $data, $server, $channel, "KICK"; 235 236} 237 238sub cmd_kickban { 239 my ($data, $server, $channel) = @_; 240 241 cmd_realkick $data, $server, $channel, "KICKBAN"; 242 243} 244 245Irssi::settings_add_str("misc", "default_kick_options", ""); 246Irssi::settings_add_str("misc", "kicks_configuration", 247 Irssi::get_irssi_dir() . "/kicks.conf"); 248 249Irssi::command_bind("kick", "cmd_kick"); 250Irssi::command_bind("kickban", "cmd_kickban"); 251 252initialize(); 253 254