diff options
| -rw-r--r-- | scripts/anames.pl | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/scripts/anames.pl b/scripts/anames.pl new file mode 100644 index 0000000..b73203c --- /dev/null +++ b/scripts/anames.pl @@ -0,0 +1,233 @@ +# anames.pl +# Irssi script that adds an /anames command, a clone of /names, with away nicks +# grayed out. +# +# Thanks to Dirm and Chris62vw for the Perl help and coekie for writing the +# evil code to sort the nicklist by the alphabet and rank in nicklist.pl +# +# 1.5 - Fixed halfop display bug (patch by epinephrine), 20100712 +# +# 1.4 - Merged changes from VMiklos and readded /who redirection to prevent +# spamming the status window. - ms, 20090122 +# +# 1.3 - by VMiklos +# Doing /dowho is very annoying and /alias foo /dowho;/anames won't +# work either since anames will work from the old infos. So I've +# modified /anames to just do a /dowho and the nicklist will be printed +# when we'll get the answer from the server. +# +# 1.2 - It seems that redirected events will not pass through the internal +# mechanisms that update user information (like away states). So, it +# /dowho and the periodic execution of the command has been disabled. +# /anames will still work, but new away information will need to be +# obtained by executing a /who on a channel. +# If you can make redirection (execute a /who without the information +# spilling to the status window) work, let me know so I can fix the +# script. +# +# 1.0.1 - Fixed row-determining and max-nick-length code, changed command_add +# calls to refs instead of names. +# +# 1.0 - Added timer for periodic /who of all channels +# +# 0.9 - Initial test release + +use strict; +use Irssi; +use POSIX; +#use Data::Dumper; + +use vars qw($VERSION %IRSSI); + +$VERSION = '1.5'; +%IRSSI = ( + authors => 'Matt "f0rked" Sparks, Miklos Vajna', + contact => 'ms+irssi@quadpoint.org', + name => 'anames', + description => 'a /names display with away nicks colored', + license => 'GPLv2', + url => 'http://quadpoint.org', + changed => '2010-07-12', +); + +# How often to do a /who of all channels (in seconds) +#my $who_timer = 300; + +my $tmp_server; +my $tmp_chan; + + +sub cmd_anames +{ + my($args, $server, $item) = @_; + my $channel = Irssi::active_win->{active}; + $tmp_server = $server; + $tmp_chan = $channel->{"name"}; + + if ($args ne "") { + $server = $args; + $server =~ s/-([^ ]*) .*/\1/; + $tmp_server = Irssi::server_find_tag($server); + $tmp_chan = $args; + $tmp_chan =~ s/-[^ ]* (.*)/\1/; + } + + # set up redirection + $tmp_server->redirect_event("who", 1, $tmp_chan, 0, undef, + { + "event 352" => "redir who_reply", + "event 315" => "redir who_reply_end", + }); + + $tmp_server->command("who $tmp_chan"); +} + + +sub print_anames +{ + my $server = $tmp_server; + my $chan = $tmp_chan; + my $channel = Irssi::Server::channel_find($server, $chan); + my $nick; + + if (!$channel) { + # no nicklist + Irssi::print("Not joined to any channel", MSGLEVEL_CLIENTERROR); + } else { + # Loop through each nick and display + my @nicks; + my($ops, $halfops, $voices, $normal, $away) = (0, 0, 0, 0, 0); + + # sorting from nicklist.pl + foreach my $nick (sort {(($a->{'op'}?'1':$a->{'halfop'}?'2':$a->{'voice'}?'3':'4').lc($a->{'nick'})) + cmp (($b->{'op'}?'1':$b->{'halfop'}?'2':$b->{'voice'}?'3':'4').lc($b->{'nick'}))} $channel->nicks()) { + my $realnick = $nick->{'nick'}; + my $gone = $nick->{'gone'}; + + my $prefix; + if ($nick->{'op'}) { + $prefix = "@"; + $ops++; + } elsif ($nick->{'halfop'}) { + $prefix = "%%"; + $halfops++; + } elsif ($nick->{'voice'}) { + $prefix = "+"; + $voices++; + } else { + $prefix = " "; + $normal++; + } + + $prefix = "%W$prefix%n"; + if ($gone) { + $realnick = "%K$realnick%n"; + $away++; + } + + push @nicks, "$prefix" . $realnick; + } + + my $total = @nicks; + $channel->print("%K[%n%gUsers%n %G" . $chan . "%n%K]%n", + MSGLEVEL_CLIENTCRAP); + columnize_nicks($channel,@nicks); + $channel->print("%W$chan%n: Total of %W$total%n nicks %K[%W$ops%n ops, " . + "%W$halfops%n halfops, %W$voices%n voices, %W$normal%n " . + "normal, %W$away%n away%K]%n", + MSGLEVEL_CLIENTNOTICE); + } +} + + +# create a /names style column, increasing alphabetically going down the +# columns. +sub columnize_nicks +{ + my($channel, @nicks) = @_; + my $total = @nicks; + + # determine max columns + # FIXME: this could be more intelligent (i.e., read window size) + my $cols = Irssi::settings_get_int("names_max_columns"); + $cols = 6 if $cols == 0; + + # determine number of rows + my $rows = round(ceil($total / $cols)); + + # array of rows + my @r; + for (my $i = 0; $i < $cols; $i++) { + # peek at next $rows items, determine max length + my $max_length = find_max_length(@nicks[0 .. $rows - 1]); + + # fill rows + for (my $j = 0; $j < $rows; $j++) { + my $n = shift @nicks; # single nick + if ($n ne "") { + $r[$j] .= "%K[%n$n" . fill_spaces($n,$max_length) . "%K]%n "; + } + } + } + + for (my $m = 0; $m < $rows; $m++) { + chomp $r[$m]; + $channel->print($r[$m], MSGLEVEL_CLIENTCRAP); + } +} + + +sub fill_spaces +{ + my($text, $max_length) = @_; + $text =~ s/%[a-zA-Z]//g; + return " " x ($max_length - length($text)); +} + + +sub find_max_length +{ + my $max_length = 0; + for (my $i = 0; $i < @_; $i++) { + my $nick = $_[$i]; + $nick =~ s/%[a-zA-Z]//g; + if (length($nick) > $max_length) { + $max_length = length($nick); + } + } + return $max_length; +} + + +sub round +{ + my($number) = @_; + return int($number + .5); +} + + +sub who_reply +{ + my($server, $data) = @_; + my(undef, $c, $i, $h, $n, $s) = split / /, $data; + if ($tmp_chan ne $c) { + $tmp_chan = $c; + #print "Got who info for $c"; + } +} + + +sub who_reply_end +{ + print_anames(); + $tmp_chan = ""; +} + + +Irssi::Irc::Server::redirect_register("who", 0, 0, + {"event 352" => 1}, + {"event 315" => 1}, + undef); +Irssi::signal_add("redir who_reply", \&who_reply); +Irssi::signal_add("redir who_reply_end", \&who_reply_end); +Irssi::command_bind("anames", \&cmd_anames); |
