html/users.pl


   1 # $Id: users.pl,v 1.22 2003/01/11 14:54:35 jylefort Exp $
   2 
   3 use Irssi 20020121.2020 ();
   4 $VERSION = "2.3";
   5 %IRSSI = (
   6 	  authors     => 'Jean-Yves Lefort',
   7 	  contact     => 'jylefort\@brutele.be, decadix on IRCnet',
   8 	  name        => 'users',
   9 	  description => 'Implements /USERS',
  10 	  license     => 'BSD',
  11 	  changed     => '$Date: 2003/01/11 14:54:35 $ ',
  12 );
  13 
  14 # usage:
  15 #
  16 #	/USERS [<orderstring>]
  17 #
  18 #		<orderstring> is an optional string
  19 #		whose format is described below.
  20 #
  21 # /set's:
  22 #
  23 #	users_sort_order
  24 #
  25 #		A sort order string which will be used to complete
  26 #		the order string given as a parameter to /USERS.
  27 #
  28 #		Example: /set users_sort_order mnha
  29 #
  30 #			Command		Resulting order
  31 #
  32 #			/USERS		mnha
  33 #			/USERS an	anmh
  34 #
  35 # sort order string format:
  36 #
  37 #	An order string must be composed by one or more characters from
  38 #	the following set:
  39 #
  40 #		m	server and channel mode
  41 #		n	nickname
  42 #		h	user@hostname
  43 #		a	away state
  44 #
  45 # /format's:
  46 #
  47 #	users		list header
  48 #			$0	channel name
  49 #
  50 #	users_nick	nick
  51 #			$0	* if IRC operator
  52 #			$1	@ if channel operator
  53 #			$2	% if half channel operator
  54 #			$3	+ if voiced
  55 #			$4	a if marked away
  56 #			$5	nickname
  57 #			$6	user@hostname
  58 #
  59 #	endofusers	end of list
  60 #			$0	channel name
  61 #			$1	number of nicks
  62 #			$2	number of IRC operators
  63 #			$3	number of channel operators
  64 #			$4	number of half channel operators
  65 #			$5	number of voiced
  66 #			$6	number of marked away
  67 #
  68 # changes:
  69 #
  70 #	2003-01-11	release 2.3
  71 #			* nick count was wrong
  72 #
  73 #	2003-01-09	release 2.2
  74 #			* command char independed
  75 #
  76 #	2003-01-09	release 2.1
  77 #			* minor oblivion fix
  78 #
  79 #	2003-01-09	release 2.0
  80 #			* /USERS accepts a sort order argument
  81 #			* added /set users_sort_order
  82 #			* shows away state
  83 #
  84 #	2002-07-04	release 1.01
  85 #			* command_bind uses a reference instead of a string
  86 #
  87 #	2002-04-25	release 1.00
  88 #			* uses '*' instead of 'S' for IRC operators
  89 #
  90 #	2002-04-12	release 0.13
  91 #			* added support for ircops
  92 #			* changed theme
  93 #
  94 #	2002-01-28	release 0.12
  95 #			* added support for halfops
  96 #
  97 #	2002-01-28	release 0.11
  98 #
  99 #	2002-01-23	initial release
 100 
 101 use strict;
 102 
 103 ### sort algorithms table #####################################################
 104 
 105 my %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 
 114 sub get_mode_weight
 115 {
 116   my ($nick) = @_;
 117 
 118   return ($nick->{serverop} * 4) + ($nick->{op} * 3) + ($nick->{halfop} * 2) + $nick->{voice};
 119 }
 120 
 121 sub 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 
 139 sub 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 
 154 sub 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 
 195 sub 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 
 262 Irssi::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 
 268 Irssi::settings_add_str("misc", "users_sort_order", "mnha");
 269 
 270 Irssi::command_bind("users", \&users);