diff options
-rw-r--r-- | bayes | 18 | ||||
-rw-r--r-- | lib/MaildirIndexer/Email.pm6 | 21 | ||||
-rw-r--r-- | lib/MaildirIndexer/Parser.pm6 | 8 | ||||
-rw-r--r-- | lib/MaildirIndexer/Store.pm6 | 43 |
4 files changed, 84 insertions, 6 deletions
@@ -2,21 +2,31 @@ use v6.d.PREVIEW; use lib 'lib'; use MaildirIndexer::ScanDir; -use MaildirIndexer::Parser; +use MaildirIndexer::Store; sub MAIN($maildir) { + my $store = MaildirIndexer::Store.new; + my $file-supply = scan-dir($maildir); my $file-channel = $file-supply.Channel; + for ^10 { start react { whenever $file-channel -> $file { if $file.e && $file.f { - my $email = parse-email($file,:headers-only); - say "{$file} - {$email<headers><Subject>}"; + $store.add-file($file); + } + elsif !$file.e { + $store.del-file($file); } } } } - react whenever signal(SIGINT) { exit } + react { + whenever signal(SIGINT) { exit } + whenever signal(SIGHUP) { + $store.dump(); + } + } } diff --git a/lib/MaildirIndexer/Email.pm6 b/lib/MaildirIndexer/Email.pm6 new file mode 100644 index 0000000..f5d1c39 --- /dev/null +++ b/lib/MaildirIndexer/Email.pm6 @@ -0,0 +1,21 @@ +use v6.d.PREVIEW; +unit class MaildirIndexer::Email; + +has %!headers; +has $!body; + +method BUILD(:%!headers,:$!body) { } + +method message-id { split-refs(%!headers<message-id>)[0] } +method refs { + return |( + split-refs(%!headers<in-reply-to>), + split-refs(%!headers<references>).reverse, + ); +} + +multi split-refs(Any) { return (); } +multi split-refs(Str:D $str) { + return $/<refs>».Str if $str ~~ m{'<' $<refs> = (<-[<>]>+)+ % [ '>' .*? '<' ] '>' }; + return (); +} diff --git a/lib/MaildirIndexer/Parser.pm6 b/lib/MaildirIndexer/Parser.pm6 index 90b3678..c2425fe 100644 --- a/lib/MaildirIndexer/Parser.pm6 +++ b/lib/MaildirIndexer/Parser.pm6 @@ -1,5 +1,6 @@ use v6.d.PREVIEW; unit module MaildirIndexer::Parser; +use MaildirIndexer::Email; my @separators = ( "\x0a\x0d\x0a\x0d", @@ -38,13 +39,16 @@ grammar Message { class Message-actions { method TOP($/) { - make %( headers => $/<headers>.made, body => $/<body>.Str ); + make MaildirIndexer::Email.new( + headers => $/<headers>.made, + body => $/<body>.Str, + ); } method headers($/) { make %( |$/<header>».made ); } method header($/) { - make $/<junk> ?? () !! ( $/<name>.Str => $/<value>.made ); + make $/<junk> ?? () !! ( $/<name>.Str.lc => $/<value>.made ); } method value($/) { make $/<line>.join(' ') diff --git a/lib/MaildirIndexer/Store.pm6 b/lib/MaildirIndexer/Store.pm6 new file mode 100644 index 0000000..cbfcfa1 --- /dev/null +++ b/lib/MaildirIndexer/Store.pm6 @@ -0,0 +1,43 @@ +use v6.d.PREVIEW; +unit class MaildirIndexer::Store; +use MaildirIndexer::Parser; + +has %!id-for-file; +has %!mailboxes-for-id; +has $!lock = Lock.new; + +method dump() { + $!lock.protect: { + say "{.key} → {.value}" for %!id-for-file; + say "{.key} ⇒ {.value.perl}" for %!mailboxes-for-id; + } +} + +method add-file(IO $file) { + my $email = parse-email($file,:headers-only); + my $id = $email.message-id or return; + my $mailbox = mailbox-from-path($file.path) or return; + $!lock.protect: { + %!id-for-file{ $file.path } = $id; + %!mailboxes-for-id{ $id }.push($mailbox); + }; + return; +} + +method del-file(IO $file) { + my $mailbox = mailbox-from-path($file.path) or return; + $!lock.protect: { + my $id = %!id-for-file{ $file.path }:delete; + with %!mailboxes-for-id{ $id } { +with .grep($mailbox):k -> $pos { + .splice($pos,1); + } +} + } + return; +} + +sub mailbox-from-path(Str() $path) { + $path ~~ m{'/' (<-[/]>+?) '/' [cur|new|tmp] '/'} and return ~$/[0]; + return Nil; +} |