CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Limit alerts to 3 max

 



sat110
Novice

Dec 20, 2008, 5:48 PM

Post #1 of 25 (5228 views)
Limit alerts to 3 max Can't Post

Hi Just signed up

I coach youth basketball, and need to check their schedule web page for available
time slots for practice dates and snow cancellations etc, if I'm even the slightest
bit late we wind up with the worst time slots available

I currently use a perl script to check their web page for text I define (inside)
every hour via cron, example I use 12/20/08, because whenever they update their page includes
the new date, so that seems to work for me.


if the date I define is not found inside the page it sends me a text
to phone message, Problem I have is, it never stops emailing me until I
get online and edit the script with the new date to stop that.

is there some kind of Perl code I can add to this script to linit the amount of alert
emails being sent, to no more then 3 times etc? till I can get online and enter the new date
inside the script

Any Help would be very appreciated.

below is the email code section of the script

if ($found ne "true") {
# Write the alert-email
$mailprog = '/usr/sbin/sendmail -oeq -t';
$recipient = 'test@yahoo.com';
$sender = 'test@gmail.com';
open (MAIL, "|$mailprog");
print MAIL "To: $recipient\n";
print MAIL "From: $sender\n";
print MAIL "Schedule Page Updated or down\n\n";
print MAIL "New practice slots may be posted.";
print MAIL "Call ASAP.";
close (MAIL);
}

exit;

Thanks


KevinR
Veteran


Dec 20, 2008, 6:54 PM

Post #2 of 25 (5223 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

Since the perl program is being run by a cron job you could write the number of times the perl program runs to a file and check the number in the file when the script starts. If the number is 3 just exit the program. But then you have to reset the number in the file back to 0 before restarting the next the next session.
-------------------------------------------------


sat110
Novice

Dec 20, 2008, 7:11 PM

Post #3 of 25 (5220 views)
Re: [KevinR] Limit alerts to 3 max [In reply to] Can't Post


In Reply To
Since the perl program is being run by a cron job you could write the number of times the perl program runs to a file and check the number in the file when the script starts. If the number is 3 just exit the program. But then you have to reset the number in the file back to 0 before restarting the next the next session.


Thanks for replying back so quickly

If someone can please move this over to the beginner thread for me, I obviously posted this in the wrong section,

If possible can you give an example I can use, as it would be included in my above code I pasted, if not thanks anyway

Sat


KevinR
Veteran


Dec 20, 2008, 7:40 PM

Post #4 of 25 (5217 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

There is nobody here that can move threads.

Anyway, at the very beginning of your perl program, something like:


Code
my $n = 0; 
open (FH, "<", 'path/to/file.txt') or die "$!";
$n = <FH>;
close FH;
if ($n < 3) {
open (FH, ">", 'path/to/file.txt') or die "$!";
print FH ++$n;
close FH;
}
else {
exit(0);
}
#your existing code here

-------------------------------------------------


sat110
Novice

Dec 20, 2008, 9:35 PM

Post #5 of 25 (5213 views)
Re: [KevinR] Limit alerts to 3 max [In reply to] Can't Post

Thank you so much!

this seems to work great for me
all alerts now stop after 3 emails

if anyone can use this, here is the complete code

Thanks again!

Sat

----------------------------------------------
#!/usr/bin/perl

use CGI::Carp qw(fatalsToBrowser);
use LWP::UserAgent;

my $ua = new LWP::UserAgent;
my $req = new HTTP::Request('GET', 'http://www.yourdomain/test.html');
my $res = $ua->request($req);


# Check if the requested webpage is there
if ($res->is_success) { # Request successful
$webpage = $res->content; # Store the page in the string $webpage
}

@webpage = split(/\n/,$webpage);

foreach $line (@webpage) {

# Below is the text you want to look for (I use the date)
# Example looking for 12/20/08
if ($line =~ /12\/20\/08/) {
$found = "true";
# Ok, we found a webpage with the above text in the HTML-code.
# So the webpage we are watching has not changed
}
}

my $n = 0;
open (FH, "<", '/fullpathto/alert-count.txt') or die "$!";
$n = <FH>;
close FH;
if ($n < 3) {
open (FH, ">", '/fullpathto/alert-count.txt') or die "$!";
print FH ++$n;
close FH;
}
else {
exit(0);
}
#your existing code here

if ($found ne "true") {
# Write the alert-email
$mailprog = '/usr/sbin/sendmail -oeq -t';
$recipient = 'test@yahoo.net';
$sender = 'test@gmail.com';
open (MAIL, "|$mailprog");
print MAIL "To: $recipient\n";
print MAIL "From: $sender\n";
print MAIL "Subject: Schedule Page Updated or down\n\n";
print MAIL "NEW Basketball schedule may be posted.";
print MAIL "Must Call ASAP.";
close (MAIL);
}

exit;
----------------------------------------------


FishMonger
Veteran / Moderator

Dec 21, 2008, 6:53 AM

Post #6 of 25 (5200 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

Kevin did a good job of showing how to limit it to 3 emails. So, now lets look at improving the overall quality of the script.

To begin with, every Perl script you write should include the warnings and strict pragmas which will point out common mistakes that are sometimes difficult to track down.

You could simplify the retrieval of the web page with LWP::Simple which uses LWP::UserAgent under the hood.

There really isn't any need to use the $found when checking for the date in the web page. Instead, move your checking of the count and email section into that spot.

Using the code Kevin gave is ok and is a common approach, but I think it could be improved with the use of the File::CounterFile module.


Code
#!/usr/bin/perl 

use strict;
use warnings;
use LWP::Simple;
use File::CounterFile;

# Store the page in the string $webpage
my $webpage = get('http://www.yourdomain/test.html');

# Check if the requested webpage is there
unless ( $webpage ) {
# you might want to create a log entry
exit;
}

# the date is passed to the script as an argument
# and I really should add some error handling to this part
my $date = shift;

if ( $webpage =~ m|$date| ) {
my $counter = File::CounterFile->new('/fullpathto/alert-count.txt', 0);
if ( $counter->value <= 3 ) {
$counter->inc;

# personally, I'd use MIME::Lite to send the email
# but this method is common and ok.
my $mailprog = '/usr/sbin/sendmail -oeq -t';
my $recipient = 'test@yahoo.net';
my $sender = 'test@gmail.com';
open (MAIL, "|$mailprog");
print MAIL "To: $recipient\n";
print MAIL "From: $sender\n";
print MAIL "Subject: Schedule Page Updated or down\n\n";
print MAIL "NEW Basketball schedule may be posted.";
print MAIL "Must Call ASAP.";
close (MAIL);
}
}


Keep in mind that when you modify the date that you search for, you also need to reset the counter either by manually editing the counter file or simply by deleting the file.


(This post was edited by FishMonger on Dec 21, 2008, 7:13 AM)


KevinR
Veteran


Dec 21, 2008, 7:33 AM

Post #7 of 25 (5196 views)
Re: [FishMonger] Limit alerts to 3 max [In reply to] Can't Post

He will also need to install the File::CounterFile module. I've never seen that one before, looks interesting.
-------------------------------------------------


FishMonger
Veteran / Moderator

Dec 21, 2008, 7:52 AM

Post #8 of 25 (5195 views)
Re: [KevinR] Limit alerts to 3 max [In reply to] Can't Post

Yes, File::CounterFile would need to be installed since it's not a core module, but that is a trivial task.

One improvement to my code, besides the already mentioned error handling, would be to put the $date assignment prior to retrieving the web page. Why? Because if the date wasn't passed, there would be no need to retrieve the web page. Part of the error handling on the $date assignment would be to send an email if it was undefined or if it wasn't in a valid format.


sat110
Novice

Feb 11, 2009, 12:47 PM

Post #9 of 25 (5028 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

This script below works great and emails
when it "does not" find a string match

is it possible to trigger (send email) only,
when "there is" a string match?

--------------------------------------------
#!/usr/bin/perl

use CGI::Carp qw(fatalsToBrowser);
use LWP::UserAgent;

my $ua = new LWP::UserAgent;
my $req = new HTTP::Request('GET', 'http://www.yourdomain/test.html');
my $res = $ua->request($req);


# Check if the requested webpage is there
if ($res->is_success) { # Request successful
$webpage = $res->content; # Store the page in the string $webpage
}

@webpage = split(/\n/,$webpage);

foreach $line (@webpage) {

# Below is the text you want to look for (I use the date)
# Example looking for 12/20/08
if ($line =~ /12\/20\/08/) {
$found = "true";
# Ok, we found a webpage with the above text in the HTML-code.
# So the webpage we are watching has not changed
}
}

my $n = 0;
open (FH, "<", '/fullpathto/alert-count.txt') or die "$!";
$n = <FH>;
close FH;
if ($n < 3) {
open (FH, ">", '/fullpathto/alert-count.txt') or die "$!";
print FH ++$n;
close FH;
}
else {
exit(0);
}
#your existing code here

if ($found ne "true") {
# Write the alert-email
$mailprog = '/usr/sbin/sendmail -oeq -t';
$recipient = 'test@yahoo.net';
$sender = 'test@gmail.com';
open (MAIL, "|$mailprog");
print MAIL "To: $recipient\n";
print MAIL "From: $sender\n";
print MAIL "Subject: Schedule Page Updated or down\n\n";
print MAIL "NEW Basketball schedule may be posted.";
print MAIL "Must Call ASAP.";
close (MAIL);
}

exit;
----------------------------------------------



FishMonger
Veteran / Moderator

Feb 11, 2009, 3:52 PM

Post #10 of 25 (5024 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

It sure is possible, and you only need to change 2 characters in your script. I'll leave it up to you to find out which 2 characters.


sat110
Novice

Feb 11, 2009, 4:03 PM

Post #11 of 25 (5019 views)
Re: [FishMonger] Limit alerts to 3 max [In reply to] Can't Post


In Reply To
It sure is possible, and you only need to change 2 characters in your script. I'll leave it up to you to find out which 2 characters.


if ($found ne "true") {
if ($found "true") {

I have been trying, I changed true to false
and that line above still does not work


KevinR
Veteran


Feb 11, 2009, 4:10 PM

Post #12 of 25 (5016 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

I thought we went over this before, maybe on a different forum?
-------------------------------------------------


sat110
Novice

Feb 11, 2009, 4:30 PM

Post #13 of 25 (5011 views)
Re: [KevinR] Limit alerts to 3 max [In reply to] Can't Post


In Reply To
I thought we went over this before, maybe on a different forum?


Way back I did post it on one other forum but this forum
"The Perl Archive" was the one that helped me, get that script
above working, just look at the orig post date above,

having the script match for some string before emailing is
probably the best way to go for me

So I came back to this forum because I know the people
around here, will always try to help people when possible


(This post was edited by sat110 on Feb 11, 2009, 4:31 PM)


FishMonger
Veteran / Moderator

Feb 11, 2009, 4:31 PM

Post #14 of 25 (5010 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

If you would have followed at least one of my prior recommendations, you'd find out that this line is definitely wrong.

if ($found "true") {


FishMonger
Veteran / Moderator

Feb 11, 2009, 4:38 PM

Post #15 of 25 (5008 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

What is Perl's opposite of ne ?


sat110
Novice

Feb 11, 2009, 4:38 PM

Post #16 of 25 (5007 views)
Re: [FishMonger] Limit alerts to 3 max [In reply to] Can't Post


In Reply To
If you would have followed at least one of my prior recommendations, you'd find out that this line is definitely wrong.

if ($found "true") {


you said it was exactly 2 characters
so I thought it might be the "ne"from
that line. at least I know I'm close
Thanks


FishMonger
Veteran / Moderator

Feb 11, 2009, 6:14 PM

Post #17 of 25 (5001 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

There's a reason why I used the word 'change' as apposed to 'remove'.


sat110
Novice

Feb 11, 2009, 6:34 PM

Post #18 of 25 (4998 views)
Re: [FishMonger] Limit alerts to 3 max [In reply to] Can't Post


In Reply To
There's a reason why I used the word 'change' as apposed to 'remove'.


I don't know, I have been trying to learn a little perl - php
and thought I was getting somewhere but obviously not I guess
I cant even tell you the opposite of "ne" I know you mentioned
I am 2 characters away but it might as well be a 1000


FishMonger
Veteran / Moderator

Feb 11, 2009, 6:43 PM

Post #19 of 25 (4994 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

if ($found eq"true") {


sat110
Novice

Feb 11, 2009, 7:04 PM

Post #20 of 25 (4986 views)
Re: [FishMonger] Limit alerts to 3 max [In reply to] Can't Post


In Reply To
if ($found eq"true") {


I did a search when you first asked about that
and I did consider "eq" instead of "ne", but for
some reason I kept thinking it was true false
related etc.

so this was it, change?
if ($found ne "true") {
to
if ($found eq "true") {


see this is the stuff that confuses me why doesn't
this below get changed?

if ($line =~ /12\/20\/08/) {
$found = "true";

again thanks


KevinR
Veteran


Feb 11, 2009, 10:35 PM

Post #21 of 25 (4979 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

When you have a true/false condition you can just use a binary flag. In perl, 0 (zero) is a false value, and 1 (or any number or string) is true. So you can do this:


Code
#!/usr/bin/perl  

use CGI::Carp qw(fatalsToBrowser);
use LWP::UserAgent;

my $ua = new LWP::UserAgent;
my $req = new HTTP::Request('GET', 'http://www.yourdomain/test.html');
my $res = $ua->request($req);


# Check if the requested webpage is there
if ($res->is_success) { # Request successful
$webpage = $res->content; # Store the page in the string $webpage
}

@webpage = split(/\n/,$webpage);
$found = 0;#false
foreach $line (@webpage) {

# Below is the text you want to look for (I use the date)
# Example looking for 12/20/08
if ($line =~ /12\/20\/08/) {
$found = 1;#true
# Ok, we found a webpage with the above text in the HTML-code.
# So the webpage we are watching has not changed
}
}

my $n = 0;
open (FH, "<", '/fullpathto/alert-count.txt') or die "$!";
$n = <FH>;
close FH;
if ($n < 3) {
open (FH, ">", '/fullpathto/alert-count.txt') or die "$!";
print FH ++$n;
close FH;
}
else {
exit(0); #<---here your program might exit before sending an email
}
#your existing code here

if ($found) {
# Write the alert-email
$mailprog = '/usr/sbin/sendmail -oeq -t';
$recipient = 'test@yahoo.net';
$sender = 'test@gmail.com';
open (MAIL, "|$mailprog");
print MAIL "To: $recipient\n";
print MAIL "From: $sender\n";
print MAIL "Subject: Schedule Page Updated or down\n\n";
print MAIL "NEW Basketball schedule may be posted.";
print MAIL "Must Call ASAP.";
close (MAIL);
}

exit;

-------------------------------------------------


(This post was edited by KevinR on Feb 11, 2009, 10:35 PM)


FishMonger
Veteran / Moderator

Feb 12, 2009, 7:12 AM

Post #22 of 25 (4968 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

If you're going to use a boolean flag, there is no need to initialize it to 0. An uninitialized var holds a value of undef and in boolean context that equates to false.

Personally, I would not use the flag. It would be better to correct the logic flow.

In its current form, the key purpose of this script is to send an email if the following 2 conditions are met; 1) the counter is less than 3, and 2) the specified date is in the web page. If the counter equals 3, then there is no need to check for the date so therefore, there is no reason to download the web page.

Checking the counter should be at the beginning of the script and the downloading of the web page should only be done if the counter is less than 3.

When checking/incrementing the counter, instead of opening the file twice, it would be more efficient to only open it once and use seek and truncate when updating. However, personally I'd use the File::CounterFile module which does this for you and includes file locking.

Since you're not setting a specific user agent, you could simply the retrieval of the web page by using LWP::Simple.

Here's an updated version and since there's no indication that this is run in a cgi environment, I left out the loading of the CGI::Carp module.


Code
#!/usr/bin/perl 

use strict;
use warnings;
use LWP::Simple;

my $date = $ARGV[0] or die "Usage: $0 mm/dd/yy\n";
my $counter_file = '/path/to/alert-count.txt';

open( my $FH, '+<', $counter_file ) or die $!;
my $cnt = <$FH> || 0;

if ($cnt < 3) {
seek($FH, 0, 0);
truncate $FH, 0;
print $FH ++$cnt;

my $webpage = get('http://www.yourdomain/test.html');
unless( defined $webpage ) {
die "failed to download schedule";
}

send_email() if $webpage =~ m|$date|;
}
close $FH;



sub send_email {
# Write the alert-email
my $mailprog = '/usr/sbin/sendmail -oeq -t';
my $recipient = 'test@yahoo.net';
my $sender = 'test@gmail.com';
open (MAIL, "|$mailprog") or die "can't pipe to sendmail $!";;
print MAIL "To: $recipient\n";
print MAIL "From: $sender\n";
print MAIL "Subject: Schedule Page Updated or down\n\n";
print MAIL "NEW Basketball schedule may be posted.";
print MAIL "Must Call ASAP.";
close (MAIL);
}



sat110
Novice

Feb 12, 2009, 7:44 AM

Post #23 of 25 (4963 views)
Re: [KevinR] Limit alerts to 3 max [In reply to] Can't Post

Hi FishMonger

I just changed what you said to do earlier "ne - eq"
and the orig script works the new way, fine now

this new script you posted which seems more efficient
but I see there is no search string, in it for me to enter

my $date = $ARGV[0] or die "Usage: $0 mm/dd/yy\n";
or
send_email() if $webpage =~ m|$date|;

that makes a lot of sense about not wanting to download the
page twice. I don't know how you and Kevin do this stuff so
easy. after my brief experience with scripts, I have the utmost
respect for programmers


(This post was edited by sat110 on Feb 12, 2009, 7:46 AM)


FishMonger
Veteran / Moderator

Feb 12, 2009, 8:02 AM

Post #24 of 25 (4960 views)
Re: [sat110] Limit alerts to 3 max [In reply to] Can't Post

How do you execute the script, form the command line or from a web page?

If you execute it from the command line, you'd pass the date as a parameter to the script instead of manually editing the script each time you need to use a different date.

e.g.,
script.pl 2/25/09

If you execute it from a web page, then we'd need to make a couple minor adjustments.


sat110
Novice

Feb 12, 2009, 9:44 AM

Post #25 of 25 (4955 views)
Re: [FishMonger] Limit alerts to 3 max [In reply to] Can't Post

Some times to test and make sure of things, I call it from the
browser, I also noticed when you move up the alert count
check code to the top, it writes (counts) every time the script
runs instead of the times it sends the email.

That can come in handy for lets say checking a page for a set
period of time depending on when and how many times a day
you call it etc.

When I first posted I needed to check for a particular string on
the page I was watching for example: 2/10/2009 and when
that that page was updated the string would be changed and I
would get a email "IF NOT FOUND" SEND EMAIL

The problem was that string would get changed whenever
minor changes were being done, thus eating up my alert count

The latest script now looks for a string and
"IF FOUND WILL" THEN SEND EMAIL

this is perfect and pretty much fool proof now, example if the
page's server is down or minor changes are updated I do not
get emailed

I look for a string like a future date 3/14/2009 and only when
found will I get emailed about the update meaning new dates
are available to me.

Although this might at a quick glance look like we went through
this before, but this new opposite function is like night and day.

I am using the orig version with eq instead of ne and it works
perfectly, Thanks to both of you, KevinR's log check code was
perfect for limiting alets.


(This post was edited by sat110 on Feb 12, 2009, 10:00 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives