1 # ho_mkick.pl
2 #
3 # $Id: ho_mkick.pl,v 1.6 2004/08/22 20:19:26 jvunder REL_0_3 $
4 #
5 # Part of the Hybrid Oper Script Collection.
6 #
7 # This provides a /MKICK command to masskick clients from a channel.
8 #
9 # TODO:
10 # * support multiple kicks in 1 line if the ircd supports it.
11
12 # ---------------------------------------------------------------------
13
14 use strict;
15 use vars qw($VERSION %IRSSI $SCRIPT_NAME);
16
17 use Irssi;
18 use Irssi::Irc;
19 use HOSC::again;
20 use HOSC::again 'HOSC::Base';
21 use HOSC::again 'HOSC::Tools';
22 use Getopt::Long;
23
24 # ---------------------------------------------------------------------
25
26 ($VERSION) = '$Revision: 1.6 $' =~ / (\d+\.\d+) /;
27 %IRSSI = (
28 authors => 'Garion',
29 contact => 'garion@efnet.nl',
30 name => 'ho_mkick.pl',
31 description => 'Masskick command for a channel.',
32 license => 'Public Domain',
33 url => 'http://www.garion.org/irssi/',
34 changed => '25 May 2004 22:53:46',
35 );
36 $SCRIPT_NAME = 'Masskick';
37
38
39 # ---------------------------------------------------------------------
40
41 sub cmd_mkick {
42 my ($cmdline, $server, $chan) = @_;
43
44 if ($cmdline =~ /^help/) {
45 return print_help();
46 }
47
48 my $args = process_arguments($cmdline);
49
50 if ($args->{help}) {
51 return print_help();
52 }
53
54 if (!$server) {
55 ho_print_error("Please use /MKICK in a window of the server ".
56 "you want to masskick on.");
57 return;
58 }
59
60 if (!defined $args->{channel}) {
61 ho_print_error("<channel> argument missing. See /MKICK HELP for help.");
62 return;
63 }
64
65 my $channel = $server->channel_find($args->{channel});
66
67 if (!defined $channel) {
68 ho_print_error("You are not on channel " . $args->{channel} .
69 " on this server.");
70 return;
71 }
72 if (!$channel->{ownnick}->{op}) {
73 ho_print_error("You are not opped on channel " . $args->{channel} .
74 " on this server.");
75 return;
76 }
77
78 $args->{channel_obj} = $channel;
79 $args->{server_obj} = $server;
80
81 if (!defined $args->{reason}) {
82 $args->{reason} = Irssi::settings_get_str('ho_mkick_reason');
83 }
84
85 if (defined $args->{hostmask} &&
86 $args->{hostmask} =~ /^(?:(.+)!)?(.+)@(.+)$/
87 ) {
88 $args->{nick} = $1 ? $1 : "*";
89 $args->{user} = $2;
90 $args->{host} = $3;
91 } else {
92 ho_print_error("Missing or invalid hostmask. See /MKICK HELP for help.");
93 return;
94 }
95
96 ho_print('Simulation enabled.') if $args->{simulation};
97 ho_print('Masskicking clients matching ' .
98 $args->{nick} . "!" .
99 $args->{user} . "@" .
100 $args->{host} . " in " .
101 $args->{channel} . " for reason '" . $args->{reason} . "'.");
102
103 perform_masskick($args);
104 }
105
106
107 sub perform_masskick {
108 my ($args) = @_;
109 ho_print("Performing masskick.");
110
111 my $num_kicks = 0;
112
113 for my $client ($args->{channel_obj}->nicks()) {
114 my $nick = $client->{nick};
115 # Don't kick myself!
116 next if $nick eq $args->{server_obj}->{nick};
117
118 my $hostmask = $client->{host};
119 if (Irssi::mask_match_address($args->{nick} . '!' .
120 $args->{user} . '@' . $args->{host},
121 $nick, $hostmask)
122 ) {
123 if ($client->{op} && !$args->{ops}) {
124 ho_print($nick . " is opped. Not kicking.")
125 if $args->{verbose};
126 next;
127 }
128 if ($client->{voice} && !($args->{voices} || $args->{ops})) {
129 ho_print($nick . " is voiced. Not kicking.")
130 if $args->{verbose};
131 next;
132 }
133 my $rawcmd = "KICK " . $args->{channel} . " $nick :" . $args->{reason};
134 my $cmd = "KICK " . $args->{channel} . " $nick " . $args->{reason};
135 my $can_flood = Irssi::settings_get_bool('ho_mkick_can_flood');
136 if ($args->{simulation}) {
137 ho_print($cmd);
138 } else {
139 if ($can_flood) {
140 $args->{server_obj}->send_raw_now($rawcmd);
141 } else {
142 $args->{server_obj}->command($cmd);
143 }
144 }
145 $num_kicks++;
146 }
147 }
148
149 ho_print("Done. Kicked $num_kicks client" .
150 ($num_kicks == 1 ? '' : 's') . ".");
151 }
152
153
154 sub process_arguments {
155 my ($arguments) = @_;
156 my $opt;
157
158 # Removes double spaces in kick reason *shrug*
159 local @ARGV = split / +/, $arguments;
160
161 my $res = GetOptions(
162 'ops' => \$opt->{ops},
163 'voices' => \$opt->{voices},
164 'sim' => \$opt->{simulation},
165 'simulate' => \$opt->{simulation},
166 'simulation' => \$opt->{simulation},
167 'verbose' => \$opt->{verbose},
168 );
169
170 # Get the channel.
171 if (@ARGV) {
172 $opt->{channel} = shift @ARGV;
173 }
174
175 # Get the hostmask.
176 if (@ARGV) {
177 $opt->{hostmask} = shift @ARGV;
178 }
179
180 # Reassemble the reason.
181 for my $arg (@ARGV) {
182 $opt->{reason} .= $arg . " ";
183 }
184 $opt->{reason} =~ s/ $// if defined $opt->{reason};
185
186 return $opt;
187 }
188
189 # ---------------------------------------------------------------------
190
191 ho_print_init_begin($SCRIPT_NAME);
192
193 Irssi::command_bind('mkick', 'cmd_mkick');
194
195 Irssi::settings_add_str('ho', 'ho_mkick_reason', 'Plonk!');
196 Irssi::settings_add_bool('ho', 'ho_mkick_can_flood', 0);
197
198 ho_print_init_end($SCRIPT_NAME);
199 ho_print("Use /MKICK HELP for help.");
200
201 # ---------------------------------------------------------------------
202
203 sub print_help {
204 ho_print_help('head', $SCRIPT_NAME);
205
206 ho_print_help('section', 'Syntax');
207 ho_print_help('syntax', 'MKICK [-simulation] [-ops] [-voices] <channel> <[nick!]user@host> [<reason>]');
208
209 ho_print_help('section', 'Description');
210 ho_print_help(
211 "Masskicks all users in this channel matching the given hostmask. ".
212 "By default only non-opped users are kicked, but if ".
213 "you specify the -ops flag, ops are killed as well.".
214 "Same for voiced users and the -voices flag. The -ops flag overrules ".
215 "the -voices flag, so if you want to kick both ops and voices you only ".
216 "need to specify -ops."
217 );
218 }
syntax highlighted by Code2HTML, v. 0.9.1