### operit.pl (c) 2002, 2003 Petr Baudis
#
## Perform certain action (invite/op/...) on request authenticated by the
## IRC operator status.
#
## See http://pasky.ji.cz/~pasky/dev/irssi/ for the latest version.
#
## Thanks to:
## mofo (patches)
## Garion (ideas)
## Borys (ideas)
## devastor (bug reports)
## babar (delay patch)
#
## $Id: operit.pl,v 1.14 2003/09/06 12:27:11 pasky Exp pasky $
#
# $Log: operit.pl,v $
# Revision 1.14 2003/09/06 12:27:11 pasky
# Okay, so while I'm at it updated other instance of my email addy, copyright, bunch of grammar fixes and documented the operit_public_delay variable.
#
# Revision 1.13 2003/09/06 12:25:09 pasky
# Updated my email addy.
#
# Revision 1.12 2003/09/06 12:23:50 pasky
# Added support for randomly delayed operit - if operit is public, the delay is zero to five seconds by default - this helps greatly if there is a lot of operit-enabled clients on a channel. Patch by Babar and me.
#
# Revision 1.11 2003/03/20 08:58:18 pasky
# Match whole channel, not random part, when checking for deny_channels and deny_hosts. So you can deny operits at #iraq but still allow them at #iraqlive ;-). Thanks to viha for cooperation during testing.
#
# Revision 1.10 2002/11/29 16:51:46 pasky
# Don't play with channels we aren't on. Fixes occassional 'can't call method command on undefined value'; thanks to devastor for a report.
#
# Revision 1.9 2002/10/19 13:12:34 pasky
# Introduced operit_allow_public (by default on), which toggles accepting of public (on-channel) operit requests. Idea by Borys.
#
# Revision 1.8 2002/10/13 12:33:13 pasky
# We don't care about /^operit [^!#&]/ anymore. Thanks fly to Garion for suggestion.
#
# Revision 1.7 2002/10/07 14:16:58 pasky
# Added operit_show_requests bool setting (by default 1, that is same behaviour as now).
#
# Revision 1.6 2002/09/01 12:27:08 pasky
# Erm, compilation fixes.
#
# Revision 1.5 2002/09/01 12:24:24 pasky
# Allow specification of more channels separated by a comma in requests. Changed default value of operit_hosts_deny to something harmless. Patch by mofo .
#
# Revision 1.4 2002/03/13 13:17:36 pasky
# remove one debug message accidentally left there
#
# Revision 1.3 2002/03/12 18:02:37 pasky
# invait actually works now
#
# Revision 1.2 2002/02/05 17:47:13 pasky
# fixed many things :^). now it basically works how it should...
#
# Revision 1.1 2002/02/05 16:47:09 pasky
# Initial revision
#
#
###
### Inspired by Operit-2.01b+enge script for ircII+ clients by
## - Viha ([email protected])
# - Karzan ([email protected])
#
## Credits also go to:
# - LuckyS ([email protected]) [bug reports]
# - Fusion ([email protected]) [bug reports]
# - RA^v^EN ([email protected]) [bug reports]
# - tumble ([email protected]) [beta testing]
# - koopal ([email protected]) [script ideas]
# - pt ([email protected]) [script ideas]
# - delta ([email protected]) [script ideas]
# - pht ([email protected]) [bug reports]
# - enge ([email protected]) [modifications]
#
### The most recent version can always be found at
# http://www.vip.fi/~viha/irc/
###
use strict;
use vars qw ($VERSION %IRSSI $rcsid);
$rcsid = '$Id: operit.pl,v 1.14 2003/09/06 12:27:11 pasky Exp pasky $';
($VERSION) = '$Revision: 1.14 $' =~ / (\d+\.\d+) /;
%IRSSI = (
name => 'operit',
authors => 'Petr Baudis',
contact => '[email protected]',
url => 'http://pasky.ji.cz/~pasky/dev/irssi/',
license => 'BSD',
description => 'Perform certain action (invite/op/...) on request authenticated by the IRC operator status.'
);
use Irssi 20021117; # timeout_add_once
use Irssi::Irc;
my $queue = 0; # already queued an operit? (when?)
my $disp = 0; # already displayed kind notice about already queued operit?
my $cmd = ""; # command issued
my $target = ""; # who issued the command
my $chan = ""; # object of the command
my $coperit = 0;
my $cinvait = 0;
my $cdamode = 0;
my $mpublic = 0;
sub event_privmsg {
my ($server, $data, $nick, $address) = @_;
my ($msgtarget, $text) = split(/ :/, $data, 2);
return if (Irssi::settings_get_bool("operit_deny"));
if ($text =~ s/^(invait|operit|damode)( .*)?$/$2/i) {
if (uc($msgtarget) eq uc($server->{nick})) {
$mpublic = 0;
} else {
return unless (Irssi::settings_get_bool("operit_allow_public"));
$mpublic = 1;
}
if (time - $queue < 10) {
Irssi::print "Operit currently deactivated or queued. Request ignored."
if (time - $disp > 20);
$disp = time;
return;
}
$cmd = $1; $target = $nick; $queue = 0; $disp = 0;
# if ($msgtarget eq $N or $cmd eq 'invait') {
if (1) {
($_, $chan) = split /\s+/, $text; # oh.. oh well :)
my $a = 0;
$chan = $msgtarget if (not $chan and $msgtarget ne $server->{nick});
return unless ($chan =~ /^[#!&]/);
foreach (split /\s+/, Irssi::settings_get_str("operit_chans")) {
s/\./\\./;
s/\*/.*/g;
if ($chan =~ /^$_$/i) {
$a++;
}
}
unless ($a) {
Irssi::print "Unauthorized $cmd $chan by $target (not in operit_chans)" if (Irssi::settings_get_bool("operit_show_requests"));
return;
}
foreach (split /\s+/, Irssi::settings_get_str("operit_chans_deny")) {
s/\./\\./;
s/\*/.*/g;
if ($chan =~ /^$_$/i) {
Irssi::print "Unauthorized $cmd $chan by $target (in operit_chans_deny)" if (Irssi::settings_get_bool("operit_show_requests"));
return;
}
}
foreach (split /^\s+$/, Irssi::settings_get_str("operit_hosts_deny")) {
s/\./\\./;
s/\*/.*/g;
if ($address =~ /$_/i) {
Irssi::print "Unauthorized $cmd $chan by $target <$address> (in operit_hosts_deny)" if (Irssi::settings_get_bool("operit_show_requests"));
return;
}
}
$queue = time;
$server->redirect_event("userhost", 1, $target, 0, 'redir userhost_operit_error',
{"event 302" => "redir userhost_operit"});
$server->command("USERHOST $target");
}
}
}
sub event_userhost_error {
Irssi::print "Operit userhost on $target failed, aborting the action...";
$queue = $disp = 0;
}
sub event_userhost_operit {
my ($server, $data) = @_;
my ($mynick, $reply) = split(/ +/, $data);
my ($nick, $user, $host) = $reply =~ /^:(.*)=.(.*)@(.*)/;
unless ($nick =~ s/\*$//) {
Irssi::print "$target requested UNAUTHORIZED $cmd on channel $chan" if (Irssi::settings_get_bool("operit_show_requests"));
return;
}
Irssi::print "$target requested $cmd on channel $chan" if (Irssi::settings_get_bool("operit_show_requests"));
foreach my $chansplit (split(/\,/, $chan)) {
my $channel = $server->channel_find($chansplit);
next unless ($channel);
if (lc($cmd) eq "operit") {
if ($mpublic) {
my $precision = 10; # Delay precision (10 = 1/10s)
my $rdelay = int(rand(Irssi::settings_get_str("operit_public_delay") * $precision)) * 1000 / $precision;
Irssi::print "Waiting " . ($rdelay / 1000) . " seconds before executing PUBLIC $cmd for $target on $chan";
Irssi::timeout_add_once($rdelay + 11, sub { # XXX why + 10 ? --pasky
my ($target, $channel) = @{$_[0]};
my ($tgrec) = $channel->nick_find($target);
$channel->command("op $target") unless ($tgrec and $tgrec->{'op'});
}, [ $target, $channel ]);
} else {
$channel->command("op $target");
}
$coperit++;
} elsif (lc($cmd) eq "invait") {
$server->command("invite $target $chansplit");
$cinvait++;
} elsif (lc($cmd) eq "damode") {
$server->command("notice $target mode for $chansplit is +$channel->{mode}");
$cdamode++;
}
}
$queue = $disp = 0;
}
sub event_ctcp {
my ($server, $data, $nick, $address, $target) = @_;
return if (Irssi::settings_get_bool("operit_deny"));
if ($data =~ /^operit/i) {
Irssi::print "$nick requested operit thru CTCP... no way!" if (Irssi::settings_get_bool("operit_show_requests"));
$server->command("NOTICE $nick ssshht!");
Irssi::signal_stop();
}
}
sub cmd_operit {
my ($data, $server, $channel) = @_;
if ($data =~ /^(usage|help)/i) {
foreach (split /\n/, <