#!/usr/bin/perl # etff: Eat the Frog First use strict; use Date::Parse; use DB_File::Lock; use Email::Simple; use File::Find; use File::Slurp qw( slurp ) ; use constant DAY => 86400; use constant TASK => 0; use constant META => 1; use constant FILENAME => 2; use constant AGE => 3; use constant DEADLINE => 4; use constant SKIP => 0; use constant CHECK => 1; use constant UNKNOWN => 2; my $DB = '/home/dmarti/.etff'; my $SPAM = '/home/dmarti/Maildir/spam'; my %Todo_messages; my %Item; my $Last_modified = 90; if (-e $DB) { $Last_modified = -M $DB; } my $Now = time(); tie(%Todo_messages, 'DB_File::Lock', [$DB, O_RDWR|O_CREAT, 0660, $DB_HASH], 'write') or die "Can't open $DB (another copy running?)\n"; find (\&wanted, '/home/dmarti/Maildir'); untie(%Todo_messages) or die $!; foreach my $item (values(%Item)) { $item->[DEADLINE] = $Now + 365 * DAY; if ($item->[META] =~ /^done/i) { # recycle old done items? ; } elsif ($item->[META] =~ /^A\b/i) { $item->[DEADLINE] = $Now; } elsif ($item->[META] =~ /^(B)\b/i) { $item->[DEADLINE] = $Now + 7 * DAY; } elsif ($item->[META] =~ /^(C)\b/i) { $item->[DEADLINE] = $Now + 1000 * DAY; } elsif ($item->[META] =~ /^due\s+(.*)/) { $item->[DEADLINE] = str2time($1); } else { defined($ENV{'EDITOR'}) and -e $ENV{'EDITOR'} or die $!; exec ($ENV{'EDITOR'}, $item->[FILENAME]); } } print "Items due today\n----- --- -----\n"; foreach my $item (sort {$a->[DEADLINE] <=> $b->[DEADLINE]} values(%Item)) { next if !$item->[DEADLINE]; next if $Now + 1 * DAY < $item->[DEADLINE]; print "$item->[TASK] $item->[META]\n"; } print "\nOther\n-----\n"; foreach my $item (sort {$a->[DEADLINE] <=> $b->[DEADLINE]} values(%Item)) { next if $item->[DEADLINE] < $Now + 1 * DAY; next if $item->[META] =~ /^done$/i; print "$item->[TASK] $item->[META]\n"; } sub is_todo { my $file = shift; my $result = UNKNOWN; if (exists($Todo_messages{$file})) { $result = $Todo_messages{$file}; } return $result; } sub wanted { my $file = $File::Find::name; next if $file =~ /^$SPAM/; if (-f $file) { if (-M $file < $Last_modified or is_todo($file) != SKIP) { # print "checking $file\n"; my $text = slurp($file); my $email = Email::Simple->new(\$text); if (my $todo = $email->header('X-Todo')) { $Todo_messages{$file} = CHECK; if (my $mid = $email->header('Message-ID')) { unless (exists $Item{$mid} and -M $file > $Item{$mid}->[AGE]) { $Item{$mid} = [$email->header('Subject'), $todo, $file, -M $file]; } else { print "dup $Item{$mid}->[TASK]\n"; } } } else { $Todo_messages{$file} = SKIP; } } } }