#!/usr/bin/perl # # Author: Petter Reinholdtsen # Date: 2005-12-28 # License: GNU Public License v2 or later # # Make it easier to report gmane messages as spam. List all new # messages in a given group, and let the user mark a message as spam # with a single keypress. # # Configuration is in ~/.gmanespam, with content like this: # server news.gmane.org # group gmane.linux.debian.devel.initscripts-ng # group gmane.linux.debian.devel.java # # New version of this script is available from # use warnings; use strict; use Net::NNTP; use LWP::UserAgent; my $server = "news.gmane.org"; my $spamurl = "http://spam.gmane.org/{group}:{msgnum}"; # List of groups to process my @groups; # Msgnum of the last visited article in the key group. my %grouplast; my @configfiles = ("/etc/gmanespam", $ENV{HOME}."/.gmanespam"); my $statusfile = $ENV{HOME}."/.gmanespamrc"; loadconfig(); my $nntp = Net::NNTP->new($server); unless ($nntp) { print "error: Unable to connect to NNTP server '$server'.\n"; exit 1; } my $ua = LWP::UserAgent->new; loadstatus($statusfile); for my $group (@groups) { process_gmane_group($group); } savestatus($statusfile); $nntp->quit; sub loadconfig { for my $filename (@configfiles) { open (CFG, "<$filename") || next; while () { chomp; s/\#.*//g; s/\s*$//g; next if (/^$/); $server = $1 if (m/^server (.+)$/); $spamurl = $1 if (m/^spamurl (.+)$/); push(@groups, $1) if (m/^group (.+)$/); } close(CFG); } } sub loadstatus { my $statusfile = shift; open (STATUS, "<$statusfile"); while () { chomp; my ($groupname, $lastnum) = m/^(\S+): 1-(\d+)$/; $grouplast{$groupname} = $lastnum; } close(STATUS); } sub savestatus { my $statusfile = shift; open(STATUS, ">$statusfile") || die "Unable to write to $statusfile"; for my $groupname (sort keys %grouplast) { print STATUS "$groupname: 1-".$grouplast{$groupname}."\n"; } close(STATUS); } sub process_gmane_group { my $group = shift; my ($msgcount, $msgfirst, $msglast, $groupname) = $nntp->group($group); my $curmsgnum = $grouplast{$groupname}; my @spammsgs; print "\n$groupname: $msgfirst -> $msglast ($msgcount)\n"; my $aktive = 1; while ($aktive && ++$curmsgnum <= $msglast) { print "\n[$curmsgnum/$msglast] ============ $groupname ===========\n"; my $headersref = $nntp->head($curmsgnum); unless ($headersref) { print "**** Message does not exist. Skipping.\n"; next; } my ($spam, $subject, $from) = process_header($headersref); print "From: $from\n"; print "Subject: $subject\n"; if ($spam) { print "**** Message already flagged as spam. Ignoring.\n"; next; } print "Non-spam/Spam/sKip/view Body/view Full/jump #/Help/Quit [N] ? "; my $input = <>; chomp $input; $input = "\L$input"; if ("" eq $input || "n" eq $input) { # Not spam, ignore } elsif ("s" eq $input) { # Report as spam push(@spammsgs, $curmsgnum); } elsif ("q" eq $input) { print "Exiting\n"; savestatus($statusfile); exit 0; } elsif ($input =~ m/^(\d+)$/) { $curmsgnum = $1 - 1; $curmsgnum = $msglast if $curmsgnum > $msglast; print "Jumping to message number $1\n"; next; } elsif ("k" eq $input) { # Skip this group and move to the next group $aktive = 0; } elsif ("f" eq $input) { # View message header and body my $articleref = $nntp->article($curmsgnum); list_lines($articleref); $curmsgnum--; } elsif ("b" eq $input) { # View message body my $bodyref = $nntp->body($curmsgnum); list_lines($bodyref); $curmsgnum--; } elsif ("h" eq $input) { # print help } else { print STDERR "error: Unhandled choice '$input'\n"; } } if (@spammsgs) { print "Submit changes? [yes] "; my $input = <>; chomp $input; $input = "\L$input"; if ("" eq $input || "yes" eq $input) { for my $msgnum (@spammsgs) { report_spam($groupname, $msgnum); } } } $grouplast{$groupname} = --$curmsgnum; print "Storing $curmsgnum as last read message in $groupname\n"; } sub list_lines { my $arrayref = shift; for (@{$arrayref}) { print " ", $_; } } sub process_header { my $headerref = shift; my $subject; my $from; my $spam; for (@{$headerref}) { $from = $1 if m/^From: (.*)$/i; $subject = $1 if m/^Subject: (.*)$/i; $spam = 1 if m/Xref: .*gmane.spam.detected.*$/; } return ($spam, $subject, $from) } sub report_spam { my ($groupname, $msgnum) = @_; my $url = $spamurl; $url =~ s/{group}/$groupname/g; $url =~ s/{msgnum}/$msgnum/g; my $response = $ua->get($url); if ($response->is_success) { print "Reported $groupname:$msgnum as spam.\n"; } else { die $response->status_line; } }