html/mailcount.pl


   1 # mailcount.pl v 1.4.5 by Marcin Rozycki (derwan@irssi.pl)
   2 #                 changed at Sat Oct 18 14:43:27 CEST 2003
   3 #
   4 # Script adds statusbar item mailcount and displays info about new mails
   5 # in your mailbox ( not support for maildir)
   6 #
   7 # Run command '/statusbar window add mailcount' after loading mailcount.pl.
   8 #
   9 # Modules:
  10 #
  11 #    Mail::MboxParser 
  12 #         http://search.cpan.org/CPAN/authors/id/V/VP/VPARSEVAL/Mail-MboxParser-0.41.tar.gz
  13 #         http://derwan.irssi.pl/perl-modules/Mail-MboxParser-0.41.tar.gz
  14 #
  15 #    Digest::MD5
  16 #         http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/Digest-MD5-2.27.tar.gz
  17 #         http://derwan.irssi.pl/perl-modules/Digest-MD5-2.27.tar.gz
  18 #
  19 # Settings:
  20 #
  21 #    Mailcount_mailbox [ list separated with spaces ] 
  22 #         - ex. /set mailcount_mailbox /var/mail/derwan /home/derwan/inbox
  23 #
  24 #    Mailcount_ofset [ sconds ]
  25 #         - 60 by default
  26 #
  27 #    Mailcount_show_headers [ list separated with spaces ]
  28 #         - ex. /set mailcount_show_headers from to cc subject date sender
  29 #
  30 #    Mailcount_show_max [ count ]
  31 #         - 30 by default
  32 #         - shows all mails if value set to 0
  33 #         - info disabled if set to -1
  34 #
  35 #    Mailcount_sbitem [ format ]
  36 #         - %n - new messages
  37 #         - %o - old messages
  38 #         - %t - total
  39 #
  40 
  41 use strict;
  42 use vars qw($VERSION %IRSSI);
  43 
  44 use Irssi 20021117 qw( settings_add_str settings_get_str settings_add_int settings_get_int
  45    settings_add_bool settings_get_bool get_irssi_dir timeout_add_once theme_register active_win );
  46 
  47 $VERSION = '1.4.5';
  48 %IRSSI = (
  49   authors      => 'Marcin Rozycki',
  50   contact      => 'derwan@irssi.pl',
  51   name         => 'mailcount',
  52   description  => 'Adds statusbar item mailcount and displays info about new mails',
  53   modules      => 'Mail::MboxParser Digest::MD5',
  54   license      => 'GNU GPL v2',
  55   url          => 'http://derwan.irssi.pl',
  56   changed      => 'Sat Oct 18 14:43:27 CEST 2003'
  57 );
  58 
  59 use Irssi::TextUI;
  60 use IO::File;
  61 use POSIX '_exit';
  62 use Mail::MboxParser;
  63 use Digest::MD5 'md5_hex';
  64 
  65 theme_register([
  66    'mailcount_notify', 'You have new mail in %C$0%n',
  67    'mailcount_sender', '%R> %CFrom:%n %_$0%_',
  68    'mailcount_header', '  %c$0:%n $1',
  69    'mailcount_more', '  ( and $0 more... )' 
  70 ]);
  71 
  72 our ($u, $r, $active_pid, $input_tag) = (0, 0, undef, undef);
  73 our (%register, %ctime, %cache, @buf);
  74 
  75 sub mailcount {
  76    return if ( $active_pid or $input_tag );
  77    my $reader = IO::File->new() or return;
  78    my $writer = IO::File->new() or return;
  79    my ($n, $o) = (0, 0);
  80    pipe($reader, $writer);
  81    $active_pid = fork();
  82    return unless ( defined $active_pid );
  83    if ( $active_pid ) {
  84       close($writer);
  85       Irssi::pidwait_add($active_pid);
  86       $input_tag = Irssi::input_add(fileno($reader), INPUT_READ, \&input_read, $reader);
  87    } else {
  88       close($reader);
  89       my $headers = 'from to subject '. lc( settings_get_str('mailcount_show_headers') );
  90       my ($count, $max) = (0, settings_get_int('mailcount_show_max'));
  91       $max = 10 if ( $max > 0 and $max < 10 );
  92       foreach my $box ( split /[: ]+/, settings_get_str('mailcount_mailbox') ) {
  93          push(@buf,"ctime 0 $box", "stat n=0 o=0 $box"), next if ( not -r $box );
  94          my ($mn, $mo, $info, $ctime) = (0, 0, 0, (stat($box))[9]);
  95          if ( $ctime eq $ctime{ $box } ) {
  96              $mn = $cache{ $box }->{ n };
  97              $mo = $cache{ $box }->{ o };
  98          } else {
  99              push @buf, "ctime $ctime $box";
 100              my $mb = Mail::MboxParser->new( $box,
 101                    decode     => 'ALL',
 102                    parseropts => { enable_cache    => 1,
 103                       enable_grep     => 1,
 104                       cache_file_name => sprintf('%s/.mailcount-cache', get_irssi_dir) }
 105             );
 106              while ( my $msg = $mb->next_message ) {
 107                 next if ( $msg->header->{ subject } =~ m/.*\bfolder internal data/i );
 108                 ( $msg->header->{ status } and $msg->header->{ status } =~ m/[OR]+/i ) and ++$mo, next or ++$mn;
 109                 unless ( is_register($msg) ) {
 110                    push @buf, "info $box" unless $info++;
 111                    next if ( ++$count > $max and $max );
 112                    my %header;
 113                    foreach my $header ( split / +/, $headers ) {
 114                       next if ( $header{ $header }++);
 115                       my $data = $msg->header->{ $header };
 116                       push @buf,"header $header $data" if ( defined $data );
 117                    }
 118                 }
 119              }
 120              push @buf, "stat n=$mn o=$mo $box";
 121              push @buf, sprintf('more %d'. ($count - $max)) if ( $max > 0 and $count > $max );
 122           }
 123           $n += $mn; $o += $mo;
 124       }
 125       push(@buf,"total n=$n o=$o");
 126       foreach my $data ( @buf ) { print($writer "$data\n"); }
 127       close($writer);
 128       POSIX::_exit(1);
 129    }
 130 }
 131 
 132 sub is_register ($$) {
 133    my $msg = shift;
 134    my $hex = md5_hex($msg->header->{ from } . $msg->header->{ to } . 
 135         $msg->header->{ subject } . $msg->header->{ 'message-id' });
 136    return 1 if ( $register{ $hex } );
 137    push(@buf,"register $hex");
 138    return 0;
 139 }
 140 
 141 sub input_read {
 142    my $reader = shift;
 143    while (<$reader>) {
 144       chomp;
 145       /^ctime (\d+) (.*)/ and $ctime{ $2 } = $1, next;
 146       /^stat n=(\d+) o=(\d+) (.*)/ and $cache{ $3 }->{ n } = $1, $cache{ $3 }->{ o } = $2, next; 
 147       /^info (.*)/ and active_win->printformat(MSGLEVEL_CLIENTCRAP, 'mailcount_notify', $1), next;
 148       /^register (.*)/ and $register{ $1 } = 1, next;
 149       /^more (\d+)/ and active_win->printformat(MSGLEVEL_CLIENTCRAP, 'mailcount_more', $1), next;
 150       /^total n=(\d+) o=(\d+)/ and $u = $1, $r = $2, last;
 151       /^header ([^\s]+) (.*)/ and mailcount_show_header($1, $2);
 152    }
 153    Irssi::input_remove($input_tag);
 154    close($reader);
 155    $input_tag = $active_pid = undef;
 156    Irssi::statusbar_items_redraw('mailcount');
 157    my $timeout = settings_get_int('mailcount_ofset'); $timeout = 15 if ( $timeout <= 15 );
 158    timeout_add_once($timeout*1000, 'mailcount', undef);
 159 }
 160 
 161 sub mailcount_show_header ($$) {
 162    my ($header, $data) = @_;
 163    $data =~ s/\s+/ /g;
 164    active_win->printformat(MSGLEVEL_CLIENTCRAP, 'mailcount_sender', $data), return 
 165       if ( $header eq 'from' );
 166    active_win->printformat(MSGLEVEL_CLIENTCRAP, 'mailcount_header', ucfirst($header), $data);
 167 }
 168 
 169 sub mailcount_sbitem {
 170   my ($sbitem, $get_size_only) = @_;
 171   $sbitem->{min_size} = $sbitem->{max_size} = 0 if ($get_size_only);
 172   my $sbitem_format = settings_get_str('mailcount_sbitem');
 173   $sbitem_format = 'n/%n o/%o t/%t' unless ( $sbitem_format );
 174   $sbitem_format =~ s/%n/$u/e;
 175   $sbitem_format =~ s/%o/$r/e;
 176   $sbitem_format =~ s/%t/($u + $r)/e;
 177   $sbitem->default_handler($get_size_only, undef, $sbitem_format, 1);
 178 }
 179 
 180 settings_add_str('mailcount', 'mailcount_mailbox', $ENV{'MAIL'});
 181 settings_add_int('mailcount', 'mailcount_ofset', 60);
 182 settings_add_str('mailcount', 'mailcount_show_headers', 'from to cc subject date sender');
 183 settings_add_int('mailcount', 'mailcount_show_max', 30);
 184 settings_add_str('mailcount', 'mailcount_sbitem', 'n/%n o/%o t/%t');
 185 
 186 Irssi::statusbar_item_register('mailcount', '{sb Mail: $0-}', 'mailcount_sbitem');
 187 mailcount();