1# modelist.pl v 0.7.2 by Marcin Rozycki (derwan@irssi.pl) changed at Sat Jun 5 22:38:59 CEST 2004 2# 3# Usage: 4# /se 5# /si 6# /unexcept [index] ( ex. /unexcept 1 5 17) 7# /uninvite [index] ( ex. /uninvite 3 8) 8# 9 10use strict; 11use Irssi 20020600 (); 12use Irssi::Irc; 13 14use vars qw($VERSION %IRSSI); 15 16$VERSION = "0.7.2"; 17%IRSSI = ( 18 authors => 'Marcin Rozycki', 19 contact => 'derwan@irssi.pl', 20 name => 'modelist', 21 description => 'Cache of invites and ban exceptions in channel. Usage: /si, /se, '. 22 '/unexcept [indexes], /uninvite [indexes]', 23 license => 'GNU GPL v2', 24 url => 'http://derwan.irssi.pl', 25 changed => 'Sat Jun 5 22:38:59 CEST 2004' 26); 27 28Irssi::theme_register([ 29 'modelist', '$0 - {hilight $1}: $2 %c$3%n $4' 30]); 31 32my %modelist = (); 33 34sub channel_create 35{ 36 my ($server, $channel) = (@_[0], lc($_[1])); 37 delete $modelist{lc($server->{tag})}{$channel}; 38 39 $server->redirect_event("mode I", 1, "$channel", 0, undef, { 40 'event 346' => 'redir modelist invite', 41 '' => 'event empty' }); 42 $server->send_raw("MODE $channel I"); 43 44 $server->redirect_event("mode e", 1, "$channel", 0, undef, { 45 'event 348' => 'redir modelist except', 46 '' => 'event empty' }); 47 $server->send_raw("MODE $channel e"); 48} 49 50sub sig_channel_created 51{ 52 channel_create($_[0]->{server}, $_[0]->{name}) unless ($_[0]->{no_modes}); 53} 54 55 56sub sig_redir_modelist_invite 57{ 58 my ($nick, $chan, $mode) = split(/ +/, $_[1], 3); 59 message_irc_mode($_[0], $chan, undef, undef, "+I $mode"); 60} 61 62sub sig_redir_modelist_except 63{ 64 my ($nick, $chan, $mode) = split(/ +/, $_[1], 3); 65 message_irc_mode($_[0], $chan, undef, undef, "+e $mode"); 66} 67 68sub message_irc_mode 69{ 70 my ($mode, @args) = split(/ +/, $_[4]); 71 return unless $_[0]->ischannel($_[1]); 72 my ($tag, $chan, $mod) = (lc($_[0]->{tag}), lc($_[0]->channel_find($_[1])->{name}), "+"); 73 foreach ( split //, $mode ) 74 { 75 /([+-])/ and $mod = $_, next; 76 my $arg = ( $mod eq '+' && $_ =~ m/[beIkloRvh]/ or $mod eq '-' && $_ =~ m/[beIkoRvh]/ ) ? shift(@args) : undef; 77 next unless ( $_ =~ m/[eI]/ ); 78 ( $mod eq '+' ) and push(@{$modelist{$tag}{$chan}{$_}}, [$arg, $_[2], time]), next; 79 for (my $idx = 0; $idx <= $#{$modelist{$tag}{$chan}{$_}}; $idx++) { 80 splice(@{$modelist{$tag}{$chan}{$_}}, $idx, 1) if ($modelist{$tag}{$chan}{$_}[$idx][0] eq $arg); 81 } 82 } 83} 84 85sub proc_modelist_show 86{ 87 my ($arg, $server, $channel, $list, $mode) = @_; 88 89 Irssi::print("You\'re not connected to server"), return unless ($server and $server->{connected}); 90 91 $arg =~ s/\s.*//; 92 if ($arg) { 93 Irssi::print("Bad channel name: $arg"), return unless ($server->ischannel($arg)); 94 unless ($channel = $server->channel_find($arg)) { 95 Irssi::print("You\'re not in channel $arg --> sending request to server"); 96 $server->send_raw("MODE $arg $list"); 97 return; 98 } 99 } 100 101 Irssi::print("Not joined to any channel"), return unless ($channel and $channel->{type} eq "CHANNEL"); 102 Irssi::print("Channel not fully synchronized yet, try again after a while"), return unless ($channel->{synced}); 103 Irssi::print("Channel doesn\'t support modes"), return if ($channel->{no_modes}); 104 105 my ($tag, $name) = (lc($server->{tag}), $channel->{name}); 106 my $chan = lc($name); 107 my $items = $#{$modelist{$tag}{$chan}{$list}}; 108 109 Irssi::print("No $mode\s in channel %_$name%_"), return if ($items < 0); 110 111 for (my $idx = 0; $idx <= $items; $idx++) 112 { 113 my ($mask, $who) = ($modelist{$tag}{$chan}{$list}[$idx]->[0], $modelist{$tag}{$chan}{$list}[$idx]->[1]); 114 $mask =~ tr/\240\002\003\037\026/\206\202\203\237\226/; 115 my $setby = ($who) ? "\00314[\003by \002$who\002, ".(time - $modelist{$tag}{$chan}{$list}[$idx]->[2])." secs ago\00314]\003" : undef; 116 $channel->printformat(MSGLEVEL_CRAP, 'modelist', ($idx+1), $name, $mode, $mask, $setby); 117 } 118} 119 120sub cmd_si { proc_modelist_show @_, "I", "invite"; } 121sub cmd_se { proc_modelist_show @_, "e", "ban exception"; } 122 123sub cmd_modelist { 124 my ( $type, $data, $server, $witem) = @_; 125 Irssi::print("You\'re not connected to server"), return unless ($server and $server->{connected}); 126 Irssi::print("Not joined to any channel"), return unless ( $witem and $witem->{type} eq "CHANNEL" ); 127 my ($tag, $chan, @masks) = (lc($server->{tag}), lc($server->channel_find($witem->{name})->{name})); 128 while ( $data =~ m/(\d+)/g ) { 129 my $idx = $1 - 1; 130 next unless ( exists $modelist{$tag}{$chan}{$type}[$idx] ); 131 push(@masks, $modelist{$tag}{$chan}{$type}[$idx]->[0]); 132 } 133 return unless ( $#masks >= 0 ); 134 $witem->command(sprintf("MODE %s -%s %s", $chan, $type x scalar(@masks), join(" ", @masks))); 135} 136 137Irssi::signal_add("channel created", "sig_channel_created"); 138Irssi::signal_add("redir modelist invite", "sig_redir_modelist_invite"); 139Irssi::signal_add("redir modelist except", "sig_redir_modelist_except"); 140Irssi::signal_add("message irc mode", "message_irc_mode"); 141 142Irssi::command_bind("si", "cmd_si"); 143Irssi::command_bind("se", "cmd_se"); 144Irssi::command_bind("uninvite" => sub { cmd_modelist("I", @_); }); 145Irssi::command_bind("unexcept" => sub { cmd_modelist("e", @_); }); 146 147foreach my $server (Irssi::servers) 148{ 149 foreach my $channel ($server->channels()) 150 { 151 channel_create($server, $channel->{name}) unless ($channel->{no_modes}); 152 } 153} 154