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