#!/usr/bin/perl -w
######################################################################
# chknews.pl
######################################################################
# Perl Power! - Michael Schilli 1998
######################################################################

######################################################################
# chknews.pl - search newsgroups for new titles
######################################################################

#*********************************************************************
# Extended Newsrc class
#*********************************************************************
package MyNewsrc;

use News::Newsrc;                        # manage Newsrc file
use Set::IntSpan;                        # additional range handler

@ISA = qw/News::Newsrc/;                 # base class

######################################################################
sub get_unmarked_articles {              # fetch list of unmarked
    my ($self, $ng, $from, $to) = @_;    # articles; format: as Newsrc
######################################################################

    my $intervals = Set::IntSpan->new(   # create IntSpan object
        join(',', $self->unmarked_articles($ng, $from, $to)));
    $intervals->run_list();              # return string
}

######################################################################
sub clear_old_ranges {                   # limit ranges
    my ($self, $ng, $article_limit) = @_;
######################################################################
                                         # find last article
    my $articles = $self->get_articles($ng);
    my ($last_article) = ($articles =~ /(\d+)$/);
                                         # overwrite ranges before
    if($last_article > $article_limit) { # the last N articles
        $self->mark_range($ng, 1, $last_article-$article_limit);
    }
}

#*********************************************************************
# Main program
#*********************************************************************
package main;

my $newsrcfile    = "$ENV{HOME}/data/news.dat"; # "memory"
my $newsserver    = "$ENV{NNTPSERVER}";         # news server
my $article_limit = 10000;               # length of monitored zone
                                         # at end of number range
$| = 1;                                  # do not buffer output

use Net::NNTP;                           # NNTP user agent
use Getopt::Std;                         # command line parameter

$opt_r = $opt_h = $opt_v = $opt_d = undef; # options -r, -h, -d, -v
getopts("rhvd");

my($ng, $pattern) = @ARGV;               # command line parameter
usage("Argument Error") unless defined $pattern;
usage() if defined $opt_h;               # -h set?

$newsrc = MyNewsrc->new();               # create Newsrc object

if(-f $newsrcfile) {                     # read Newsrc file
    $newsrc->load($newsrcfile) || die "Cannot load $newsrcfile";
}

print "Scanning $ng for $pattern\n" if $opt_v;

                                         # create newsagent
print "Connecting to $newsserver\n" if $opt_d;
($newsagent = Net::NNTP->new($newsserver)) ||
    die "Cannot connect to $newsserver";
                                         # fetch numbers of available
                                         # articles from the server
(my ($total, $first, $last) = $newsagent->group($ng)) ||
    usage("Unknown newsgroup $ng");
                                         # define ranges of
                                         # unread articles
print "$total ($first-$last) articles in $ng\n" if $opt_d;
$unmarked = $newsrc->get_unmarked_articles($ng, $first, $last);
                                         # re-check option: all
$unmarked = "$first-$last" if defined $opt_r;

foreach (split(/,/, $unmarked)) {        # for each range:
    my ($from, $to) = split(/-/, $_);
                                         # amend interval
    $to = $from +1 if(!defined $to || $to == $from);

    print "XHDR $from $to\n" if $opt_d;  # fetch subject lines
    (my $subjects = $newsagent->xhdr('Subject', [$from, $to])) ||
        die "xhdr failed";

    while (($msgno, $subject) = each %$subjects) {
        $newsrc->mark($ng, $msgno);      # mark as 'read'
                                         # output if match
        if($subject =~ /$pattern/i) {
            print "    " if($opt_d || $opt_v);
            print "$ng: $subject\n";
        }
    }
}

$newsrc->clear_old_ranges($ng, $article_limit);  # limit ranges

$newsrc->save_as($newsrcfile);

$newsagent->quit();                      # release newsagent

######################################################################
sub usage {                              # display usage
######################################################################
    (my $program = $0) =~ s,.*/,,g;      # determine base name
    print "$program: @_\n";
    print "usage: $program [-rvhd] newsgroup subject\n";
    print "           -r: re-check all Articles\n";
    print "           -v: verbose on\n";
    print "           -h: print out this message\n";
    print "           -d: debug on\n";
    exit 0;
}

