]> pere.pagekite.me Git - homepage.git/blob - linux/gmanespam
Switched blog to hungry.com for now. Updated all links.
[homepage.git] / linux / gmanespam
1 #!/usr/bin/perl
2 #
3 # Author: Petter Reinholdtsen
4 # Date: 2005-12-28
5 # License: GNU Public License v2 or later
6 #
7 # Make it easier to report gmane messages as spam. List all new
8 # messages in a given group, and let the user mark a message as spam
9 # with a single keypress.
10 #
11 # Configuration is in ~/.gmanespam, with content like this:
12 # server news.gmane.org
13 # group gmane.linux.debian.devel.initscripts-ng
14 # group gmane.linux.debian.devel.java
15 #
16 # New version of this script is available from
17 # <URL:http://www.student.uit.no/~pere/linux/>
18
19 use warnings;
20 use strict;
21
22 use Net::NNTP;
23 use LWP::UserAgent;
24
25 my $server = "news.gmane.org";
26 my $spamurl = "http://spam.gmane.org/{group}:{msgnum}";
27
28 # List of groups to process
29 my @groups;
30
31 # Msgnum of the last visited article in the key group.
32 my %grouplast;
33
34 my @configfiles = ("/etc/gmanespam", $ENV{HOME}."/.gmanespam");
35 my $statusfile = $ENV{HOME}."/.gmanespamrc";
36
37 loadconfig();
38
39 my $nntp = Net::NNTP->new($server);
40
41 unless ($nntp) {
42 print "error: Unable to connect to NNTP server '$server'.\n";
43 exit 1;
44 }
45
46 my $ua = LWP::UserAgent->new;
47
48 loadstatus($statusfile);
49
50 for my $group (@groups) {
51 process_gmane_group($group);
52 }
53
54 savestatus($statusfile);
55
56 $nntp->quit;
57
58 sub loadconfig {
59 for my $filename (@configfiles) {
60 open (CFG, "<$filename") || next;
61 while (<CFG>) {
62 chomp;
63 s/\#.*//g;
64 s/\s*$//g;
65 next if (/^$/);
66 $server = $1 if (m/^server (.+)$/);
67 $spamurl = $1 if (m/^spamurl (.+)$/);
68 push(@groups, $1) if (m/^group (.+)$/);
69 }
70 close(CFG);
71 }
72 }
73
74 sub loadstatus {
75 my $statusfile = shift;
76 open (STATUS, "<$statusfile");
77 while (<STATUS>) {
78 chomp;
79 my ($groupname, $lastnum) = m/^(\S+): 1-(\d+)$/;
80 $grouplast{$groupname} = $lastnum;
81 }
82 close(STATUS);
83 }
84
85 sub savestatus {
86 my $statusfile = shift;
87 open(STATUS, ">$statusfile") || die "Unable to write to $statusfile";
88 for my $groupname (sort keys %grouplast) {
89 print STATUS "$groupname: 1-".$grouplast{$groupname}."\n";
90 }
91 close(STATUS);
92 }
93
94 sub process_gmane_group {
95 my $group = shift;
96 my ($msgcount, $msgfirst, $msglast, $groupname) = $nntp->group($group);
97 my $curmsgnum = $grouplast{$groupname};
98
99 my @spammsgs;
100
101 print "\n$groupname: $msgfirst -> $msglast ($msgcount)\n";
102 my $aktive = 1;
103 while ($aktive && ++$curmsgnum <= $msglast) {
104 print "\n[$curmsgnum/$msglast] ============ $groupname ===========\n";
105
106 my $headersref = $nntp->head($curmsgnum);
107 unless ($headersref) {
108 print "**** Message does not exist. Skipping.\n";
109 next;
110 }
111 my ($spam, $subject, $from) = process_header($headersref);
112
113 print "From: $from\n";
114 print "Subject: $subject\n";
115 if ($spam) {
116 print "**** Message already flagged as spam. Ignoring.\n";
117 next;
118 }
119 print "Non-spam/Spam/sKip/view Body/view Full/jump #/Help/Quit [N] ? ";
120 my $input = <>;
121 chomp $input;
122 $input = "\L$input";
123 if ("" eq $input || "n" eq $input) {
124 # Not spam, ignore
125 } elsif ("s" eq $input) {
126 # Report as spam
127 push(@spammsgs, $curmsgnum);
128 } elsif ("q" eq $input) {
129 print "Exiting\n";
130 savestatus($statusfile);
131 exit 0;
132 } elsif ($input =~ m/^(\d+)$/) {
133 $curmsgnum = $1 - 1;
134 $curmsgnum = $msglast if $curmsgnum > $msglast;
135 print "Jumping to message number $1\n";
136 next;
137 } elsif ("k" eq $input) {
138 # Skip this group and move to the next group
139 $aktive = 0;
140 } elsif ("f" eq $input) {
141 # View message header and body
142 my $articleref = $nntp->article($curmsgnum);
143 list_lines($articleref);
144 $curmsgnum--;
145 } elsif ("b" eq $input) {
146 # View message body
147 my $bodyref = $nntp->body($curmsgnum);
148 list_lines($bodyref);
149 $curmsgnum--;
150 } elsif ("h" eq $input) {
151 # print help
152 } else {
153 print STDERR "error: Unhandled choice '$input'\n";
154 }
155 }
156 if (@spammsgs) {
157 print "Submit changes? [yes] ";
158 my $input = <>;
159 chomp $input;
160 $input = "\L$input";
161 if ("" eq $input || "yes" eq $input) {
162 for my $msgnum (@spammsgs) {
163 report_spam($groupname, $msgnum);
164 }
165 }
166 }
167 $grouplast{$groupname} = --$curmsgnum;
168 print "Storing $curmsgnum as last read message in $groupname\n";
169 }
170
171 sub list_lines {
172 my $arrayref = shift;
173 for (@{$arrayref}) {
174 print " ", $_;
175 }
176 }
177
178 sub process_header {
179 my $headerref = shift;
180 my $subject;
181 my $from;
182 my $spam;
183 for (@{$headerref}) {
184 $from = $1 if m/^From: (.*)$/i;
185 $subject = $1 if m/^Subject: (.*)$/i;
186 $spam = 1 if m/Xref: .*gmane.spam.detected.*$/;
187 }
188 return ($spam, $subject, $from)
189 }
190
191 sub report_spam {
192 my ($groupname, $msgnum) = @_;
193 my $url = $spamurl;
194 $url =~ s/{group}/$groupname/g;
195 $url =~ s/{msgnum}/$msgnum/g;
196 my $response = $ua->get($url);
197 if ($response->is_success) {
198 print "Reported $groupname:$msgnum as spam.\n";
199 } else {
200 die $response->status_line;
201 }
202 }