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);