+ if (!ref($inbox) && $inbox eq 'watchspam') {
+ return _remove_spam($self, $path);
+ }
+ my $im = _importer_for($self, $inbox);
+ my $mime = _path_to_mime($path) or return;
+ $mime->header_set($_) foreach @PublicInbox::MDA::BAD_HEADERS;
+ my $wm = $inbox->{-watchheader};
+ if ($wm) {
+ my $v = $mime->header_obj->header_raw($wm->[0]);
+ return unless ($v && $v =~ $wm->[1]);
+ }
+ if (my $scrub = _scrubber_for($inbox)) {
+ my $ret = $scrub->scrub($mime) or return;
+ $ret == 100 and return;
+ $mime = $ret;
+ }
+
+ _force_mid($mime);
+ $im->add($mime, $self->{spamcheck});
+}
+
+sub quit { trigger_scan($_[0], 'quit') }
+
+sub watch {
+ my ($self) = @_;
+ my $scan = File::Temp->newdir("public-inbox-watch.$$.scan.XXXXXX",
+ TMPDIR => 1);
+ my $scandir = $self->{scandir} = $scan->dirname;
+ my $re = qr!\A$scandir/!;
+ my $cb = sub { _try_fsn_paths($self, $re, \@_) };
+
+ # lazy load here, we may support watching via IMAP IDLE
+ # in the future...
+ require Filesys::Notify::Simple;
+ my $fsn = Filesys::Notify::Simple->new([@{$self->{mdir}}, $scandir]);
+ $fsn->wait($cb) until $self->{quit};
+}
+
+sub trigger_scan {
+ my ($self, $base) = @_;
+ my $dir = $self->{scandir} or die "not watch-ing, yet\n";
+ open my $fh, '>', "$dir/$base" or die "open $dir/$base failed: $!\n";
+ close $fh or die "close $dir/$base failed: $!\n";
+}
+
+sub scan {
+ my ($self, $path) = @_;
+ if ($path =~ /quit\z/) {
+ %{$self->{opendirs}} = ();
+ _done_for_now($self);
+ $self->{quit} = 1;
+ return;
+ }
+ # else: $path =~ /(cont|full)\z/
+ return if $self->{quit};
+ my $max = 10;
+ my $opendirs = $self->{opendirs};
+ my @dirnames = keys %$opendirs;
+ foreach my $dir (@dirnames) {
+ my $dh = delete $opendirs->{$dir};
+ my $n = $max;
+ while (my $fn = readdir($dh)) {
+ _try_path($self, "$dir/$fn");
+ last if --$n < 0;
+ }
+ $opendirs->{$dir} = $dh if $n < 0;
+ }
+ if ($path =~ /full\z/) {
+ foreach my $dir (@{$self->{mdir}}) {
+ next if $opendirs->{$dir}; # already in progress
+ my $ok = opendir(my $dh, $dir);
+ unless ($ok) {
+ warn "failed to open $dir: $!\n";
+ next;
+ }
+ my $n = $max;
+ while (my $fn = readdir($dh)) {
+ _try_path($self, "$dir/$fn");
+ last if --$n < 0;
+ }
+ $opendirs->{$dir} = $dh if $n < 0;
+ }
+ }
+ _done_for_now($self);
+ # do we have more work to do?
+ trigger_scan($self, 'cont') if keys %$opendirs;
+}
+
+sub _path_to_mime {
+ my ($path) = @_;