* Completely move around the home directory system and begin
[irc.git] / .irssi / scripts / auto_bleh.pl
1 # bleh stuff
2
3 use Irssi;
4 use Irssi::Irc;
5 use strict;
6 use vars qw($VERSION %IRSSI $DEBUG);
7
8 # 0.05 -- Add IPv6 support
9
10 $VERSION = q$Revision: 1.1 $;
11 %IRSSI = (authors     => 'Don Armstrong',
12           name        => 'auto_bleh',
13           description => 'Provides /ak /aq /ab /abr /abrn /arn /amb /amr /at',
14           license     => 'GPL',
15           changed     => q$Id: auto_bleh.pl,v 1.1 2005/03/17 08:19:53 don Exp $,
16          );
17
18 $DEBUG = 1 unless defined $DEBUG;
19
20 my ($actions, %defaults);
21
22 %defaults = (GET_OP       => 1,    # Should we try to get opped when we auto_bleh?
23              USE_CHANSERV => 1,    # Should we use chanserv to get opped?
24              EXPIRE       => 6000,   # Do not try to do anything if the action is more than 6000 seconds old.
25              DEOP         => 1,    # Automatically deop after we've done whatever we were supposed to do.
26              TIMEOUT      => 10,   # Timeout /at bans after 10 minutes
27             );
28
29 my %command_bindings = (ak   => 'cmd_ak',
30                         ab   => 'cmd_ab',
31                         aq   => 'cmd_aq',
32                         ar   => 'cmd_ar',
33                         abr  => 'cmd_abr',
34                         abk  => 'cmd_abk',
35                         abrn => 'cmd_abrn',
36                         abk  => 'cmd_abkn',
37                         arn  => 'cmd_arn',
38                         amb  => 'cmd_amb',
39                         amr  => 'cmd_amr',
40                         at   => 'cmd_at',
41                        );
42
43 my %bans_to_remove;
44
45
46 sub cmd_at {
47      my ($data, $server, $witem) = @_;
48      return do_auto_bleh('timeout',$data,$server,$witem);
49 }
50
51 sub cmd_ak {
52      my ($data, $server, $witem) = @_;
53      return do_auto_bleh('kick',$data,$server,$witem);
54 }
55
56 sub cmd_abk {
57      my ($data, $server, $witem) = @_;
58      return do_auto_bleh('kick,ban',$data,$server,$witem);
59 }
60 sub cmd_abkn {
61      my ($data, $server, $witem) = @_;
62      return do_auto_bleh('kick,ban,notice',$data,$server,$witem);
63 }
64
65 sub cmd_amb{
66      my ($data, $server, $witem) = @_;
67      my @nicks = split /\s+/, $data;
68      for (@nicks) {
69           next unless /\w/;
70           do_auto_bleh('ban',$_,$server,$witem);
71      }
72 }
73
74 sub cmd_ab {
75      my ($data, $server, $witem) = @_;
76      return do_auto_bleh('ban',$data,$server,$witem);
77 }
78
79 sub cmd_aq {
80      my ($data, $server, $witem) = @_;
81      return do_auto_bleh('quiet',$data,$server,$witem);
82 }
83
84
85 sub cmd_amr{
86      my ($data, $server, $witem) = @_;
87      my @nicks = split /\s+/, $data;
88      for (@nicks) {
89           next unless /\w/;
90           do_auto_bleh('remove',$_,$server,$witem);
91      }
92 }
93
94 sub cmd_ar {
95      my ($data, $server, $witem) = @_;
96      return do_auto_bleh('remove',$data,$server,$witem);
97 }
98 sub cmd_abr{
99      my ($data, $server, $witem) =@_;
100      return do_auto_bleh('remove,ban',$data,$server,$witem);
101 }
102 sub cmd_abrn{
103      my ($data, $server, $witem) =@_;
104      return do_auto_bleh('remove,ban,notice',$data,$server,$witem);
105 }
106 sub cmd_arn{
107      my ($data, $server, $witem) =@_;
108      return do_auto_bleh('remove,notice',$data,$server,$witem);
109 }
110
111
112 sub do_auto_bleh {
113      my ($cmd, $data, $server, $witem, $duration) = @_;
114
115      if (!$server || !$server->{connected}) {
116           Irssi::print("Not connected to server");
117           return;
118      }
119
120      if ($witem->{type} ne 'CHANNEL') {
121           Irssi::print("Can't autokick on a non-channel. [$witem->{type}]");
122           return;
123      }
124
125      # use Data::Dumper;
126      # Irssi::print(Dumper($data,$server,$witem));
127      # set the network that we're on, the channel and the nick to kick
128      # once we've been opped
129
130      # Heh. Looks like $data needs to be sanitized a bit.
131      $data =~ /^\s*([^\s]+)\s*(\d+)?\s*(.+?|)\s*$/;
132      my $nick = $1;
133      my $timeout = $2;
134      my $reason = $3;
135      $timeout = $defaults{TIMEOUT} if not defined $timeout or $timeout eq '';
136      $reason = 'you should know better' if not defined $reason or $reason eq '';
137
138      my $nick_rec = $witem->nick_find($nick);
139      if (not defined $nick_rec) {
140           Irssi::print("Unable to find nick: $nick");
141      }
142
143      my $hostname = $nick_rec->{host} if defined $nick_rec;
144      Irssi::print("Unable to find hostname for $nick") if not defined $hostname or $hostname eq '';
145      $hostname =~ s/.+\@//;
146
147      Irssi::print("Nick set to '$nick' from '$data', reason set to '$reason'.") if $DEBUG;
148      my $action = {type      => $cmd,
149                    nick      => $nick,
150                    nick_rec  => $nick_rec,
151                    network   => $witem->{server}->{chatnet},
152                    server    => $witem->{server},
153                    completed => 0,
154                    inserted  => time,
155                    channel   => $witem->{name},
156                    reason    => $reason,
157                    hostname  => $hostname,
158                    timeout   => $timeout,
159                   };
160      Irssi::print(i_want($action)) if $DEBUG;
161      if ($witem->{chanop}) { # we seem to be opped.
162           take_action($action,$server,$witem);
163      }
164      else {
165                $actions->{$data.$action->{inserted}}=$action;
166                get_op($server, $action->{channel}) if $defaults{GET_OP};
167      }
168
169 }
170
171 sub get_op {
172      my ($server,$channel) = @_;
173
174      Irssi::print("MSG chanserv op $channel");
175      $server->command("MSG chanserv op $channel") if $defaults{USE_CHANSERV};
176 }
177
178 sub i_want {
179      my $action = shift;
180
181      return "I've wanted to $action->{type} $action->{nick} off $action->{channel} on $action->{network} since $action->{inserted}";
182 }
183
184 sub take_action {
185      my ($action,$server,$channel) = @_;
186
187      local $_ = $action->{type};
188      # Now support multiple actions against a single nick (to FE, kick
189      # ban, or remove ban). See /abr foo
190      if (/timeout/) {
191           Irssi::print("Quieting $action->{nick} on $action->{channel} with hostname $action->{hostname} for $action->{timeout} minutes");
192           $server->send_raw("MODE $action->{channel} +q *!*@".$action->{hostname}) if $action->{hostname} ne ''; #quiet hostname
193           $bans_to_remove{"$action->{nick}$action->{inserted}"} = $action;
194      }
195      if (/quiet/) {
196           Irssi::print("Quieting $action->{nick} on $action->{channel} with hostname $action->{hostname}") if $DEBUG;
197           # Find hostname
198           if ($action->{hostname}) {
199                $server->send_raw("MODE $action->{channel} +b %*!*@".$action->{hostname}) if $action->{hostname} ne ''; #quiet hostname
200           }
201
202      }
203      if (/ban/) {
204           Irssi::print("Banning $action->{nick} from $action->{channel} with hostname $action->{hostname}") if $DEBUG;
205           $server->send_raw("MODE $action->{channel} +b *!*@".$action->{hostname}) if $action->{hostname} ne ''; # ban hostname
206      }
207      if (/kick/) {
208           Irssi::print("Kicking $action->{nick} from $action->{channel}") if $DEBUG;
209           if ($action->{reason} =~ /\s/) {
210                $server->send_raw("KICK $action->{channel} $action->{nick} :$action->{reason}");
211           }
212           else {
213                 $server->send_raw("KICK $action->{channel} $action->{nick} $action->{reason}");
214            }
215      }
216      if (/remove/) {
217           Irssi::print("Removing $action->{nick} from $action->{channel}") if $DEBUG;
218           if ($action->{reason} =~ /\s/) {
219                $server->send_raw("REMOVE $action->{channel} $action->{nick} :$action->{reason}");
220           }
221           else {
222                $server->send_raw("REMOVE $action->{channel} $action->{nick} $action->{reason}");
223           }
224      }
225      if (/notice/) {
226           Irssi::print("Noticing $action->{nick} with $action->{reason}") if $DEBUG;
227           $server->command("NOTICE $action->{nick} $action->{reason}");
228      }
229      # unquiet. This is crap, and needs to be changed to something sane.
230      if (/teiuq/) {
231           Irssi::print("Unquieting $action->{nick} on $action->{channel} with hostname $action->{hostname}") if $DEBUG;
232           $server->command("MODE $action->{channel} -q *!*@".$action->{hostname});
233      }
234      return; #for now.
235 }
236
237 sub deop_us {
238      my ($rec) = @_;
239      my $channel = $rec->{channel};
240      my $server = $rec->{server};
241
242      #$server->command("MODE $channel->{name} -o $channel->{ownick}->{nick}");
243      if ($channel->{chanop}) {
244           Irssi::print("MODE $channel->{name} -o $channel->{ownnick}->{nick}");
245           $channel->command("/deop $channel->{ownnick}->{nick}");
246      }
247 }
248
249 sub sig_mode_change {
250      my ($channel,$nick) = @_;
251
252      #Irssi::print(Dumper($nick));
253      #Irssi::print(Dumper($channel));
254
255      # Are there any actions to process?
256      # See if we got opped.
257      return if scalar(keys %$actions) eq 0;
258
259      if ($channel->{server}->{nick} eq $nick->{nick} and $nick->{op}) {
260           # Ok, we've been opped, or we are opped now, so do whatever we're supposed to do.
261           Irssi::print("We've been opped") if $DEBUG;
262           # We seem to need some sort of delay here for the chanop stuff to catch up
263           Irssi::timeout_add_once(250,'attempt_actions',undef);
264      }
265      else {
266           Irssi::print("Fooey. Not opped.") if $DEBUG;
267      }
268 }
269
270 sub attempt_actions {
271
272      my @deop_array;
273
274      foreach (keys %$actions) {
275           #Irssi::print(Dumper($actions->{$_}));
276           # See if this action is too old
277           if (time - $actions->{$_}->{inserted} > $defaults{EXPIRE}) {
278                Irssi::print("Expiring action: \"".i_want($actions->{$_})."\" because of time");
279                delete $actions->{$_};
280                next;
281           }
282           Irssi::print(i_want($actions->{$_})) if $DEBUG;
283           # Find the server to take action on
284           my $server = Irssi::server_find_chatnet($actions->{$_}->{network});
285           Irssi::print("Unable to find server for chatnet: $actions->{$_}->{network}") and return if not defined $server;
286           Irssi::print("Found server for chatnet: $actions->{$_}->{network}") if $DEBUG;
287           # Find the channel to take action on
288           my $s_channel = $server->channel_find($actions->{$_}->{channel});
289           Irssi::print("Unable to find channel for channel: $actions->{$_}->{channel}") and return if not defined $s_channel;
290           Irssi::print("Found channel for channel: $actions->{$_}->{channel}") if $DEBUG;
291           # Are we opped on that channel?
292           if ($s_channel->{chanop}) {          # Yes? Take the action against the user.
293                Irssi::print("We are opped on the channel!") if $DEBUG;
294                take_action($actions->{$_},$server,$s_channel);
295                push @deop_array,{server=>$server,channel=>$s_channel} if $defaults{DEOP};
296                delete $actions->{$_}; # Do not repeat this action.
297           }
298           else {
299                Irssi::print("We are not opped on the channel.") if $DEBUG;
300           }
301      }
302      foreach (@deop_array) {
303           deop_us($_);
304      }
305 }
306
307
308 sub try_to_remove_bans {
309      return unless keys %bans_to_remove;
310      for my $key (keys %bans_to_remove) {
311           if (($bans_to_remove{$key}{inserted} + $bans_to_remove{$key}{timeout}*60) < time) {
312                $bans_to_remove{$key}{type} = 'teiuq'; #unquiet
313                $actions->{$key} = $bans_to_remove{$key};
314                delete $bans_to_remove{$key};
315                get_op($actions->{$key}{server}, $actions->{$key}{channel}) if $defaults{GET_OP};
316           }
317      }
318 }
319
320 # call the try to remove bans function every minute
321 Irssi::timeout_add(1000*60,'try_to_remove_bans',undef);
322 Irssi::signal_add_last('nick mode changed','sig_mode_change');
323 my ($command,$function);
324
325 while (($command,$function) = each %command_bindings) {
326      Irssi::command_bind($command,$function);
327 }
328
329 1;