1     #!/usr/bin/perl -w
2     use strict;
3     $|++;
4     
5     use XML::RSS;
6     use LWP::Simple qw(mirror is_success);
7     
8     ## BEGIN config
9     
10    my $MAIL_TO = 'merlyn@XXstonehenge.comXX';
11    my $MAIL_FROM = 'merlyn@XXstonehenge.comXX';
12    my $MAIL_SUBJECT = "All the news that fits, we print!";
13    my $MAILHOST = "localhost";
14    my $DIR = "/home/merlyn/.rssnews";
15    my @NEWS =
16      (
17       ## Perl News
18       "http://www.news.perl.org/perl-news-short.rdf" => "perl-news-short.rdf",
19       ## Slashdot
20       "http://slashdot.org/slashdot.rdf" => "slashdot.rdf",
21       ## CNET computing news
22       "http://alchemy.openjava.org/rss/news-com.rdf" => "cnet-computing-news.rdf",
23       ## Freshmeat
24       "http://freshmeat.net/backend/fm.rdf" => "freshmeat.rdf",
25       ## Linux Today
26       "http://linuxtoday.com/backend/my-netscape.rdf" => "linuxtoday.rdf",
27       ## Linux Planet
28       "http://www.linuxplanet.com/rss" => "linuxplanet.rdf",
29       ## Mac Central
30       "http://www.maccentral.com/mnn.cgi" => "maccentral.rdf",
31       ## Macweek.com
32       "http://macweek.zdnet.com/macweek.xml" => "macweek.rdf",
33       ## Moreover Computer Security
34       "http://www.moreover.com/cgi-local/page?index_computersecurity+rss"
35       => "moreover-computer-security.rdf",
36      );
37    
38    ## END config
39    
40    chdir $DIR or die "Cannot chdir $DIR: $!";
41    my @output;
42    
43    while (@NEWS >= 2) {
44      my ($url, $localname) = splice @NEWS, 0, 2;
45      dbmopen my %SAW, $localname, 0644 or warn "Cannot open %SAW for $localname: $!";
46    
47      next unless is_success(mirror($url, $localname));
48    
49      my $rss = XML::RSS->new or die "can't create XML::RSS?";
50      eval {$rss->parsefile($localname)} and not $@
51        or (warn "cannot parse $localname: $@"), next;
52    
53      my %seen;
54      my @item_output;
55      for my $item (@{$rss->{items}}) {
56        my ($title, $link, $description) = @$item{qw(title link description)};
57        $description = "" unless defined $description;
58        my $tag = "$title\0$link";
59        $seen{$tag} = time;
60        next if $SAW{$tag};
61        push @item_output, "$tag\0$description";
62      }
63      %SAW = %seen;
64      if (@item_output) {
65        push @output, "== ".($rss->channel("title"))." ==\n", map {
66          my ($title, $link, $description) = split /\0/;
67          "$title\n",
68          "  <URL:$link>\n",
69          (length $description ? "  $description\n" : ());
70        } @item_output;
71      }
72    }
73    
74    if (@output) {
75      require Net::SMTP;
76      my $m = Net::SMTP->new($MAILHOST)
77        or die "Cannot connect to mail $MAILHOST: $!";
78      $m->mail($MAIL_FROM)
79        or die "Cannot set mail from: $!";
80      $m->to($MAIL_TO)
81        or die "Cannot set mail to: $!";
82      $m->data("From: $MAIL_FROM\n",
83               "To: $MAIL_TO\n",
84               "Subject: $MAIL_SUBJECT\n",
85               "\n",
86               @output,
87               )
88        or die "Cannot send contents: $!";
89      $m->quit
90        or die "Cannot close mail: $!";
91    }