Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
388 lines (320 sloc) 9.46 KB
use Irssi 20020300;
use strict;
use vars qw($VERSION %IRSSI %HELP);
$HELP{getop} = "
GETOP [channel]
Gets op on current channel or 'channel' from random opped bot added by ADDGETOP.
";
$HELP{addgetop} = "
ADDGETOP [channel] <mask> <command>
Adds entry to 'channel' or current channel getop list.
The \$0 in command specifies nick of random found mask
in channel.
";
$HELP{delgetop} = "
DELGETOP [channel] <mask or index number from LISTGETOP>
Deletes entry from getoplist on current channel or 'channel'.
";
$HELP{listgetop} = "
LISTGETOP [channel]
Lists all entries in getop list or just 'channel's getop list.
";
$VERSION = "0.9b";
%IRSSI = (
authors => "Maciek \'fahren\' Freudenheim",
contact => "fahren\@bochnia.pl",
name => "GetOP",
description => "Automatically request op from random opped person with specifed command from list after joining channel",
license => "GNU GPLv2 or later",
changed => "Fri Jan 10 03:54:07 CET 2003"
);
Irssi::theme_register([
'getop_listline', '[%W$[!-2]0%n]%| $[40]1%_: %_$2',
'getop_add', 'Added \'%_$2%_\' to getop list on channel %_$1%_ /$0/',
'getop_del', 'Deleted \'%_$2%_\' from getop list on channel %_$1%_ /$0/',
'getop_changed', 'Changed command for mask \'%_$2%_\' on channel %_$1%_ /$0/',
'getop_noone', '"%Y>>%n No one to get op from on $1 /$0/',
'getop_get', '%Y>>%n Getting op from %_$2%_ on $1 /$0/'
]);
my %getop = ();
my @userhosts;
my $getopfile = Irssi::get_irssi_dir . "/getoplist";
sub sub_getop {
my ($args, $server, $winit) = @_;
my $chan;
my ($channel) = $args =~ /^([^\s]+)/;
if ($server->ischannel($channel)) {
unless ($chan = $server->channel_find($channel)) {
Irssi::print("%R>>%n You are not on $channel.");
return;
}
$args =~ s/^[^\s]+\s?//;
} else {
unless ($winit && $winit->{type} eq "CHANNEL") {
Irssi::print("%R>>%n You don't have active channel in that window.");
return;
}
$channel = $winit->{name};
$chan = $winit;
}
if ($chan->{chanop}) {
Irssi::print("%R>>%n You are already opped on $channel.");
return;
}
$channel = lc($channel);
my $tag = lc($server->{tag});
unless ($getop{$tag}{$channel}) {
Irssi::print("%R>>%n Your getop list on channel $channel is empty. Use /ADDGETOP first.");
return;
};
unless ($getop{$tag}{$channel}) {
Irssi::print("%R>>%n Your getop list on channel $channel is empty.");
return;
}
getop_proc($tag, $chan);
}
sub sub_addgetop {
my ($args, $server, $winit) = @_;
my ($channel) = $args =~ /^([^\s]+)/;
if ($server->ischannel($channel)) {
$args =~ s/^[^\s]+\s?//;
} else {
unless ($winit && $winit->{type} eq "CHANNEL") {
Irssi::print("%R>>%n You don't have active channel in that window.");
return;
}
$channel = $winit->{name};
}
my ($mask, $command) = split(/ +/, $args, 2);
unless ($command) {
Irssi::print("Usage: /ADDGETOP [channel] <mask or nickname> <command>. If you type '\$0' in command then it will be changed automatically into mask's nick.");
return;
}
my $cmdchar = Irssi::settings_get_str('cmdchars');
$command =~ s/^($cmdchar*)\^?/\1^/g;
if (index($mask, "@") == -1) {
my ($c, $n);
if (($c = $server->channel_find($channel)) && ($n = $c->nick_find($mask))) {
$mask = $n->{host};
$mask =~ s/^[~+\-=^]/*/;
} else {
$server->redirect_event('userhost', 1, $mask, 0, undef, {
'event 302' => 'redir getop userhost',
'' => 'event empty' } );
$server->send_raw("USERHOST $mask");
my $uh = lc($mask) . " " . lc($channel) . " $command";
push @userhosts, $uh;
return;
}
}
$mask = "*!" . $mask if (index($mask, "!") == -1);
my $tag = lc($server->{tag});
my $channel = lc($channel);
for my $entry (@{$getop{$tag}{$channel}}) {
if ($entry->{mask} eq $mask) {
$entry->{command} = $command;
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_changed', $tag, $channel, $mask, $command);
&savegetop;
return;
}
}
my $gh = {
mask => $mask,
command => $command
};
push @{$getop{$tag}{$channel}}, $gh;
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_add', $tag, $channel, $mask, $command);
&savegetop;
}
sub sub_delgetop {
my ($args, $server, $winit) = @_;
my ($channel) = $args =~ /^([^\s]+)/;
if ($server->ischannel($channel)) {
$args =~ s/^[^\s]+\s?//;
} else {
unless ($winit && $winit->{type} eq "CHANNEL") {
Irssi::print("%R>>%n You don't have active channel in that window.");
return;
}
$channel = $winit->{name};
}
my $tag = lc($server->{tag});
my $channel = lc($channel);
unless ($getop{$tag}{$channel}) {
Irssi::print("%R>>%n Your getop list on channel $channel is empty.");
return;
}
unless ($args) {
Irssi::print("%W>>%n Usage: /DELGETOP [channel] <mask | index from LISTGETOP>");
return;
}
my $num;
if ($args =~ /^[0-9]+$/) {
if ($args > scalar(@{$getop{$tag}{$channel}})) {
Irssi::print("%R>>%n No such entry in $channel getop list.");
return;
}
$num = $args - 1;
} else {
my $i = 0;
for my $entry (@{$getop{$tag}{$channel}}) {
$args eq $entry->{mask} and $num = $i, last;
$i++;
}
}
if (my($gh) = splice(@{$getop{$tag}{$channel}}, $num, 1)) {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_del', $tag, $channel, $gh->{mask}, $gh->{command});
unless (scalar(@{$getop{$tag}{$channel}})) {
Irssi::print("%R>>%n No more entries in $channel getop list left.");
delete $getop{$tag}{$channel};
}
unless (keys %{$getop{$tag}}) {
Irssi::print("%R>>%n No more entries in getop list on $tag left.");
delete $getop{$tag};
}
}
&savegetop;
}
sub sub_listgetop {
my ($args, $server, $winit) = @_;
my ($channel) = $args =~ /^([^\s]+)/;
if ($server->ischannel($channel)) {
my $tag = lc($server->{tag});
$channel = lc($channel);
unless ($getop{$tag}{$channel}) {
Irssi::print("%R>>%n Your getop list on channel $channel is empty.");
return;
}
my $i = 0;
Irssi::print("Getop list on $channel /$tag/:");
for my $entry (@{$getop{$tag}{$channel}}) {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_listline', $i++, $entry->{mask}, $entry->{command});
}
} else {
unless (keys %getop) {
Irssi::print("%R>>%n Your getop list is empty. /ADDGETOP first.");
return;
}
for my $ircnet (keys %getop) {
for my $chan (keys %{$getop{$ircnet}}) {
Irssi::print("Channel: $chan /$ircnet/");
my $i = 1;
for my $entry (@{$getop{$ircnet}{$chan}}) {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_listline', $i++, $entry->{mask}, $entry->{command});
}
}
}
}
}
sub userhost_red {
my ($server, $data) = @_;
$data =~ s/^[^ ]* :?//;
my $uh = shift @userhosts;
my ($nick, $chan, $command) = split(/ /, $uh, 3);
unless ($data && $data =~ /^([^=\*]*)\*?=.(.*)@(.*)/ && lc($1) eq $nick) {
Irssi::print("%R>>%n No such nickname: $nick");
return;
}
my ($user, $host) = ($2, $3);
$user =~ s/^[~+\-=^]/*/;
my $mask = "*!" . $user . "@" . $host;
my $tag = lc($server->{tag});
for my $entry (@{$getop{$tag}{$chan}}) {
if ($entry->{mask} eq $mask) {
$entry->{command} = $command;
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_changed', $tag, $chan, $mask, $command);
&savegetop;
return;
}
}
my $gh = {
mask => $mask,
command => $command
};
push @{$getop{$tag}{$chan}}, $gh;
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_add', $tag, $chan, $mask, $command);
&savegetop;
}
sub getop_proc ($$) {
my ($tag, $chan) = @_;
my $channel = lc($chan->{name});
return unless ($getop{$tag}{$channel});
my (@list, $mask);
for my $nick ($chan->nicks()) {
next unless ($nick->{op});
$mask = $nick->{nick} . "!" . $nick->{host};
for my $entry (@{$getop{$tag}{$channel}}) {
if (mask_match($mask, $entry->{mask})) {
my $lh = {
nick => $nick->{nick},
command => $entry->{command}
};
push @list, $lh;
}
}
}
unless (@list) {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_noone', $tag, $channel);
} else {
my $get = $list[int(rand(@list))];
$get->{command} =~ s/\$0/$get->{nick}/g;
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_get', $tag, $channel, $get->{nick}, $get->{command});
$chan->command($get->{command});
}
}
sub mask_match ($$) {
my ($what, $match) = @_;
$match =~ s/\\/\\\\/g;
$match =~ s/\./\\\./g;
$match =~ s/\*/\.\*/g;
$match =~ s/\!/\\\!/g;
$match =~ s/\?/\./g;
$match =~ s/\+/\\\+/g;
$match =~ s/\^/\\\^/g;
return ($what =~ /^$match$/i);
}
sub got_notopped {
my ($server, $data) = @_;
my ($chan) = $data =~ /^[^\s]+\s([^\s]+)\s:/;
getop_proc(lc($server->{tag}), $server->channel_find($chan));
}
sub channel_sync {
my $chan = shift;
getop_proc(lc($chan->{server}->{tag}), $chan) unless ($chan->{chanop});
}
sub savegetop {
local *fp;
open (fp, ">", $getopfile) or die "Couldn't open $getopfile for writing";
for my $ircnet (keys %getop) {
for my $chan (keys %{$getop{$ircnet}}) {
for my $entry (@{$getop{$ircnet}{$chan}}) {
print(fp "$ircnet $chan $entry->{mask} $entry->{command}\n");
}
}
}
close fp;
}
sub loadgetop {
%getop = ();
return unless (-e $getopfile);
local *fp;
open (fp, "<", $getopfile) or die "Couldn't open $getopfile for reading";
local $/ = "\n";
while (<fp>) {
chop;
my $gh = {};
my ($tag, $chan);
($tag, $chan, $gh->{mask}, $gh->{command}) = split(/ /, $_, 4);
push @{$getop{$tag}{$chan}}, $gh;
}
close fp;
}
&loadgetop;
Irssi::command_bind( {
'getop' => \&sub_getop,
'addgetop' => \&sub_addgetop,
'delgetop' => \&sub_delgetop,
'listgetop' => \&sub_listgetop } );
Irssi::signal_add({ 'redir getop userhost' => \&userhost_red,
'event 482' => \&got_notopped,
'channel sync' => \&channel_sync});