- my ($chan) = @_;
-
- if (!defined $chan) {
- &help('verstats');
- return;
- }
-
- if (!&validChan($chan)) {
- &msg($who, "chan $chan is invalid.");
- return;
- }
-
- if (scalar @vernick > scalar(keys %{ $channels{lc $chan}{''} })/4) {
- &msg($who, 'verstats already in progress for someone else.');
- return;
- }
-
- &msg($who, "Sending CTCP VERSION to $chan; results in 60s.");
- $conn->ctcp('VERSION', $chan);
- $cache{verstats}{chan} = $chan;
- $cache{verstats}{who} = $who;
- $cache{verstats}{msgType} = $msgType;
-
- $conn->schedule(30, sub {
- my $c = lc $cache{verstats}{chan};
- @vernicktodo = ();
-
- foreach (keys %{ $channels{$c}{''} } ) {
- next if (grep /^\Q$_\E$/i, @vernick);
- push(@vernicktodo, $_);
- }
-
- &verstats_flush();
- } );
-
- $conn->schedule(60, sub {
- my $vtotal = 0;
- my $c = lc $cache{verstats}{chan};
- my $total = keys %{ $channels{$c}{''} };
- $chan = $c;
- $who = $cache{verstats}{who};
- $msgType = $cache{verstats}{msgType};
- delete $cache{verstats}; # sufficient?
-
- foreach (keys %ver) {
- $vtotal += scalar keys %{ $ver{$_} };
- }
-
- my %sorted;
- my $unknown = $total - $vtotal;
- my $perc = sprintf("%.1f", $unknown * 100 / $total);
- $perc =~ s/.0$//;
- $sorted{$perc}{'unknown/cloak'} = "$unknown ($perc%)" if ($unknown);
-
- foreach (keys %ver) {
- my $count = scalar keys %{ $ver{$_} };
- $perc = sprintf("%.01f", $count * 100 / $total);
- $perc =~ s/.0$//; # lame compression.
-
- $sorted{$perc}{$_} = "$count ($perc%)";
- }
-
- ### can be compressed to a map?
- my @list;
- foreach ( sort { $b <=> $a } keys %sorted ) {
- my $perc = $_;
- foreach (sort keys %{ $sorted{$perc} }) {
- push(@list, "$_ - $sorted{$perc}{$_}");
- }
- }
-
- # hack. this is one major downside to scheduling.
- $chan = $c;
- &performStrictReply( &formListReply(0, "IRC Client versions for $c ", @list) );
-
- # clean up not-needed data structures.
- undef %ver;
- undef @vernick;
- } );
+ my ($chan) = @_;
+
+ if ( !defined $chan ) {
+ &help('verstats');
+ return;
+ }
+
+ if ( !&validChan($chan) ) {
+ &msg( $who, "chan $chan is invalid." );
+ return;
+ }
+
+ if ( scalar @vernick > scalar( keys %{ $channels{ lc $chan }{''} } ) / 4 ) {
+ &msg( $who, 'verstats already in progress for someone else.' );
+ return;
+ }
+
+ &msg( $who, "Sending CTCP VERSION to $chan; results in 60s." );
+ $conn->ctcp( 'VERSION', $chan );
+ $cache{verstats}{chan} = $chan;
+ $cache{verstats}{who} = $who;
+ $cache{verstats}{msgType} = $msgType;
+
+ $conn->schedule(
+ 30,
+ sub {
+ my $c = lc $cache{verstats}{chan};
+ @vernicktodo = ();
+
+ foreach ( keys %{ $channels{$c}{''} } ) {
+ next if ( grep /^\Q$_\E$/i, @vernick );
+ push( @vernicktodo, $_ );
+ }
+
+ &verstats_flush();
+ }
+ );
+
+ $conn->schedule(
+ 60,
+ sub {
+ my $vtotal = 0;
+ my $c = lc $cache{verstats}{chan};
+ my $total = keys %{ $channels{$c}{''} };
+ $chan = $c;
+ $who = $cache{verstats}{who};
+ $msgType = $cache{verstats}{msgType};
+ delete $cache{verstats}; # sufficient?
+
+ foreach ( keys %ver ) {
+ $vtotal += scalar keys %{ $ver{$_} };
+ }
+
+ my %sorted;
+ my $unknown = $total - $vtotal;
+ my $perc = sprintf( '%.1f', $unknown * 100 / $total );
+ $perc =~ s/.0$//;
+ $sorted{$perc}{'unknown/cloak'} = "$unknown ($perc%)" if ($unknown);
+
+ foreach ( keys %ver ) {
+ my $count = scalar keys %{ $ver{$_} };
+ $perc = sprintf( '%.01f', $count * 100 / $total );
+ $perc =~ s/.0$//; # lame compression.
+
+ $sorted{$perc}{$_} = "$count ($perc%)";
+ }
+
+ ### can be compressed to a map?
+ my @list;
+ foreach ( sort { $b <=> $a } keys %sorted ) {
+ my $perc = $_;
+ foreach ( sort keys %{ $sorted{$perc} } ) {
+ push( @list, "$_ - $sorted{$perc}{$_}" );
+ }
+ }
+
+ # hack. this is one major downside to scheduling.
+ $chan = $c;
+ &performStrictReply(
+ &formListReply( 0, "IRC Client versions for $c ", @list ) );
+
+ # clean up not-needed data structures.
+ undef %ver;
+ undef @vernick;
+ }
+ );