html/dccstat.pl


   1 use Irssi::Irc;
   2 use Irssi 20020217; # Irssi 0.8.0
   3 use vars qw($VERSION %IRSSI);
   4 $VERSION = "1.52";
   5 %IRSSI = (
   6     authors     => "Matti 'qvr' Hiljanen",
   7     contact     => 'matti\@hiljanen.com',
   8     contributors => 'stefan@pico.ruhr.de, dieck@gmx.de, peder@ifi.uio.no',
   9     name        => "dccstat",
  10     description => "Shows verbose or short information of dcc send/gets on statusbar (speed, size, eta etc.)",
  11     license     => "GPL, Version 2",
  12     url         => "http://matin.maapallo.org/softa/irssi",
  13     sbitems     => "dccstat"
  14 );
  15 
  16 # Theme settings:
  17 #   sb_dccstat = "{sb $0-}";
  18 #       $0 = sb_ds_short(_waiting)/sb_ds_normal(_waiting)
  19 #   sb_ds_short = "$0%G:%n$1%Y@%n$2kB/s%G:%n$4%G:%n$3";
  20 #       $0 = G/S
  21 #       $1 = filename
  22 #       $2 = transfer speed
  23 #       $3 = percent
  24 #       $4 = progressbar
  25 #   sb_ds_short_waiting = "$0%G:%n$1 $2 $3 waiting";
  26 #       $0 = G/S
  27 #       $1 = filename
  28 #       $2 = to/from
  29 #       $3 = nick
  30 #   sb_ds_normal = "$0 $1: '$2' $3 of $4 [$8] $9 ($5) $6kB/s ETA: $7";
  31 #       $0 = GET/SEND
  32 #       $1 = nick
  33 #       $2 = filename
  34 #       $3 = transferred amount
  35 #       $4 = full filesize
  36 #       $5 = percent
  37 #       $6 = speed
  38 #       $7 = ETA
  39 #       $8 = progressbar
  40 #       $9 = rotator thingy :)
  41 #   sb_ds_normal_waiting = "$0 $1: '$2' $3 $4 $5 waiting";
  42 #       $0 = GET/SEND
  43 #       $1 = nick
  44 #       $2 = filename
  45 #       $3 = full filesize
  46 #       $4 = to/from
  47 #       $5 = nick
  48 #   sb_ds_separator = ", ";
  49 #
  50 # TODO:
  51 #   new ideas more than welcome :) 
  52 # 
  53 # FAQ:
  54 #   Q: my input line gets cleared every time dcc send/get starts or ends,
  55 #   why's that?!
  56 #   A: it's a bug in irssi which is already fixed in cvs (2002-03-24 Sunday 20:06)
  57 #   so the solution: upgrade to cvs or live with it and wait until the next stable release
  58 #
  59 
  60 
  61 use Irssi::TextUI;
  62 use strict;
  63 
  64 my $dccstat_refresh=5;
  65 my ($refresh_tag, $old_refresh, $new_refresh, $displayed_since);
  66 my $visible = -1;
  67 my $displaying = 0;
  68 my @rot_bar = ('|', '/', '-', '\\\\\\\\');
  69 my $rot_bar_n = 0;
  70 my %dccstat;
  71 
  72 sub cmd_print_help {
  73      Irssi::print(
  74      "%_Dccstat.pl Help:%_\n\n".
  75      "Statusbar called dccstat should have appeared when you loaded this script,\n".
  76      "now you need to add the dccstat item into that statusbar:\n".
  77      "      /statusbar dccstat add dccstat\n".
  78      "      /save\n\n".
  79      " The default verbose mode will produce output like this:  \n".
  80      "      [GET nick: 'foobar.avi' 5500kB of 11MB (50%) 99kB/s ETA: 00:03:00]\n".
  81      " and the short mode looks like this:\n".
  82      "      [G:foobar.avi\@99kB/s:(50%)]\n\n".
  83      " %_/SETs:%_\n".
  84      "  /set dccstat_refresh <secs> (default: 5)\n".
  85      "  /set dccstat_short_mode <ON/OFF> (default: OFF)\n".
  86      "      shorter output and doesn't show DCCs: None when there are no GET/SENDs\n".
  87      "  /set dccstat_hide_sbar_when_inactive <ON/OFF> (default: OFF)\n".
  88      "      hides the statusbar called dccstat when there are no GET/SENDs\n".
  89      "  /set dccstat_auto_short_limit (default: 2)\n".
  90      "      amount of dcc sends/gets we can have before we automagically switch to short mode\n".
  91      "      (when all the info wouldn't fit to statusbar). setting it to 0 will disable it.\n".
  92      "  /set dccstat_progbar_width (default: 10)\n".
  93      "      progressbar width in chars\n".
  94      "  /set dccstat_progbar_transferred (default: '%%g=%%n')\n".
  95      "  /set dccstat_progbar_position (default: '%%y>%%n')\n".
  96      "  /set dccstat_progbar_remaining (default: '%%r-%%n')\n".
  97      "  /set dccstat_cycle_through_transfers (default: OFF)\n".
  98      "      cycle trough the transfers (ON) or show all transfers at the same time (OFF, default)\n".
  99      "  /set dccstat_cycle_through_transfers_refresh <secs> (default: 5)\n".
 100      "      how long to show one transfer at  a time\n".
 101      "  /set dccstat_filename_max_length (default: 17)\n".
 102      "  /set dccstat_filename_max_length_shortmode (default: 10)\n".
 103      "      how much to show of a filename in normal and short modes\n\n".
 104      "  /set dccstat_EXPERIMENTAL_fast_refresh (default: OFF)\n".
 105      "      use very experimental and super fast refreshing, will probably consume all cpu power,\n".
 106      "      depending on your connection speed. but hey, it's fun :)\n".
 107      "  /set dccstat_debug (default: OFF)\n".
 108      "      show debug messages\n".
 109      " \n".
 110      "\nSee also: STATUSBAR, DCC and theme help in the actual script"
 111      ,MSGLEVEL_CRAP);
 112 }
 113      
 114 sub debug {
 115     my ($text) = @_;
 116     return unless Irssi::settings_get_bool('dccstat_debug');
 117     my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = 
 118       localtime(time);
 119     $sec = sprintf("%02d", $sec);
 120     $min = sprintf("%02d", $min);
 121     $hour = sprintf("%02d", $hour);
 122     Irssi::print("DEBUG(%_Dccstat.pl%_): ".$text." [$hour:$min:$sec]");
 123 }
 124 
 125 sub startup_check {
 126     debug("START-UP - DEBUG IS ON");
 127     my @dccs = Irssi::Irc::dccs();
 128     my $act;
 129     foreach my $dcc (@dccs) { $act=$dcc if $dcc->{type} eq "SEND" || $dcc->{type} eq "GET"; };
 130     dcc_connected($act);
 131 }
 132 
 133 sub dcc_connected {
 134     debug("entering dcc_connected");
 135     my ($dcc) = @_;
 136     return unless $dcc->{type} eq "SEND" || $dcc->{type} eq "GET";
 137     debug("removing dcc connected -signal");
 138     Irssi::signal_remove('dcc connected', 'dcc_connected');
 139     my $refresh_msecs = (Irssi::settings_get_int('dccstat_refresh')*1000);
 140     $refresh_msecs = ($dccstat_refresh*1000) if $refresh_msecs < 1000;
 141     debug("adding normal timeout..");
 142     $refresh_tag=Irssi::timeout_add($refresh_msecs, 'refresh_dccstat', undef);
 143     $old_refresh=Irssi::settings_get_int('dccstat_refresh');
 144     Irssi::signal_add_last('dcc destroyed', 'dcc_checklast');
 145     refresh_dccstat();
 146 }
 147 
 148 sub dcc_setupcheck {
 149    $new_refresh = Irssi::settings_get_int('dccstat_refresh');
 150    if ($new_refresh != $old_refresh) {
 151       debug("setting a new refresh timeout");
 152 	  $new_refresh = ($new_refresh*1000);
 153 	  Irssi::timeout_remove($refresh_tag);
 154 	  $new_refresh = ($dccstat_refresh*1000) if $new_refresh < 1000;
 155 	  $refresh_tag=Irssi::timeout_add($new_refresh, 'refresh_dccstat', undef);
 156 	  $old_refresh=Irssi::settings_get_int('dccstat_refresh');
 157    }
 158    refresh_dccstat();
 159 }
 160 
 161 sub dcc_checklast {
 162     my @dccs     = Irssi::Irc::dccs();
 163     my $count    = dcc_getcount();
 164     debug("check for last, count is '$count'");
 165     return unless $count == 0;
 166     debug("was last, removing timeout '$refresh_tag'");
 167     Irssi::timeout_remove($refresh_tag);
 168     Irssi::signal_remove('dcc destroyed', 'dcc_checklast');
 169     Irssi::signal_add('dcc connected', 'dcc_connected');
 170     refresh_dccstat();
 171 }
 172 
 173 # this function calculates the average speed of the last 10 seconds.
 174 # i think that's better than irssis default way of calculating the 
 175 # average speed from the whole transfer
 176 sub dcc_calcSpeed {
 177    my @dccs = Irssi::Irc::dccs();
 178    foreach my $dcc (@dccs) {
 179       next unless $dcc->{type} eq "SEND" || $dcc->{type} eq "GET";
 180       my $id = "$dcc->{created}" . "$dcc->{addr}" . "$dcc->{port}";
 181       if (defined($dccstat{$id}{'speed'})) {
 182          my $old = $dccstat{$id}{'position'};
 183          my $current = $dcc->{transfd};
 184          my $speed = (($current-$old)/10);
 185          unless ($dccstat{$id}{'speed'} == "-1" && ($current-$old) == 0) {
 186             $dccstat{$id}{'speed'} = $speed;
 187          }
 188          $dccstat{$id}{'position'} = $current;
 189       } else {
 190          # new dcc
 191          my $id = "$dcc->{created}" . "$dcc->{addr}" . "$dcc->{port}";
 192          debug("creating dcc hash '$id'");
 193          $dccstat{$id}{'speed'} = "-1";
 194          $dccstat{$id}{'position'} = "0";
 195       }
 196    }
 197 
 198     # let's remove old hashes
 199     foreach my $hash (keys %dccstat) {
 200        my $keep = 0;
 201        foreach my $dcc (@dccs) {
 202           my $id = "$dcc->{created}" . "$dcc->{addr}" . "$dcc->{port}";
 203           $keep = 1 if ($hash == $id);
 204        }
 205        if ($keep) {
 206           debug("dcc '$hash' is still active, it's speed is '" . $dccstat{$hash}{'speed'} . "'");
 207        } else {
 208           debug("deleting dcc '$hash'");
 209           delete $dccstat{$hash};
 210        }
 211     }     
 212 }
 213 
 214 ### this function originally implemented by dieck@gmx.de
 215 sub dcc_calculateETA {
 216     my $dcc = $_[0];
 217     my ($dccspeed, $dccleft, $going, $dccsecs, $dcctime);
 218     
 219     # calculate current speed
 220     $going=(time-$dcc->{starttime});
 221     $going=1 if $going==0;
 222     my $id = "$dcc->{created}" . "$dcc->{addr}" . "$dcc->{port}";
 223     if (defined($dccstat{$id})) {
 224        $dccspeed=$dccstat{$id}{'speed'};
 225     } else {
 226        $dccspeed = -1;
 227     }
 228     ## speed in bytes/sec
 229     if ($dccspeed > 0) {
 230     
 231        # calculate left transfer size
 232        $dccleft = ($dcc->{size}-$dcc->{transfd});
 233        ## size left in byte
 234     
 235        $dccspeed=1 if $dccspeed==0;
 236        $dccsecs = $dccleft / $dccspeed;  
 237     
 238        $dcctime =  sprintf("%02d:%02d:%02d", int($dccsecs/60/60), int($dccsecs/60%60), int($dccsecs%60));
 239     } elsif ($dccspeed == "0") {
 240        $dcctime = "stalled";
 241     } elsif ($dccspeed == "-1") {
 242        $dcctime = "???";
 243     } else {
 244        # panic!
 245        $dcctime = "error!";
 246     }
 247     return $dcctime; 
 248 }
 249 
 250 ### this function originally implemented by stefan_tomanek@web.de 
 251 sub dcc_progbar {
 252     my ($dcc) = @_;
 253     my ($filebar, $nobar);
 254     my $barwidth = Irssi::settings_get_int('dccstat_progbar_width');
 255     my $char1 = Irssi::settings_get_str('dccstat_progbar_transferred');
 256     my $char2 = Irssi::settings_get_str('dccstat_progbar_position');
 257     my $char3 = Irssi::settings_get_str('dccstat_progbar_remaining');
 258     if ($dcc->{size} > 0) {
 259         my $width_per_size = ($barwidth) / $dcc->{size};
 260         my $transf_chars = sprintf("%.0f",($width_per_size * $dcc->{transfd}));
 261         $filebar = $char1 x $transf_chars; 
 262         $nobar = $char3 x ($barwidth - $transf_chars - 1);
 263         return "${filebar}${char2}${nobar}";
 264     } else {
 265         return $barwidth x $char3;
 266     }
 267 }
 268 
 269 sub dcc_calculateSIZE {
 270     my $fsize = $_[0];
 271     my ($size, $unit, $div);
 272     
 273     if       ($fsize >= 1024*1024*1024)  { $size = $fsize/1024/1024/1024; $unit = "GB"; $div = 2; }
 274     elsif    ($fsize >= 1024*1024)       { $size = $fsize/1024/1024; $unit = "MB";  $div = 2; }
 275     elsif    ($fsize >= 1024)            { $size = $fsize/1024; $unit = "kB"; $div = 0; }
 276     else                                 { $size = $fsize; $unit = "B"; $div = 0; }
 277     $size = sprintf("%.${div}f", $size);
 278     return "${size}${unit}";
 279 }
 280 
 281 sub dcc_getcount { 
 282     my @dccs  = Irssi::Irc::dccs();
 283     my $count = 0;
 284     foreach my $dcc (@dccs) { $count++ if $dcc->{type} eq "GET" || $dcc->{type} eq "SEND"; }
 285     return $count;
 286 }
 287 
 288 sub dccstat {
 289     #debug("going into main function"); 
 290     my ($item, $get_size_only) = @_;
 291     my @dccs=Irssi::Irc::dccs();
 292     my (@results, $results);
 293     my $mode      = Irssi::settings_get_bool('dccstat_short_mode');
 294     my $exp_flags = Irssi::EXPAND_FLAG_IGNORE_EMPTY | Irssi::EXPAND_FLAG_IGNORE_REPLACES;
 295     my $theme     = Irssi::current_theme();
 296     my $format    = $theme->format_expand("{sb_dccstat}");
 297     my $count     = dcc_getcount();
 298     if ($count>0) {
 299 	my $sendcount=0;
 300 	my $getcount=0;
 301 	my (
 302 	    $dccpercent,   $dccspeed,      $dcctype,   $going, 
 303 	    $dccnick,      $dccfile,       $FooOfBar,  $str, 
 304 	    $fsize,        $transize,      $dcceta,    $from, 
 305 	    $to,           $direction,     $prep,      $autolimit,
 306 	    $separator,    $dccprogbar,    $dccrotbar
 307 	   );
 308 	foreach my $dcc (@dccs) {
 309 	    next unless $dcc->{type} eq "SEND" || $dcc->{type} eq "GET";
 310 	    # if count is above the autolimit, we'll force the mode to short
 311         # but not if we're cycling through transfers.
 312         if (not Irssi::settings_get_bool('dccstat_cycle_through_transfers')) {
 313            $autolimit=Irssi::settings_get_int('dccstat_auto_short_limit');
 314 	       $mode=1 if $count > $autolimit && $autolimit > 0;
 315         }
 316 	    
 317 	    $sendcount++ if $dcc->{type} eq "SEND";
 318 	    $getcount++ if $dcc->{type} eq "GET";
 319 	    
 320 	    $dccpercent = ($dcc->{size} == 0) ? "(0%)" : sprintf("%.1f", $dcc->{transfd}/$dcc->{size}*100)."%%";
 321 	    
 322        $going = (time-$dcc->{starttime});
 323 	   $going = 1 if $going==0;
 324         
 325 	    my $id = "$dcc->{created}" . "$dcc->{addr}" . "$dcc->{port}";
 326         if (defined($dccstat{$id})) {
 327            $dccspeed = $dccstat{$id}{'speed'};
 328         } else {
 329            $dccspeed = -1;
 330         }
 331         if ($dccspeed >= 0) {
 332            $dccspeed = sprintf("%.2f", ($dccspeed/1024));
 333         } else {
 334            $dccspeed = sprintf("%.2f", ($dcc->{transfd}-$dcc->{skipped})/$going/1024);
 335         }
 336               
 337         $dcctype = $dcc->{type};
 338 	    
 339 	    $dccnick = $dcc->{nick};
 340 	    $dccnick =~ s/\\/\\\\/g;
 341 	    $dccfile = $dcc->{arg};
 342 	    $dccfile =~ s/ /\240/g;
 343 	    $dccfile =~ s/\\/\\\\/g; 
 344 	    
 345 	    # if filename is longer than 17 chars, we'll show only the first 15 chars
 346 	    # and in short mode we'll show only 8 chars
 347         # (lengths are now configurable, but the idea is the same)
 348 	    my $max_normal = Irssi::settings_get_int('dccstat_filename_max_length');
 349         my $max_short = Irssi::settings_get_int('dccstat_filename_max_length_shortmode');
 350 	    if (!$mode) { 
 351            $dccfile=substr($dccfile, 0, $max_normal-2).".." if (length($dccfile) > $max_normal); 
 352         } else {
 353            $dccfile=substr($dccfile, 0, $max_short-2).".." if (length($dccfile) > $max_short); 
 354         }
 355 	    
 356 	    $fsize      = dcc_calculateSIZE($dcc->{size});
 357 	    $transize   = dcc_calculateSIZE($dcc->{transfd});
 358 	    $dccprogbar = dcc_progbar($dcc);
 359 	    $dccprogbar =~ s/ /\240/g;
 360 	    $dcceta     = dcc_calculateETA($dcc);
 361 	    
 362 	    if ($dcctype eq "GET") { $direction = "G"; $prep = "from"; }
 363 	    if ($dcctype eq "SEND") { $direction = "S"; $prep = "to"; }
 364 	    
 365 	    $dccrotbar  = $rot_bar[$rot_bar_n];
 366 	    
 367 	    # short mode?
 368 	    if ($mode) {
 369 		# theme?
 370 		if ($format) {
 371 		    if ($dcc->{starttime} > 0) {
 372 			$str = $theme->format_expand("{sb_ds_short $direction $dccfile $dccspeed $dccpercent $dccprogbar $dccrotbar}", $exp_flags);
 373 		    } else {
 374 			$str = $theme->format_expand("{sb_ds_short_waiting $direction $dccfile $prep $dccnick}", $exp_flags);
 375 		    }
 376 		} else {
 377 		    $str = "$direction%G:%n$dccfile";
 378 		    $str .= ($dcc->{starttime} > 0) ? "%G@%n${dccspeed}kB/s%G:%n$dccprogbar%G:%n$dccrotbar%G:%n$dccpercent" : " $prep $dccnick waiting";
 379 		}
 380 	    } else {
 381 		if ($format) {
 382 		    if ($dcc->{starttime} > 0) {
 383 			$str = $theme->format_expand("{sb_ds_normal $dcctype $dccnick $dccfile $transize $fsize $dccpercent $dccspeed $dcceta $dccprogbar $dccrotbar}", $exp_flags);
 384 		    } else {
 385 			$str = $theme->format_expand("{sb_ds_normal_waiting $dcctype $dccnick $dccfile $fsize $prep $dccnick}", $exp_flags);
 386 		    }
 387 		} else {
 388 		    $str = "$dcctype $dccnick: '$dccfile'";
 389 		    $str .= ($dcc->{starttime} > 0) ? " $transize of $fsize [$dccprogbar] $dccrotbar ($dccpercent) ${dccspeed}kB/s ETA: $dcceta" : " $fsize $prep $dccnick waiting";
 390 		}
 391 	    }
 392 	    push @results,$str;
 393 	}
 394 	if (not Irssi::settings_get_bool('dccstat_cycle_through_transfers')) {
 395 	    $separator = ($theme->format_expand("{sb_ds_separator}")) ? $theme->format_expand("{sb_ds_separator}") : ", ";
 396 	    $results   = join("$separator", @results);
 397 	} else {
 398 	    if (scalar(@results)-1 < $displaying) { $displaying = 0 };
 399 	    $results = @results[$displaying];
 400         if (not $get_size_only) {
 401            if ((time-$displayed_since) >= (Irssi::settings_get_int('dccstat_cycle_through_transfers_refresh'))) {
 402               debug("refreshing cycle display");
 403               $displaying++;
 404               $displayed_since = time;
 405            }
 406         }
 407 	}
 408     } else {
 409 	$results="%_DCCs:%_ None" if !$mode;
 410     }
 411     if ($format) {
 412 	if ($count > 0) {
 413 	    $results = "{sb_dccstat $results}"
 414 	} else {
 415 	    $results = "{sb_dccstat $results}" unless $mode;
 416 	}
 417     } else {
 418 	if ($count > 0) {
 419 	    $results = "{sb $results}";
 420 	} else {
 421 	    $results = "{sb $results}" unless $mode;
 422 	}
 423     }
 424     $item->default_handler($get_size_only, "$results", undef, 1);
 425 }
 426 
 427 sub refresh_dccstat {
 428     #debug("refreshing item");
 429     my $hide      = Irssi::settings_get_bool('dccstat_hide_sbar_when_inactive');
 430     my $count     = dcc_getcount();
 431     
 432     if ($hide && $count == 0) {
 433 	if ($visible == -1 || $visible == 1) {
 434 	    Irssi::command("statusbar dccstat disable");
 435 	    debug("disabling statusbar");
 436 	    $visible = 0;
 437 	}
 438 	return;
 439     }
 440     if ($visible == 0 || $visible == -1) {
 441 	Irssi::command("statusbar dccstat enable");
 442 	debug("enabling statusbar");
 443 	$visible = 1;
 444     }
 445     Irssi::statusbar_items_redraw('dccstat');
 446     $rot_bar_n++;
 447     $rot_bar_n %= @rot_bar;
 448     
 449 }
 450 
 451 my $fref = 0;
 452 sub dcc_fast_refresh {
 453     if (Irssi::settings_get_bool('dccstat_EXPERIMENTAL_fast_refresh')) 
 454     {
 455        refresh_dccstat();
 456        $fref++;
 457        debug("transfer updated! ($fref)");
 458     }
 459 }
 460 
 461 Irssi::settings_add_int($IRSSI{'name'}, "dccstat_refresh", $dccstat_refresh);
 462 Irssi::settings_add_bool($IRSSI{'name'}, 'dccstat_short_mode', 0);
 463 Irssi::settings_add_bool($IRSSI{'name'}, 'dccstat_hide_sbar_when_inactive', 0);
 464 Irssi::settings_add_int($IRSSI{'name'}, 'dccstat_auto_short_limit', 2);
 465 Irssi::settings_add_int($IRSSI{'name'}, 'dccstat_progbar_width', 10);
 466 Irssi::settings_add_str($IRSSI{'name'}, 'dccstat_progbar_transferred', '%g=%n');
 467 Irssi::settings_add_str($IRSSI{'name'}, 'dccstat_progbar_position', '%y>%n');
 468 Irssi::settings_add_str($IRSSI{'name'}, 'dccstat_progbar_remaining', '%r-%n');
 469 Irssi::settings_add_bool($IRSSI{'name'}, 'dccstat_cycle_through_transfers', 0);
 470 Irssi::settings_add_int($IRSSI{'name'}, 'dccstat_cycle_through_transfers_refresh', 10);
 471 Irssi::settings_add_bool($IRSSI{'name'}, 'dccstat_EXPERIMENTAL_fast_refresh', 0);
 472 Irssi::settings_add_bool($IRSSI{'name'}, 'dccstat_debug', 0);
 473 Irssi::settings_add_int($IRSSI{'name'}, 'dccstat_filename_max_length', 17);
 474 Irssi::settings_add_int($IRSSI{'name'}, 'dccstat_filename_max_length_shortmode', 10);
 475 
 476 Irssi::command_bind('dccstat', 'cmd_print_help');
 477 
 478 Irssi::statusbar_item_register('dccstat', undef, 'dccstat');
 479 Irssi::timeout_add('10000', 'dcc_calcSpeed', undef);
 480 Irssi::signal_add('dcc connected', 'dcc_connected');
 481 Irssi::signal_add( 
 482 		  { 
 483 		   'setup changed'       =>  \&dcc_setupcheck,
 484 		   'dcc request'         =>  \&refresh_dccstat,
 485 		   'dcc created'         =>  \&refresh_dccstat,
 486 		   'dcc destroyed'       =>  \&refresh_dccstat,
 487 		   'dcc transfer update' =>  \&dcc_fast_refresh,
 488 		  } 
 489 		 );
 490 
 491 # Startup
 492 startup_check();
 493 refresh_dccstat();
 494 
 495 # lets save some global variables
 496 $old_refresh    = Irssi::settings_get_int('dccstat_refresh');
 497 
 498 Irssi::print("Dccstat.pl loaded - /dccstat for help");
 499 
 500 # EOF