package Parp::Filter::User;

use strict;
use warnings;

use Parp::Config qw(config);

use base 'Parp::Filter';

##############################################################################
##
## User-defined filtering routines.
##
## They are invoked as methods, so the first parameter is always the
## Parp::Mail object, which contains all the information you would
## normally need to perform standard tests on it.  For example, if $m
## is the object, $m->subject is the subject line, and
## $m->matches('ftc', $re) is a method which returns a list of any of the
## e-mail addresses found in the From, To, Cc (or X-Mailing-List)
## headers which the regexp $re matches.  See the Parp::Mail manual
## page for more information.
##
## Once you have performed tests and determined what action you want
## to take for a given e-mail, there are some useful methods available
## for taking the action, including:
##
##   $m->accept_mail($reason, @details);      # tag mail as accepted
##   $m->reject_mail($reason, @details);      # tag mail as rejected
##   $m->reject_junk_mail($reason, @details); # tag mail as rejected junk
##   $m->deliver_to('foo');                   # deliver to folder `foo'
##   $m->deliver_to_inbox('bar');             # deliver to inbox `bar'
##   $m->pipe_forward('command arg1 arg2');   # pipe mail | command arg1 arg2
##
## Return values are also important; see the filter() and categorize()
## routines in Parp::Filter to understand how they affect filtering.
##


#
# is_special_case()
#
# Handles special cases before virtually any other filtering
# occurs.  Should return 'IS_SPECIAL' in cases where you want
# to take all appropriate action yourself (e.g. delivery/forwarding).
# Other return values have the normal meaning; for more details
# see Parp::Filter::categorize().
#

sub is_special_case {
  my $self = shift;
  my ($m) = @_;

  if ($m->to =~ /\b(adam-.*test.*\@thelonious\.new\.ox\.ac\.uk)\b/i) {
    $m->accept_mail('test mail', $1);
    $m->deliver_to_inbox('test');
    return 'IS_SPECIAL';
  }

  if ($m->to =~ /\b(adam-.*auto.*\@thelonious\.new\.ox\.ac\.uk)\b/i) {
    $m->accept_mail('auto-reply', $1);
    $m->deliver_to_inbox('autoreply');
    return 'IS_SPECIAL';
  }

  if ($m->to =~ /\b(adam-cuteftp\@thelonious\.new\.ox\.ac\.uk)\b/i) {
    $m->ditch_mail('obsolete address', $1);
    return 'IS_SPECIAL';
  }

  if ($m->to =~ /\b(adam-.*\@thelonious\.new\.ox\.ac\.uk|.*\@adamspiers.org)\b/i) {
    $m->deliver_to_inbox('alt_addresses');
  }

  if ($m->matches('ftc', qr/buzzaway\.com\b/i)) {
    $m->accept_mail('buzz spam');
    $m->deliver_to_main;
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/dpie\.com\b/i)) {
    $m->ditch_mail('Diamond Point spam');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/handspring\.p0\.com\b/i)) {
    $m->accept_mail('handspring news');
    $m->deliver_to_inbox('handspring');
    return 'IS_SPECIAL';
  }

  if ($m->to =~ /solo string mailing list/i) {
    $m->accept_mail('solo string');
    $m->deliver_to_inbox('solo_string');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/\bowner.*topica\.com\b/i)) {
    $m->accept_mail('topica');
    $m->deliver_to_inbox('topica');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/\blinux-thinkpad\@topica\.com\b/i)) {
    $m->ditch_mail('no time to read');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/\bwebring\.org\b/i)) {
    $m->accept_mail('webring.org');
    $m->deliver_to_inbox('webring');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/\bexcellnews.*excell\.to\b/i)) {
    $m->accept_mail('eXcell news');
    $m->deliver_to_inbox('eXcell.to');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/\bquios.*\.net\b/i)) {
    $m->accept_mail('quios');
    $m->deliver_to_inbox('quios');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/\bgeniemail\.co\.uk\b/i)) {
    $m->accept_mail('BT Cellnet/Genie');
    $m->deliver_to_inbox('genie');
    return 'IS_SPECIAL';
  }

  if ($m->matches(
    'ftc',
    qr/\b(
          gc-orders.*       |
          cards-bounces.*   |
          .*news.*
         )\@.*amazon\.(com|co\.uk)\b/ix))
  {
    $m->accept_mail('amazon.com');
    $m->deliver_to_inbox('amazon');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/(admin|noreply)\@sourceforge\.net\b/i)) {
    $m->accept_mail('sourceforge.net');
    $m->deliver_to_inbox('sourceforge');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/\bfreshmeat-news\@.*freshmeat\.net\b/)) {
    $m->deliver_to_inbox('freshmeat');
#     $m->pipe_forward('fmscore >>' . config->inbox('freshmeat'));
    return 'IS_SPECIAL';
  }

  if ($m->from =~ /(nobody|jobs|subscriber\.email)\@.*jobserve\.com/i) {
    $m->pipe_forward("$ENV{HOME}/bin/jobserve");
    return 'IS_SPECIAL';
  }
  
  if ($m->from =~ /(jobs-filtered)\@jobserve\.com/i) {
    $m->accept_mail('jobserve jobs (filtered)');
    $m->deliver_to_inbox('jobs-filtered');
    return 'IS_SPECIAL';
  }
  
  if ($m->subject =~ /headlines/i and
      $m->matches('ftc', qr/slashdot\.org/)) {
    $m->accept_mail('slashdot daily news');
    $m->deliver_to_inbox('slashdot');
    return 'IS_SPECIAL';
  }

  if (($m->matches('froms', qr/\@.*\.london\.guideguide\.com/))[0]) {
    $m->accept_mail('guideguide intranet');
    return 'IS_SPECIAL';
  }

  if (  
        ($m->matches('froms', config->me))[0]           &&
      ! ($m->matches('froms', qr/auto|test/))[0] &&
        $m->mailer   !~ /[Mm]utt|Eudora .* for PalmOS/     &&
        $m->reply_to !~ /adam\@spiers\.net/                &&
        $m->to       !~ /cvs-notify|topica\.com|gimp-perl/ &&
        $m->sender   !~ /nobody\@.*guideguide\.com/ 
     )
  {
    $m->reject_junk_mail('not /really/ from me');
    return 'IS_SPAM';
  }

  if ($m->matches('ftc', qr/activesw\.com/i) &&
      $m->subject =~ /qstat/i) {
    $m->accept_mail('qstat');
    $m->deliver_to_inbox('qstat');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/ntknow\@lists\.ntk\.net/i)) {
    $m->accept_mail('NTK');
    $m->deliver_to_inbox('NTK');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/press.*release.*moneyworld\.co\.uk/i)) {
    $m->ditch_mail('MoneyWorld press release');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/wstearns\@pobox\.com/i)) {
    $m->accept_mail('buildkernel');
    $m->deliver_to_main;
    return 'IS_SPECIAL';
  }

  if ($m->to =~ /\bIBM\b.*\bSupport Customer/) {
    $m->accept_mail('IBM support');
    $m->deliver_to_inbox('ibm-support');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/announcements\@vmware\.com|vmwarenews/i)) {
    $m->accept_mail('vmware crap');
    $m->deliver_to_inbox('vmware');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/freerealtime\.com/i)) {
    $m->ditch_mail('freerealtime crap');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/brainbench\.com/i)) {
    $m->accept_mail('brainbench crap');
    $m->deliver_to_inbox('brainbench');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/setiathome/i)) {
    $m->accept_mail('setiathome crap');
    $m->deliver_to_inbox('setiathome');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/raxco/i)) {
    $m->ditch_mail('Raxco crap');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/reminder.*myfamily|myfamily.*reminder/i)) {
    $m->ditch_mail('MyFamily reminder');
    return 'IS_SPECIAL';
  }

  if ($m->matches('ftc', qr/notifyservice.*myfamily/i)) {
    $m->ditch_mail('MyFamily notification');
    return 'IS_SPECIAL';
  }

  if ($m->from =~ /Member.Update/i &&
      $m->from =~ /MyFamily/i) {
    $m->ditch_mail('MyFamily member update');
    return 'IS_SPECIAL';
  }

  if ($m->from =~ /news\@mail\.com/) {
    $m->ditch_mail('mail.com crap');
    return 'IS_SPECIAL';
  }

  if ($m->from =~ /announcement.*\@mail\.com/i) {
    $m->accept_mail('mail.com announcement');
    $m->deliver_to_main;
    return 'IS_SPECIAL';
  }

  if ($m->from =~ /apeleg\@interjazz\.com/ &&
      $m->subject =~ /InterJazz mailing list/) {
    $m->accept_mail('interjazz');
    $m->deliver_to_inbox('interjazz');
    return 'IS_SPECIAL';
  }
}


## Define any mailing lists you're on here.
##
## The key on the left is the name of the inbox, and the regular
## expression on the right is what either the From, To, or Cc header
## should match for the mail to be identified as belonging to the
## list.  If a `subject_RE' key is given in the hash on the right, any
## mail whose subject matches the corresponding regular expression
## will also be associated with the list.
##
## For convenient typing, the %s will get replaced by the key on the
## left.

sub lists {
  (
   ## hardware

   'linux-thinkpad'   => {
                           RE => '%s.*topica\.com',
                           subject_RE => qr/\[LTP\]/,
                         },
   'linux-laptop'     => { RE => '%s.*vger\.rutgers\.edu' },
   'lhd'              => { RE => 'lhd.*datapower\.com' },


   ## software

   'alsa-announce'    => { RE => '%s.*alsa-project\.org' },
   'alsa-devel'       => { RE => '%s.*alsa-project\.org' },
   'alsa-user'        => { RE => '%s.*alsa-project\.org' },
   'apmd-list'        => { RE => '%s.*worldvisions\.ca' },
   'arch-announce'    => { RE => '%s.*regexps\.com' },
   'arch-users'       => { RE => '%s.*regexps\.com' },
   'arch-dev'         => { RE => '%s.*regexps\.com' },
   'bug-arch'         => { RE => '%s.*regexps\.com' },
   'bashprompt'       => { RE => 'bash.*current\.nu' },
   'buggies'          => { RE => '%s@landfill\.tequilarista\.org' },
   'fetchmail'        => { RE => '%s-friends.*@lists\.ccil\.org' },
   'galeon-user'      => { RE => '%s.*sourceforge\.net' },
   'galeon-devel'     => { RE => '%s.*sourceforge\.net' },
   'gconf-list'       => { RE => '%s.*gnome\.org' },
   'gimp-perl'        => { RE => 'gimp-perl.*lists\.netcentral\.net' },
   'gnokii'           => { RE => '%s@net.lut.ac.uk' },
   'gnome-pilot'      => { RE => '%s.*@gnome\.org' },
   'gphoto-devel'     => { RE => '%s.*@gphoto.(net|org)' },
   'gphoto'           => { RE => '%s@gphoto.(net|org)' },
   'gqview-users'     => { RE => '%s.*sourceforge\.net' },
   'infobot'          => { RE => '%s.*(cs\.cmu\.edu|metronomicon\.com|' .
                                      'infobot\.org)' },
   'linux-diald'      => { RE => '%s.*vger\.rutgers\.edu' },
   'linux-smp'        => { RE => '%s.*redhat\.com' },
   'mod-perl'         => { RE => 'modperl@apache.org' },
   'mozilla-announce' => { RE => '%s.*mozilla\.org' },
   'mozilla-bugzilla' => { RE => 'bugzilla-daemon@mozilla\.org' },
   'mutt-announce'    => { RE => '%s@mutt\.org' },
   'perlunit-devel'   => { RE => '%s.*sourceforge\.net' },
   'perlunit-users'   => { RE => '%s.*sourceforge\.net' },
   'perlunit-commits' => { RE => '%s.*sourceforge\.net' },
   'pjbox'            => { RE => '%s.*@phobos\.(fs\.tum|fachschaften\.tu-muenchen)\.de' },
   'plucker-dev'      => { RE => 'plucker.*@.*rubberchicken\.org' },
   'redhat-contrib'   => { RE => '(contrib|redhat)-list.*redhat\.com' },
   'redhat-bugzilla'  => { RE => 'bugzilla@bugzilla\.redhat\.com' },
   'rep-gtk'          => { RE => '%s.*sourceforge\.net' },
   'req'              => { RE => 'req.*ccs\.neu\.edu' },
   'reqng'            => { RE => 'reqng\.ml\.org|scuttlebutt\.explore\.com|' .
                                 'reqng.*sycore\.net' },
   'sawfish'          => { RE => 'saw(mill|fish).*(aarg\.net|eazel\.com)' },
   'sitescooper'      => { RE => '%s.*lists\.sourceforge\.net' },
   'vortex-bug'       => { RE => '%s' },
   'zsh-announce'     => { RE => 'zsh-announce.*(sunsite\.(auc\.)?dk|math\.gatech\.edu)' },
   'zsh-users'        => { RE => 'zsh-users.*(sunsite\.(auc\.)?dk|math\.gatech\.edu)' },
   'zsh-workers'      => { RE => 'zsh-workers.*(sunsite\.(auc\.)?dk|math\.gatech\.edu)' },


   ## chatter

   'fwp'              => { RE => '%s.*perl\.org' },
   'perl-golf'        => { RE => 'golf.*perl\.org' },
   'oxford-pm'        => { RE => '%s-list.*pm\.org' },
   'london-pm'        => { RE => 'london-list.*pm\.org' },
   'unix-admin'       => { RE => '%s.*comlab\.ox(ford)?\.ac\.uk' },
   'void'             => { 
                           RE => '(void|slobber).*(slab\.org|(guideguide|mediaconsult)\.com)',
                           subject_RE => '^(Re: )?\(void\) ',
                         },


   ## security

   'bugtraq'          => { RE => '%s.*(netspace\.org|securityfocus\.com)' },
   'linux-alert'      => { RE => '%s.*redhat\.com' },
   'linux-security'   => { RE => '%s.*redhat\.com' },


   ## miscellaneous

   'cron'             => { subject_RE => 'Cron <\w+@thelonious>' },
   'interjazz'        => { RE => 'interjazz@interjazz.com' },
  );
}


#
# is_list_mail()
#
# Should true if an e-mail is from a mailing list or similar,
# and hence should be placed in an auxiliary inbox.  The routine
# is responsible for delivery, however.
#

sub is_list_mail {
  my $self = shift;
  my ($m) = @_;

  my $rv = deliver_gg_stuff($m);
  return 1 if $rv eq 'NEXT_MAIL';   # ugh

  my %lists = $self->lists;
  foreach my $list (keys %lists) {
    if (exists $lists{$list}{backup}) {
      $m->{backup} = $lists{$list}{backup};
    }

    my $dest = $lists{$list}{folder} || config->inbox($list);

    if (exists $lists{$list}{RE}) {
      my $RE = $lists{$list}{RE};
      $RE =~ s/%s/$list/g;
      if ($m->matches('ftc', qr/$RE/i)) {
        $m->{list_mail} = "belonged to list `$list' via ftc";
        $m->{list_mail_dest} = $dest;
        last;
      }
    }

    if (exists $lists{$list}{subject_RE}) {
      my $RE = $lists{$list}{subject_RE};
      if ($m->subject =~ /$RE/i) {
        $m->{list_mail} = "belonged to list `$list' via subject";
        $m->{list_mail_dest} = $dest;
        last;
      }
    }
  }

  if ($m->{list_mail}) {
    if ($m->subject =~ /un.?subscribe\s*$/i &&
        ! ($m->matches('froms', config->me))[0]) {
      $m->reject_mail("someone doesn't know how to unsubscribe");
      return 1;
    }
    else {
      $m->accept_mail($m->{list_mail});
      $m->deliver_to($m->{list_mail_dest});
      return 1;
    }
  }

  if ($m->matches('ftc', qr/hyper\.stanford\.edu/)) {
    my $forum = $m->header->get('X-HN-Forum');
    chomp $forum;

    if ($forum eq 'PCMCIA driver beta testing') {
      $m->accept_mail('PCMCIA beta testing forum');
      $m->deliver_to_inbox('pcmcia-beta');
      return 1;
    }
    elsif ($forum eq 'Power Management and PCMCIA') {
      $m->accept_mail('APM/PCMCIA forum');
      $m->deliver_to_inbox('pcmcia-apm');
      return 1;
    }
    else {
      $m->accept_mail('unknown HyperNews forum');
      $m->deliver_to_main;
      return 1;
    }
  }

  if ($m->from =~ /postmaster\@pdi\.com/) {
    $m->ditch_mail('cretins at pdi.com');
    return 1;
  }

  return 0;
}

{
  my @gg_filters = qw/ggdev gg-dev ggnews gg-uk gg-all
                      gg-bugzilla bugzilla-daemon codereview/;

  sub deliver_gg_stuff {
    my $m = shift;
    
    my $gg = qr/(guideguide|mediaconsult)\.com/;

    return 0 unless $m->matches('ftc', $gg);

    if ($m->subject =~ /Faq-O-Matic Moderator Mail/) {
      if ($m->{body_scalar} =~ /^Who:\s*aspiers\@guideguide\.com\b/m) {
        $m->ditch_mail('my Faq-O-Matic changes');
      }
      else {
        $m->accept_mail("ggdev faqomatic");
        $m->deliver_to_inbox('gg-faqomatic');
      }
      return 'NEXT_MAIL';
    }

    foreach my $filter (@gg_filters) {
      my $RE = qr/$filter\@.*$gg/;
      $filter = 'gg-bugzilla' if $filter eq 'bugzilla-daemon';
      $filter = 'ggdev'       if $filter eq 'gg-dev';
      if ($m->matches('ftc', $RE)) {
        $m->accept_mail("belonged to list `$filter'");
        $m->deliver_to("computer-work/$filter");
        $m->{backup} = 0;
        $m->deliver_to_inbox($filter);
        return 'NEXT_MAIL';
      }
    }

    # guideguide cvs commits
    if ($m->matches('ftc', qr/cvs-notify/i)) {
      # keep a complete archive
      $m->accept_mail("gg-cvs-notify");
      $m->deliver_to("computer-work/gg-cvs-notify.%Y-%qq");

      if ($m->subject =~ m!moo/(career|images)! ||
          $m->subject =~ m!moo/gg/Modules/Foto! ||
          $m->subject =~ m!moo/gg/files/xml! ||
          $m->subject =~ m!moo/gg/messages! ||
#          $m->subject =~ m!architekt|career|friseur|gourmet|krankenhaus|
#                             moebel!ix ||
          $m->subject =~ m!<sybase>!)
      {
        $m->ditch_mail('uninteresting gg cvs commits');
        return 'NEXT_MAIL';
      }
      if (($m->matches('froms', config->me))[0]) {
        $m->ditch_mail('my gg cvs commits');
        return 'NEXT_MAIL';
      }
        
      $m->deliver_to_inbox('gg-cvs-notify');
      return 'NEXT_MAIL';
    }

    if ($m->subject =~ /bugzilla buglist needs attention/i) {
      $m->{backup} = 0;
      $m->accept_mail("gg bugzilla reminders");
      $m->deliver_to_inbox('gg-bugzilla-reminders');
      return 'NEXT_MAIL';
    }
  }
}


sub is_from_daemon {
  my $self = shift;
  my $m = shift;
  
  # known daemons
  if (my @m = $m->matches('froms',
                    qr/(
                        MAILER-DAEMON\@
                        (?:
                         (?:thelonious\.new|oxmail)\.ox\.ac\.uk |
                         tr909\.mediaconsult\.com               |
                         bt\.net 
                        ) |
                        postmaster\@.*(
                          \.genie\.syncordia\.net
                        )
                       )
                      /ix)) {
    $m->accept_mail('from daemon', "`$m[1]'");
    return 1;
  }

  if (my @m = $m->matches('froms',
                          qr/(MAILER-DAEMON\@www\.genie\.co\.uk)/)) {
    $m->accept_mail('from SMS gateway', "`$m[1]'");
    $m->{not_to_mobile} = 1;
    return 1;
  }

  return $self->SUPER::is_from_daemon($m);
}


1;
