All pastes #418890 Raw Edit

Unnamed

public text v1 · immutable
#418890 ·published 2007-03-31 22:06 UTC
rendered paste body
# bleh stuff

use Irssi;
use Irssi::Irc;
use strict;
use vars qw($VERSION %IRSSI $DEBUG);

# 0.05 -- Add IPv6 support

$VERSION = q$Revision: 1.1 $;
%IRSSI = (authors     => 'Don Armstrong',
     name        => 'auto_bleh',
     description => 'Provides /ak /aq /ab /abr /abrn /arn /amb /amr /at',
     license     => 'GPL',
     changed     => q$Id: auto_bleh.pl,v 1.1 2005/03/17 08:19:53 don Exp $,
    );

$DEBUG = 1 unless defined $DEBUG;

my ($actions, %defaults);

%defaults = (GET_OP       => 1,    # Should we try to get opped when we auto_bleh?
        USE_CHANSERV => 1,    # Should we use chanserv to get opped?
        EXPIRE       => 6000,   # Do not try to do anything if the action is more than 6000 seconds old.
        DEOP         => 1,    # Automatically deop after we've done whatever we were supposed to do.
        TIMEOUT      => 10,   # Timeout /at bans after 10 minutes
       );

my %command_bindings = (ak   => 'cmd_ak',
         ab   => 'cmd_ab',
         aq   => 'cmd_aq',
         ar   => 'cmd_ar',
         abr  => 'cmd_abr',
         abk  => 'cmd_abk',
         abrn => 'cmd_abrn',
         abk  => 'cmd_abkn',
         arn  => 'cmd_arn',
         amb  => 'cmd_amb',
         amr  => 'cmd_amr',
         at   => 'cmd_at',
             );

my %bans_to_remove;


sub cmd_at {
     my ($data, $server, $witem) = @_;
     return do_auto_bleh('timeout',$data,$server,$witem);
}

sub cmd_ak {
     my ($data, $server, $witem) = @_;
     return do_auto_bleh('kick',$data,$server,$witem);
}

sub cmd_abk {
     my ($data, $server, $witem) = @_;
     return do_auto_bleh('kick,ban',$data,$server,$witem);
}
sub cmd_abkn {
     my ($data, $server, $witem) = @_;
     return do_auto_bleh('kick,ban,notice',$data,$server,$witem);
}

sub cmd_amb{
     my ($data, $server, $witem) = @_;
     my @nicks = split /\s+/, $data;
     for (@nicks) {
     next unless /\w/;
     do_auto_bleh('ban',$_,$server,$witem);
     }
}

sub cmd_ab {
     my ($data, $server, $witem) = @_;
     return do_auto_bleh('ban',$data,$server,$witem);
}

sub cmd_aq {
     my ($data, $server, $witem) = @_;
     return do_auto_bleh('quiet',$data,$server,$witem);
}


sub cmd_amr{
     my ($data, $server, $witem) = @_;
     my @nicks = split /\s+/, $data;
     for (@nicks) {
     next unless /\w/;
     do_auto_bleh('remove',$_,$server,$witem);
     }
}

sub cmd_ar {
     my ($data, $server, $witem) = @_;
     return do_auto_bleh('remove',$data,$server,$witem);
}
sub cmd_abr{
     my ($data, $server, $witem) =@_;
     return do_auto_bleh('remove,ban',$data,$server,$witem);
}
sub cmd_abrn{
     my ($data, $server, $witem) =@_;
     return do_auto_bleh('remove,ban,notice',$data,$server,$witem);
}
sub cmd_arn{
     my ($data, $server, $witem) =@_;
     return do_auto_bleh('remove,notice',$data,$server,$witem);
}


sub do_auto_bleh {
     my ($cmd, $data, $server, $witem, $duration) = @_;

     if (!$server || !$server->{connected}) {
     Irssi::print("Not connected to server");
     return;
     }

     if ($witem->{type} ne 'CHANNEL') {
     Irssi::print("Can't autokick on a non-channel. [$witem->{type}]");
     return;
     }

     # use Data::Dumper;
     # Irssi::print(Dumper($data,$server,$witem));
     # set the network that we're on, the channel and the nick to kick
     # once we've been opped

     # Heh. Looks like $data needs to be sanitized a bit.
     $data =~ /^\s*([^\s]+)\s*(\d+)?\s*(.+?|)\s*$/;
     my $nick = $1;
     my $timeout = $2;
     my $reason = $3;
     $timeout = $defaults{TIMEOUT} if not defined $timeout or $timeout eq '';
     $reason = 'you should know better' if not defined $reason or $reason eq '';

     my $nick_rec = $witem->nick_find($nick);
     if (not defined $nick_rec) {
     Irssi::print("Unable to find nick: $nick");
     }

     my $hostname = $nick_rec->{host} if defined $nick_rec;
     Irssi::print("Unable to find hostname for $nick") if not defined $hostname or $hostname eq '';
     $hostname =~ s/.+\@//;

     Irssi::print("Nick set to '$nick' from '$data', reason set to '$reason'.") if $DEBUG;
     my $action = {type      => $cmd,
         nick      => $nick,
         nick_rec  => $nick_rec,
         network   => $witem->{server}->{chatnet},
         server    => $witem->{server},
         completed => 0,
         inserted  => time,
         channel   => $witem->{name},
         reason    => $reason,
         hostname  => $hostname,
         timeout   => $timeout,
        };
     Irssi::print(i_want($action)) if $DEBUG;
     if ($witem->{chanop}) { # we seem to be opped.
     take_action($action,$server,$witem);
     }
     else {
          $actions->{$data.$action->{inserted}}=$action;
          get_op($server, $action->{channel}) if $defaults{GET_OP};
     }

}

sub get_op {
     my ($server,$channel) = @_;

     Irssi::print("MSG chanserv op $channel");
     $server->command("MSG chanserv op $channel") if $defaults{USE_CHANSERV};
}

sub i_want {
     my $action = shift;

     return "I've wanted to $action->{type} $action->{nick} off $action->{channel} on $action->{network} since $action->{inserted}";
}

sub take_action {
     my ($action,$server,$channel) = @_;

     local $_ = $action->{type};
     # Now support multiple actions against a single nick (to FE, kick
     # ban, or remove ban). See /abr foo
     if (/timeout/) {
     Irssi::print("Quieting $action->{nick} on $action->{channel} with hostname $action->{hostname} for $action->{timeout} minutes");
     $channel->command("/quote MODE $action->{channel} +q *!*@".$action->{hostname}) if $action->{hostname} ne ''; #quiet hostname
     $bans_to_remove{"$action->{nick}$action->{inserted}"} = $action;
     }
     if (/quiet/) {
     Irssi::print("Quieting $action->{nick} on $action->{channel} with hostname $action->{hostname}") if $DEBUG;
     # Find hostname
     $channel->command("/quote MODE $action->{channel} +q *!*@".$action->{hostname}) if $action->{hostname} ne ''; #quiet hostname
     }
     if (/ban/) {
     Irssi::print("Banning $action->{nick} from $action->{channel} with hostname $action->{hostname}") if $DEBUG;
     $channel->command("/quote MODE $action->{channel} +b *!*@".$action->{hostname}) if $action->{hostname} ne ''; # ban hostname
     }
     if (/kick/) {
     Irssi::print("Kicking $action->{nick} from $action->{channel}") if $DEBUG;
     if ($action->{reason} =~ /\s/) {
          $channel->command("/quote KICK $action->{channel} $action->{nick} :$action->{reason}");
     }
     else {
           $channel->command("/quote REMOVE $action->{channel} $action->{nick} $action->{reason}");
      }
     }
     if (/remove/) {
     Irssi::print("Removing $action->{nick} from $action->{channel}") if $DEBUG;
     if ($action->{reason} =~ /\s/) {
          $channel->command("/quote REMOVE $action->{channel} $action->{nick} :$action->{reason}");
     }
     else {
          $channel->command("/quote REMOVE $action->{channel} $action->{nick} $action->{reason}");
     }
     }
     if (/notice/) {
     Irssi::print("Noticing $action->{nick} with $action->{reason}") if $DEBUG;
     $channel->command("/NOTICE $action->{nick} $action->{reason}");
     }
     # unquiet. This is crap, and needs to be changed to something sane.
     if (/teiuq/) {
     Irssi::print("Unquieting $action->{nick} on $action->{channel} with hostname $action->{hostname}") if $DEBUG;
     $channel->command("/quote MODE $action->{channel} -q *!*@".$action->{hostname});
     }
     return; #for now.
}

sub deop_us {
     my ($rec) = @_;
     my $channel = $rec->{channel};
     my $server = $rec->{server};

     #$server->command("MODE $channel->{name} -o $channel->{ownick}->{nick}");
     #if ($channel->{chanop}) {
     Irssi::print("MODE $channel->{name} -o $channel->{ownnick}->{nick}");
     $channel->command("/deop $channel->{ownnick}->{nick}");
     #}
}

sub sig_mode_change {
     my ($channel,$nick) = @_;

     #Irssi::print(Dumper($nick));
     #Irssi::print(Dumper($channel));

     # Are there any actions to process?
     # See if we got opped.
     return if scalar(keys %$actions) eq 0;

     my @deop_array;
     if ($channel->{server}->{nick} eq $nick->{nick} and $nick->{op}) {
     # Ok, we've been opped, or we are opped now, so do whatever we're supposed to do.
     Irssi::print("We've been opped") if $DEBUG;
     foreach (keys %$actions) {
          #Irssi::print(Dumper($actions->{$_}));
          # See if this action is too old
          if (time - $actions->{$_}->{inserted} > $defaults{EXPIRE}) {
          Irssi::print("Expiring action: \"".i_want($actions->{$_})."\" because of time");
          delete $actions->{$_};
          next;
          }
          Irssi::print(i_want($actions->{$_})) if $DEBUG;
          # Find the server to take action on
          #my $server = Irssi::server_find_chatnet($actions->{$_}->{network});
          my $server = $actions->{$_}->{server};
          Irssi::print("Unable to find server for chatnet: $actions->{$_}->{network}") and return if not defined $server;
          Irssi::print("Found server for chatnet: $actions->{$_}->{network}") if $DEBUG;
          # Find the channel to take action on
          my $channel = $server->channel_find($actions->{$_}->{channel});
          Irssi::print("Unable to find channel for channel: $actions->{$_}->{channel}") and return if not defined $channel;
          Irssi::print("Found channel for channel: $actions->{$_}->{channel}") if $DEBUG;
          # Are we opped on that channel?
          #if ($channel->{chanop}) {           # Yes? Take the action against the user.
          Irssi::print("We are opped on the channel!") if $DEBUG;
          take_action($actions->{$_},$server,$channel);
          push @deop_array,{server=>$server,channel=>$channel} if $defaults{DEOP};
          delete $actions->{$_}; # Do not repeat this action.
          #}
          #else {
         # Irssi::print("We are not opped on the channel.") if $DEBUG;
          #}
     }
     foreach (@deop_array) {
          deop_us($_);
     }
     }
     else {
     Irssi::print("Fooey. Not opped.") if $DEBUG;
     }
}

sub try_to_remove_bans {
     return unless keys %bans_to_remove;
     for my $key (keys %bans_to_remove) {
     if (($bans_to_remove{$key}{inserted} + $bans_to_remove{$key}{timeout}*60) < time) {
          $bans_to_remove{$key}{type} = 'teiuq'; #unquiet
          $actions->{$key} = $bans_to_remove{$key};
          delete $bans_to_remove{$key};
          get_op($actions->{$key}{server}, $actions->{$key}{channel}) if $defaults{GET_OP};
     }
     }
}

# call the try to remove bans function every minute
Irssi::timeout_add(1000*60,'try_to_remove_bans',undef);
Irssi::signal_add_last('nick mode changed','sig_mode_change');
my ($command,$function);

while (($command,$function) = each %command_bindings) {
     Irssi::command_bind($command,$function);
}

1;