1# $Id: users.pl,v 1.22 2003/01/11 14:54:35 jylefort Exp $ 2 3use strict; 4use Irssi 20020121.2020 (); 5use vars qw($VERSION %IRSSI); 6$VERSION = "2.3"; 7%IRSSI = ( 8 authors => 'Jean-Yves Lefort', 9 contact => 'jylefort\@brutele.be, decadix on IRCnet', 10 name => 'users', 11 description => 'Implements /USERS', 12 license => 'BSD', 13 changed => '$Date: 2003/01/11 14:54:35 $ ', 14); 15 16# usage: 17# 18# /USERS [<orderstring>] 19# 20# <orderstring> is an optional string 21# whose format is described below. 22# 23# /set's: 24# 25# users_sort_order 26# 27# A sort order string which will be used to complete 28# the order string given as a parameter to /USERS. 29# 30# Example: /set users_sort_order mnha 31# 32# Command Resulting order 33# 34# /USERS mnha 35# /USERS an anmh 36# 37# sort order string format: 38# 39# An order string must be composed by one or more characters from 40# the following set: 41# 42# m server and channel mode 43# n nickname 44# h user@hostname 45# a away state 46# 47# /format's: 48# 49# users list header 50# $0 channel name 51# 52# users_nick nick 53# $0 * if IRC operator 54# $1 @ if channel operator 55# $2 % if half channel operator 56# $3 + if voiced 57# $4 a if marked away 58# $5 nickname 59# $6 user@hostname 60# 61# endofusers end of list 62# $0 channel name 63# $1 number of nicks 64# $2 number of IRC operators 65# $3 number of channel operators 66# $4 number of half channel operators 67# $5 number of voiced 68# $6 number of marked away 69# 70# changes: 71# 72# 2003-01-11 release 2.3 73# * nick count was wrong 74# 75# 2003-01-09 release 2.2 76# * command char independed 77# 78# 2003-01-09 release 2.1 79# * minor oblivion fix 80# 81# 2003-01-09 release 2.0 82# * /USERS accepts a sort order argument 83# * added /set users_sort_order 84# * shows away state 85# 86# 2002-07-04 release 1.01 87# * command_bind uses a reference instead of a string 88# 89# 2002-04-25 release 1.00 90# * uses '*' instead of 'S' for IRC operators 91# 92# 2002-04-12 release 0.13 93# * added support for ircops 94# * changed theme 95# 96# 2002-01-28 release 0.12 97# * added support for halfops 98# 99# 2002-01-28 release 0.11 100# 101# 2002-01-23 initial release 102 103### sort algorithms table ##################################################### 104 105my %cmp = ( 106 m => sub { get_mode_weight($_[1]) cmp get_mode_weight($_[0]) }, 107 n => sub { lc $_[0]->{nick} cmp lc $_[1]->{nick} }, 108 h => sub { lc $_[0]->{host} cmp lc $_[1]->{host} }, 109 a => sub { $_[1]->{gone} cmp $_[0]->{gone} } 110 ); 111 112### support functions ######################################################### 113 114sub get_mode_weight 115{ 116 my ($nick) = @_; 117 118 return ($nick->{serverop} * 4) + ($nick->{op} * 3) + ($nick->{halfop} * 2) + $nick->{voice}; 119} 120 121sub nick_cmp 122{ 123 my ($this, $that, @order) = @_; 124 my $sort; 125 126 foreach (@order) 127 { 128 $sort = &{$cmp{$_}}($this, $that); 129 130 if ($sort) 131 { 132 return $sort; 133 } 134 } 135 136 return $sort; 137} 138 139sub validate_order 140{ 141 my @order = @_; 142 143 foreach (@order) 144 { 145 if (! exists($cmp{$_})) 146 { 147 return "unknown character '$_'"; 148 } 149 } 150 151 return undef; 152} 153 154sub get_order 155{ 156 my ($string) = @_; 157 my @order; 158 my @default; 159 my $error; 160 my %has; 161 162 @order = split(//, $string); 163 @default = split(//, Irssi::settings_get_str("users_sort_order")); 164 165 $error = validate_order(@default); 166 if (defined $error) 167 { 168 return "unable to validate users_sort_order: $error"; 169 } 170 171 $error = validate_order(@order); 172 if (defined $error) 173 { 174 return "unable to validate given order: $error"; 175 } 176 177 foreach (@order) 178 { 179 $has{$_} = 1; 180 } 181 182 foreach (@default) 183 { 184 if (! exists($has{$_})) 185 { 186 push(@order, $_); 187 } 188 } 189 190 return (undef, @order); 191} 192 193### /users #################################################################### 194 195sub users 196{ 197 my ($args, $server, $item) = @_; 198 199 if ($item && $item->{type} eq "CHANNEL") 200 { 201 my $error; 202 my @order; 203 my $window; 204 my @nicks; 205 206 my $serverop_count = 0; 207 my $chanop_count = 0; 208 my $halfop_count = 0; 209 my $voice_count = 0; 210 my $away_count = 0; 211 212 ($error, @order) = get_order($args); 213 214 if (defined $error) 215 { 216 Irssi::print("Unable to compute sort order: $error", MSGLEVEL_CLIENTERROR); 217 return; 218 } 219 220 Irssi::command('WINDOW NEW HIDDEN'); 221 222 $window = Irssi::active_win(); 223 $window->set_name("U:$item->{name}"); 224 $window->printformat(MSGLEVEL_CRAP, "users", $item->{name}); 225 226 @nicks = $item->nicks(); 227 @nicks = sort { nick_cmp($a, $b, @order) } @nicks; 228 229 foreach (@nicks) 230 { 231 my $serverop; 232 my $chanop; 233 my $halfop; 234 my $voice; 235 my $away; 236 237 $serverop = $_->{serverop} ? '*' : '.'; 238 $chanop = $_->{op} ? '@' : '.'; 239 $halfop = $_->{halfop} ? '%' : '.'; 240 $voice = $_->{voice} ? '+' : '.'; 241 $away = $_->{gone} ? 'a' : '.'; 242 243 $serverop_count++ if ($_->{serverop}); 244 $chanop_count++ if ($_->{op}); 245 $halfop_count++ if ($_->{halfop}); 246 $voice_count++ if ($_->{voice}); 247 $away_count++ if ($_->{gone}); 248 249 $window->printformat(MSGLEVEL_CRAP, "users_nick", 250 $serverop, $chanop, $halfop, $voice, $away, 251 $_->{nick}, $_->{host}); 252 } 253 254 $window->printformat(MSGLEVEL_CRAP, "endofusers", $item->{name}, 255 scalar @nicks, $serverop_count, $chanop_count, 256 $halfop_count, $voice_count, $away_count); 257 } 258} 259 260### initialization ############################################################ 261 262Irssi::theme_register([ 263 "users", '{names_users Users {names_channel $0}}', 264 "users_nick", '{hilight $0$1$3$4} $[9]5 $[50]6', 265 "endofusers", '{channel $0}: Total of {hilight $1} nicks, {hilight $2} IRC operators, {hilight $3} channel operators, {hilight $5} voiced, {hilight $6} marked away', 266 ]); 267 268Irssi::settings_add_str("misc", "users_sort_order", "mnha"); 269 270Irssi::command_bind("users", \&users); 271