[Home]ExternalPageMonitorScript

UseModWiki | RecentChanges | Preferences

#!/usr/bin/env perl

# This file was Copyright 2004 Dewey M. Sasser and is hereby
# explicitly placed in the public domain 

# Canonical release site:
# http://www.thesassers.com/dewey/UseMod.html

# Monitor a set of pages and email various interested parties when it changes
# Allow individual users to specify the pages in which they have interest.

# Instructions for use:
#
#   Arrange for this script to run periodically with the current
# directory being the directory to monitor.  It will read the wiki
# page file 'EmailOnChange' and pull email addresss that are on lines
# by themselves as the target of monitor email.  It will not send
# email if nothing has changed.
#
# By default it will create 1 extra file, called .wmon, in the
# location given by the HOME environment variable.  This file can be
# relocated by changing the configuration section. 
#
# Configuration:
#  
#   See the config section at the top of the code.  Set the variables
# appropriately. 
# 
# I use this with the following crontab entry:
#     WIKILOC=/usr/apache/htdocs/wiki
#     */5 * * * * (cd $WIKILOC; $HOME/bin/wmon)
#


# Notes:

# this is not a perfect implementation.  I can think of much better.
# This is a simple thing that will mostly work 

# $Revision: 1.9 $

# $Log: wmon,v $
# Revision 1.9  2004/08/11 20:51:29  dewey
# Added reference to dist site
#
# Revision 1.8  2004/08/11 20:31:34  dewey
# Cleaned up for posting
#
# Revision 1.7  2004/08/10 18:13:06  dewey
# Minor change in emailed message
#
# Revision 1.6  2004/08/10 17:59:05  dewey
# Now truncates subject line at reasonable length
#
# Revision 1.5  2004/08/10 17:49:24  dewey
# good-enough parsing of page database for email list
#
# Revision 1.4  2004/08/10 17:45:52  dewey
# Support for strange wiki page storage format
#
# Revision 1.3  2004/08/10 14:58:19  dewey
# Changed default location of .wmon
#
# Revision 1.2  2004/08/10 14:55:10  dewey
# Updated docs on .wmon file location
#
# Revision 1.1  2004/08/10 14:50:46  dewey
# Initial revision of wiki monitor



$Config{timeLoc}="$ENV{HOME}/.wmon";
$Config{wikiURL}="http://intranet1/cgi-bin/wiki.pl?";
$Config{interestedPartiesPage}="page/E/EmailOnChange.db";
$Config{pagePath}="page";
$Config{strangeWikiFormat}=1;
$Config{sendMail}=0;
$Config{mail}="| mail -s '\$subject' \$to ";
$Config{sendJustBody}=1;
$Config{wikiPageRegexp}="page/[A-Z]/.*\.db";




use strict 'vars';
use vars ( '%Config');

&main;

sub main
{
    my $fromTime = &readLastTime();
    my $toTime = time;
    my @changedFiles = &getFilesBetween($fromTime,$toTime);

    &mailAboutFiles(@changedFiles) &&
        &writeLastTime($toTime);
}

# read the list of interested parties from a "Mail on Change" page
sub readGeeks
{
    my @geeks;

    open(GEEKS,$Config{interestedPartiesPage}) || 
        return ("nobody");

    if ($Config{strangeWikiFormat})
        {
            # throw away first line
            <GEEKS>;
        }


    while(<GEEKS>)
    {
        chop;

        # it seems that we also want to ignore lines with the char
        # 263, but this works unless someone uses > or < as the first
        # character on a line

        if ($Config{strangeWikiFormat})
        {
            last if /^[<>]/;
        }

        next unless /^[ \t]*([^ \t]*\@[^ \t]*)[ \t]*$/;
        
        push(@geeks, $1);
    }

    close(GEEKS);

    return @geeks;
}


sub mailAboutFiles
{
    my @files = @_;

    # if there's nothing to mail, then don't
    return 1 unless @files;

    my $subject = "Changed Pages: " . join(", ", @files);
    my $bodyList = join("\n\t", &prefixWith($Config{wikiURL},@files));
    my @geeks = &readGeeks();
    my $geeks = join(", ", @geeks);
    my $tolist = join(" ", @geeks);

    my $mailprog = $Config{mail};

    # I'm allowing the special symbols "$to" and "$subject" in the
    # mail prog to resolve appropriately

    if(length($subject)>60)
    {
        $subject = substr($subject, 0, 60) . "...";
    }

    $mailprog =~ s/\$to/$tolist/g;
    $mailprog =~ s/\$subject/$subject/g;

    my $emailChangePage = &getPageName($Config{interestedPartiesPage});

    if ($Config{sendMail})
    {
        open(MAIL, $mailprog) || return &choke("Couldn't open $Config{mail}: $!");

        select(MAIL);
    }
    
    unless ($Config{sendJustBody} && $Config{sendMail})
    {
    print << "EOF";
To: $geeks
Subject: $subject

EOF
    }

    print << "EOF";
Just thought you might want to know, the following pages have all
changed:

	$bodyList

Edit the page wiki page $Config{wikiURL}$emailChangePage if you want
to remove yourself from this subscription.  

EOF

    if($Config{sendMail})
    {
        select STDOUT;
        close(MAIL);
    }
    
    return 1;
}

sub prefixWith
{
    my ($prefix, @strings)=@_;

    my @results;

    foreach my $string (@strings)
    {
        push(@results, "$prefix$string");
    }

    return @results;
}

sub getFilesBetween
{
    my ($start, $end) = @_;

    my $dir = ".";

    my @results;

    my @pagefiles=&getPageFiles();

    foreach my $file (@pagefiles)
    {
        my $fileMod = &getModTime("$dir/$file");
        my $page = &getPageName($file);
        push @results, $page if ($start < $fileMod && $fileMod < $end);
    }

    return @results;
}

sub getPageName
{
    my $file = shift @_;

    $file =~ /([^\/\.]+)(\.[^\/]*)?$/;

    return $1;
}

sub getPageFiles
{
    my $dir = shift @_;
    my @results;

    open(FIND,"find $Config{pagePath} -type f|") || &choke("Couldn't launch find: $!");

    while(<FIND>)
    {
        next if /~$/; # emacs style backup file
        next if /CVS\/(Entries|Repository|Root)/; # nothing in the CVS directories, please
        if($Config{wikiPageRegexp})
        {
            next unless /$Config{wikiPageRegexp}/;
        }

        chop;
        push(@results,$_);
    }

    close(FIND);

    return @results;
}

sub readLastTime()
{
    return 0 unless -r $Config{timeLoc};
    return `cat $Config{timeLoc}`;
}

sub writeLastTime()
{
    my $time = shift @_;

    system "echo $time > $Config{timeLoc}";
}

sub getModTime
{
    my $file = shift @_;

    return (stat($file))[9];
}


sub choke
{
    warn(@_);
    return 1;
}

UseModWiki | RecentChanges | Preferences
Edit text of this page | View other revisions | Search MetaWiki
Last edited August 11, 2004 8:38 pm by DeweySasser (diff)
Search: