I maintain a FAQ for the misc.immigration.misc newsgroup. I have
been looking for a short perl snippet to automate FAQ
announcements that would be posted to the misc.immigration.misc
newsgroup.
Also a perl snippet that could be run once a week to post an
article showing where the FAQ is.
I do something like this. It's based on 3 scripts. The first allows
you to add new postings to the autoposter and change frequencies and
the like, the second (run from cron) does the posting the third
displays which postings are due when.
Note that the option to have a post posted on a specific day doesn't
work over a new year (it starts in February). I must get round to
sorting that out.
The things to be posted need to be stored in text fles with all
headers except Message-ID, Supercedes and Date.
For clarity the following is not wrapped:
changes.pl - for adding new poststo and removing old posts from to
the autoposter
==BEGIN==
use strict;
use warnings;
use diagnostics;
use Storable;
my $hashref = retrieve('schedule.info');
while(1){
print 'Do you want to Add a new file, Change an existing one or Remove it? (A|C|R) ';
my $response;
until (($response = <STDIN>) =~ /[ACR]/i){
print "$response is not allowed\n";
print 'Do you want to Add a new file, Change an existing one or Remove it? (A|C|R) ';
}
if ($response =~ /a/i){
print 'Enter filename: ';
chomp(my $filename = <STDIN>);
print 'Enter schedule type (interval or day): ';
my $type = <STDIN>;
until ($type =~ /interval|day/i){
print "$type is not allowed\n";
print 'Enter schedule type (interval or day): ';
$type = <STDIN>;
}
chomp $type;
$type = lc $type;
my $postfreq;
my @days;
my $date = time();
if ($type eq 'interval'){
print 'Enter posting frequency in days: ';
chomp($postfreq = <STDIN>);
$$hashref{$filename} = {'date', $date, 'type', $type, 'interval', $postfreq};
}elsif ($type eq 'day'){
print 'Enter days to be posted on (seperated by spaces) ';
chomp($postfreq = <STDIN>);
@days = split / /, $postfreq;
$$hashref{$filename} = {'date', $date, 'type', $type, 'days', [@days]};
}
}
elsif ($response =~ /r/i){
print 'Enter filename: ';
chomp(my $filename = <STDIN>);
until (exists($$hashref{$filename})){
print "$filename is not known\n";
print 'Enter filename: ';
chomp($filename = <STDIN>);
}
delete $$hashref{$filename};
unlink ("C:/Usenet/autoposter/files/$filename") || warn "Could not delete $filename. $!";
}
elsif ($response =~ /c/i){
print 'Enter filename: ';
chomp(my $filename = <STDIN>);
until (exists($$hashref{$filename})){
print "$filename is not known\n";
print 'Enter filename: ';
chomp($filename = <STDIN>);
}
print 'Current type is ' . $$hashref{$filename}->{'type'} . ' do you want to change this? [y/n]';
if (<STDIN> =~ /y/i){
print 'Enter schedule type (interval or day): ';
my $type;
until (($type = <STDIN>) =~ /interval|day/i){
print "$type is not allowed\n";
print 'Enter schedule type (interval or day): ';
}
chomp $type;
$type = lc $type;
$$hashref{$filename}->{'type'} = $type;
newfreq($hashref,$filename);
}
else{
print 'Do you want to change the posting frequency? ';
newfreq($hashref,$filename) if (<STDIN> =~ /y/i);
}
}
print 'Do you want to change another file?? ';
last unless (<STDIN> =~ /y/i);
}
store $hashref, 'schedule.info';
##Sub routines follow
sub newfreq{
my ($hashref,$filename) = @_;
if ($$hashref{$filename}->{'type'} eq 'interval'){
print 'Enter posting frequency in days: ';
chomp(my $postfreq = <STDIN>);
$$hashref{$filename}->{'interval'} = $postfreq;
}
elsif ($$hashref{$filename}->{'type'} eq 'day'){
print 'Enter days to be posted on (seperated by spaces) ';
chomp(my $postfreq = <STDIN>);
my @days = split / /, $postfreq;
$$hashref{$filename}->{'days'} = \@days;
}
}
==END==
poster.pl - does the posting and works out when it next gets posted
==BEGIN==
use strict;
use warnings;
use diagnostics;
use Net::NNTP;
use Storable;
use Time::Local;
my $domain = 'A.DOMAIN.YOU.CAN.USE';
chdir ('C:/Usenet/autoposter');
my $hashref = retrieve('schedule.info');
# Data structure that is stored in schedule.info
#
# $hashref is a reference to a hash with the following keys
# 'type' = the way it is schedules (interval / specified days)
# 'date' = the date of next posting in time() format
# 'mid' = message-id used last time this was posted
# 'interval' = the interval (in days) that the post is repeated at (does not exist unless type = interval)
# 'days' = reference to an array containing the days they are to be posted on (does not exist unless type = day)
while (my ($filename,$info) = each %$hashref){
if ($$info{'type'} eq 'day'){
day($filename,$info);
}elsif ($$info{'type'} eq 'interval'){
interval($filename,$info)
}else{
warn "$filename has a type, $$info{'type'}, that is unknown"
}
}
store $hashref, 'schedule.info';
sub interval{
my $filename = shift;
my $info = shift;
if ($$info{'date'} < time){
if (post($filename, $info)){
$$info{'date'} += ($$info{'interval'} * 24 * 60 * 60);
}
}
}
sub day{
my $filename = shift;
my $info = shift;
if ($$info{'date'} < time){
if (post($filename, $info)){
my $next_day;
foreach (@{$$info{'days'}}){
if ($_ > (localtime($$info{'date'}))[3]){
$next_day = $_;
$$info{'date'} = timelocal(0,0,1,$next_day,[localtime()]->[4],[localtime()]->[5]);
last;
}
}
if ($$info{'date'} < time){
print "INSIDE SECOND IF";
$next_day = $$info{days}->[0];
my ($month,$year);
if([localtime()]->[4] +1 < 12){
$month = [localtime()]->[4] +1;
$year = [localtime()]->[5];
}else{
$month = 1;
$year = [localtime()]->[5] +1;
}
$$info{'date'} = timelocal(0,0,1,$next_day,$month,$year);
}
}
}
}
sub post{
my $filename = shift;
my $info = shift;
my $message_id = "Message-ID: <$filename".time().'@'."$domain>\n";
my $supercedes = '';
if(exists $$info{'mid'}){
$supercedes = $$info{'mid'};
$supercedes =~ s/^Message\-ID\://i;
$supercedes = 'Supercedes:'.$supercedes;
}
my $nntp = Net::NNTP->new('NNTPSERVER');
die 'Could not connect to server' unless ($nntp);
$nntp->authinfo('USER','PASS'); #comment out if IP based
open(POSTING, "files/$filename") or die "can't open files";
$nntp->post();
$nntp->datasend($message_id);
$nntp->datasend($supercedes) if ($supercedes);
$nntp->datasend(<POSTING>);
$nntp->dataend;
my $post_ok = $nntp->ok();
logit ($filename,$nntp->code);
$nntp->quit;
if ($post_ok){
$$info{'mid'} = $message_id;
return 1;
}else{
return 0;
}
}
sub logit{
my ($file,$code) = @_;
open (LOG, '>>C:/Usenet/autoposter/post.log') or warn "Not logged, $!";
my @date = localtime(time);
my $year = $date[5]+1900;
my $month = sprintf("%02d",$date[4]);
my $day = sprintf("%02d",$date[3]);
my $hour = sprintf("%02d",$date[2]);
my $minute = sprintf("%02d",$date[1]);
my $sec = sprintf("%02d",$date[0]);
print LOG "$day/$month/$year $hour:$minute:$sec $file $code\n";
close LOG;
}
==END==
files.pl - for seeing what files are being posted when
==BEGIN==
use strict;
use warnings;
use diagnostics;
use Storable;
my $hashref = retrieve('schedule.info');
my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @nextpost;
$^L = '';
$~ = 'INTERVAL';
$^ = 'INTERVAL_TOP';
foreach (sort keys %$hashref){
if ($$hashref{$_}->{'type'} eq 'interval'){
@nextpost = localtime($$hashref{$_}->{'date'});
write;
}
}
print "\n\n\n";
$~ = 'DAY';
$^ = 'DAY_TOP';
$- =0;
my $postlist;
foreach (sort keys %$hashref){
if ($$hashref{$_}->{'type'} eq 'day'){
@nextpost = localtime($$hashref{$_}->{'date'});
$postlist = join (' ',@{$$hashref{$_}->{'days'}});
write;
}
}
format INTERVAL=
@<<<<<<<<<<<<<< @# @<< @<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$_, $nextpost[3], $months[$nextpost[4]], $$hashref{$_}->{'interval'}, mid()
..
format INTERVAL_TOP=
Files posted at a given interval
================================
Filename Next Post Frequency Last Message-ID
..
format DAY=
@<<<<<<<<<<<<<< @# @<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<
$_, $nextpost[3], $months[$nextpost[4]],mid(), $postlist;
~~ ^<<<<<<<<<<<<<
$postlist
..
format DAY_TOP=
Files posted on a given day
===========================
Filename Next Post Last Message-ID Days Posted
..
sub mid{
$$hashref{$_}->{'mid'} ? substr($$hashref{$_}->{'mid'},13) : 'none'
}
==END==
Comments on these from experts would be taken on board with thanks.