html/centericq.pl


   1 # $Id: centericq.pl,v 1.0.0 2002/10/19 13:15:49 Garion Exp $
   2 
   3 $VERSION = "1.0.0";
   4 %IRSSI = (
   5     authors     => "Joost \"Garion\" Vunderink",
   6     contact     => "joost\@carnique.nl",
   7     name        => "centericq",
   8     description => "Staturbar item which indicates how many new messages you have in your centericq",
   9     license     => "Public Domain",
  10     url         => "http://irssi.org, http://scripts.irssi.org",
  11 );
  12 
  13 # centericq new messages statusbar item
  14 # for irssi 0.8.4 by Timo Sirainen
  15 #
  16 # This statusbar item checks whether you have unread messages in
  17 # ~/.centericq/, and if so, displays a status in your statusbar.
  18 # Example status: [ICQ: JamesOff-1,Linn-3,Paul-4]
  19 #
  20 # Use:
  21 # /script load centericq
  22 # /statusbar <name> add centericq
  23 #
  24 # Known bugs:
  25 # - It only works for ICQ and MSN in centericq.
  26 # - The refreshing is not optimal. You'll need to swap windows to make
  27 #   the statusbar item disappear if you've read the messages.
  28 # - You have to reload the script if you add new people in centericq.
  29 # - Works only with centericq in ~/.centericq/
  30 #
  31 # TODO:
  32 # - Use only the first N letters of the nickname instead of the full
  33 #   nickname.
  34 
  35 use Irssi;
  36 use Irssi::TextUI;
  37 
  38 my $icqdir = $ENV{'HOME'} . "/.centericq";
  39 my ($last_refresh_time, $refresh_tag);
  40 my $statusbar_item;
  41 
  42 # The following vars are all hashes with key the name of the dir in
  43 # ~/.centericq/ of that person
  44  
  45 my %lastreads;    # Timestamp of the last read message, per nick
  46 my %numunreads;   # Number of unread messages, per nick
  47 my %historyts;    # Timestamp of the history file of each nick
  48 my %lastreadts;   # Timestamp of the lastread file of each nick
  49 my %friendnicks;  # The nicknames of the friends
  50 
  51 
  52 #######################################################################
  53 # This is the function that will be called each N seconds, where
  54 # N is given by the centericq_refresh_time setting.
  55 
  56 sub refresh_centericq {
  57   check_new_friends();
  58 
  59   my @friends = keys(%lastreads);
  60   my ($friend, $changed) = ("", 0);
  61   foreach $friend (@friends) {
  62     if (history_changed($friend) || lastread_changed($friend)) {
  63       $changed = 1; 
  64       update_status($friend);
  65     }
  66   }
  67 
  68   if ($changed) {
  69     update_statusbar_item();
  70   }
  71 
  72   # Adding new timeout to make sure that this function will be called
  73   # again
  74   if ($refresh_tag) {
  75     Irssi::timeout_remove($refresh_tag)
  76   }
  77   my $time = Irssi::settings_get_int('centericq_refresh_time');
  78   $refresh_tag = Irssi::timeout_add($time*1000, 'refresh_centericq', undef);
  79 }
  80 
  81 
  82 #######################################################################
  83 # Checks if any new friends have been added. Not yet functional.
  84 
  85 sub check_new_friends {
  86   #Irssi::print("Checking if there are any new friends...");
  87 }
  88 
  89 #######################################################################
  90 # Checks if the last modified date/time of the lastread file has changed.
  91 # A -lot- more efficient than reading and processing the whole file :)
  92 
  93 sub lastread_changed {
  94   my ($friend) = @_;
  95 
  96   my $lr = get_lastread($friend);
  97   if ($lr != $lastreads{$friend}) {
  98     #Irssi::print("Lastread of $friendnick{$friend} changed from $lastreads{$friend} to $lr.");
  99     $lastreads{$friend} = $lr;
 100     return 1;
 101   }
 102 
 103   return 0;
 104 }
 105 
 106 #######################################################################
 107 # Checks if the last modified date/time of the history file has changed.
 108 # A -lot- more efficient than reading and processing the whole file :)
 109 
 110 sub history_changed {
 111   my ($friend) = @_;
 112   my $ts = get_historyts($friend);
 113   if ($ts != $historyts{$friend}) {
 114     #Irssi::print("History ts of $friendnick{$friend} changed from $historyts{$friend} to $ts.");
 115     $historyts{$friend} = $ts;
 116     return 1;
 117   }
 118 
 119   return 0;
 120 }
 121 
 122 #######################################################################
 123 # Reads the last read message and determines the number of unread
 124 # messages of $friend.
 125 
 126 sub update_status {
 127   my ($friend) = @_;
 128   $lastreads{$friend}   = get_lastread($friend);
 129   $numunreads{$friend}  = get_numunreads($friend);
 130 }
 131 
 132 #######################################################################
 133 # Gets the number of unread messages of all nicks and puts them together
 134 # in a nice statusbar string.
 135 # It then requests a statusbar item redraw.
 136 
 137 sub update_statusbar_item {
 138   #Irssi::print("Updating statusbaritem...");
 139   $statusbar_item = "";
 140 
 141   my @keys = keys(%lastreads);
 142   my ($key, $status);
 143 
 144   foreach $key(@keys) {
 145     if ($numunreads{$key} > 0) {
 146       #Irssi::print("$friendnick{$key} has $numunreads{$key} unreads.");
 147       $status .= $friendnick{$key} . "-" . $numunreads{$key} . ",";
 148     }
 149   }
 150   $status =~ s/,$//;
 151   if (length($status) > 0) {
 152     $statusbar_item = "ICQ: " . $status; 
 153     Irssi::statusbar_items_redraw('centericq');
 154   }
 155 }
 156 
 157 
 158 #######################################################################
 159 # This is the function called by irssi to obtain the statusbar item
 160 # for centericq.
 161 
 162 sub centericq {
 163   my ($item, $get_size_only) = @_;
 164 
 165   if (length($statusbar_item) == 0) {
 166     # no icq - don't print the [ICQ] at all
 167     if ($get_size_only) {
 168       $item->{min_size} = $item->{max_size} = 0;
 169     }
 170   } else {
 171     $item->default_handler($get_size_only, undef, $statusbar_item, 1);
 172   }
 173 }
 174 
 175 #######################################################################
 176 # Initialization of the hashes with the useful data.
 177 
 178 sub init {
 179   if (!opendir(ICQDIR, $icqdir)) {
 180     Irssi::print("There is no directory $icqdir, which is needed for this script.");
 181     return 0;
 182   }
 183  
 184   my ($icqfriends, $msnfriends) = (0, 0); 
 185   while ($filename = readdir(ICQDIR)) {
 186     # ICQ friends
 187     if ($filename =~ /^[0-9]+$/ && $filename !~ /^0$/) {
 188       $icqfriends++;
 189       init_friend($filename);
 190     }
 191     # MSN friends
 192     if ($filename =~ /^m.+/ && $filename !~ /^modelist$/ ) {
 193       $msnfriends++;
 194       init_friend($filename);
 195     }
 196   }
 197   Irssi::print("Watching $icqfriends ICQ friends and $msnfriends MSN friends.");
 198 
 199   closedir(ICQDIR);
 200   return 1;
 201 }
 202 
 203 #######################################################################
 204 # Initialises all data of $friend
 205 
 206 sub init_friend {
 207   my ($friend) = @_;
 208 
 209   $lastreads{$friend}   = get_lastread($friend);
 210   $numunreads{$friend}  = get_numunreads($friend);
 211   #$filesizes{$friend}   = get_filesize($friend);
 212   $friendnick{$friend}  = get_nickname($friend);
 213   $historyts{$friend}   = get_historyts($friend);
 214   #Irssi::print("Initilialized $friendnick{$friend}.");
 215 }
 216 
 217 #######################################################################
 218 # Returns the last read message of $friend
 219 
 220 sub get_lastread {
 221   my ($friend) = @_;
 222   my $lastreadfile = $icqdir . "/" . $friend . "/lastread"; 
 223 
 224   open(F, "<$lastreadfile") || return 0; #die("Could not open $lastreadfile.");;
 225   my $lastrd = <F>;
 226   close(F);
 227   chop($lastrd);
 228   #Irssi::print("Found lastread $lastrd of $friend from $lastreadfile.");
 229 
 230   return $lastrd;
 231 }
 232 
 233 #######################################################################
 234 # Returns the number of unread messages for $friend
 235 
 236 sub get_numunreads {
 237   my ($friend) = @_;
 238   my $lr = $lastreads{$friend};
 239   # Unknown last read message - return 0.
 240   if ($lr == 0) {
 241     return 0;
 242   }
 243 
 244   my $msgfile = $icqdir . "/" . $friend . "/history";
 245   open(F, "<$msgfile") || return 0; #die("Could not open $msgfile.");
 246   my @lines = <F>;
 247   chop(@lines);
 248   close(F);
 249 
 250   my $numlines = @lines;
 251 
 252   # read all lines up to the lastread message
 253   my $line;
 254   my $bla = 0;
 255   do {
 256     $line = shift(@lines);
 257     $bla++;
 258   } while ($line ne $lr);
 259   
 260   # now count the number of times that "MSG" is found on a line below
 261   # a line with "IN"
 262   my $count = 0;
 263   my $incoming = 0;
 264   my $verify = 0;
 265   my $bli = 0;
 266   
 267   for (@lines) {
 268     $bli++;
 269     # Sometimes 2 messages get in at the same time. Remove this so-called
 270     # new message if it has the same time as the last read message.
 271     if ($verify == 1) {
 272       if ($_ =~ /$lr/) {
 273         $count--;
 274       }
 275       $verify = 0;
 276     }
 277     # A line with "IN" has been found; check if the next line is "MSG".
 278     if ($incoming == 1) {
 279       if ($_ =~ /^MSG/) {
 280         $count++;
 281 	$verify = 1;
 282       }
 283       $incoming = 0;
 284     }
 285     # Check for "IN".
 286     if ($_ =~ /^IN/) {
 287       $incoming = 1;
 288     }
 289   }
 290 
 291   return $count;
 292 }
 293 
 294 #######################################################################
 295 # Returns the nickname of a friend. This is taken from the 46th line
 296 # of the info file. Let's hope that centericq does not change its
 297 # config file format.
 298 
 299 sub get_nickname {
 300   my ($friend) = @_;
 301 
 302   my $infofile = $icqdir . "/" . $friend . "/info";
 303   open(F, "<$infofile") || return $friend; #die("Could not open $msgfile.");
 304   my @lines = <F>;
 305   chop(@lines);
 306   close(F);
 307  
 308   return $lines[45];
 309 }
 310 
 311 #######################################################################
 312 # Returns the timestamp of the history file of $friend.
 313 
 314 sub get_historyts {
 315   my ($friend) = @_;
 316   my $histfile = $icqdir . "/" . $friend .  "/history";
 317   my @stat = stat($histfile);
 318   return $stat[9];
 319 }
 320 
 321 #######################################################################
 322 # Adding stuff to irssi
 323 
 324 Irssi::settings_add_int('misc', 'centericq_refresh_time', 120);
 325 #Irssi::settings_add_bool('misc', 'centericq_debug', 0);
 326 Irssi::statusbar_item_register('centericq', '{sb $0-}', 'centericq');
 327 
 328 #######################################################################
 329 # Startup functions
 330 
 331 if (init() == 0) {
 332   Irssi::print("You need centericq for this script.");
 333   return 0;
 334 }
 335 update_statusbar_item();
 336 refresh_centericq();
 337 
 338 Irssi::print("Centericq statusbar item loaded.");
 339 
 340 #######################################################################