Using Selenium to monitor your Vonage balance

UPDATE [2013-01-20]: The scripts weren’t reading the username and password from the config file properly. In fact, I had accidentally hard-coded my own Vonage username and password in this script. D’oh! Needless to say, I’ve changed my password, and the updated scripts below are fixed. Also, I updated the cron script to allow the usage of Xvfb to be conditional, so you can test the cron script on your desktop and watch it running by editing the script and setting the XVFB variable to “false”.


Until today, I’ve been paying Vonage a ridiculous amount of money (almost $400) for an annual plan with unlimited minutes. It turns out they’ve got a much cheaper monthly plan, something like $14 per month even after all the bogus surcharges, taxes and fees they tack on, with 300 outbound domestic minutes and 300 outbound international minutes, and unlimited inbound minutes. We rarely exceed either of those limits in a month, so the cheaper plan is a much better deal for us, so I switched to it earlier today.

However, we do exceed the domestic minutes limit in busy months, sometimes by quite a lot, and in those months I’d really like to know when we’re on track to exceed the limit, so we can take steps to avoid paying the 5ยข per minute overage charge, like using our cell phones (which have unlimited minutes) for more of our outbound calls.

Unfortunately, Vonage doesn’t provide any sort of account alerts feature which would notify us if we’re on track to exceed our limits, or at the very least if we get close to exceeding them at any point during the month. And I certainly don’t want to have to waste my time logging into the Vonage web site to check our usage!

Sai Charan solved this with a Python script, but I couldn’t use his script for two reasons: (1) it complained about a missing “libxmlmods” Python module, which I can’t figure out where to get; and (2) Vonage recently rolled out a new web site, and I’m not convinced his script works with the new site. Not only that, but the new site seems to depend on JavaScript being enabled to work properly, so I don’t think a simple screen-scraping script like Sai’s is going to work anymore (I tried writing a script like this using WWW::Mechanize in Perl, and couldn’t get it to work).

I therefore decided to automate this check using Selenium. Below are two scripts: a Perl script which does the actual fetching of data from the Vonage site, and a shell script which you can run out of cron to set up the necessary environment, run the Perl script, and then clean up after itself.

Here are the prerequisites you need:

  • Download Selenium Server JAR file from http://seleniumhq.org/download/ and save it somewhere.
  • Find the java command in the cron script and update the path name of the Selenum Server JAR file.
  • Make sure you have java, Xvfb, and nmap installed and in your search path.
  • Make sure you have the WWW::Selenium Perl module installed. On my Fedora system, I was able to do “sudo yum install ‘perl(WWW::Selenium)’” to get it from the yum repository.

Here’s how to use the scripts:

  • Save the two scripts to disk as vonage-usage-cron.sh and vonage-usage.pl and make them executable.
  • Create the file ~/closed/vonage-config.pl which sets the $vonage_username and $vonage_password Perl variables to your username and password for trhe Vonage site. You can put the file somewhere else as long as you edit the line in vonage-usage.pl that loads it.
  • If you saved vonage-usage.pl somewhere other than ~/scripts, edit the invocation of it in vonage-usage-cron.sh to point at the correct location.
  • Run vonage-usage-cron.sh in an interactive shell and you should get a report on your minutes. If not, figure out why (the /tmp/#.X.log and /tmp/#.selenium.log files will tell you whether Xvfb and/or Selenium had trouble starting up).
  • If you only want to get email when you’re in danger of exceeding your monthly minutes, then remove “–debug” from the invocation of vonage-usage.pl in vonage-usage-cron.sh.
  • Put an entry in your crontab to run the script daily, and it’ll generate output which cron will presumably mail to you (every day if you leave –debug in, or only when there’s a potential overage if you take –debug out).

Clock below to view the scripts. Copy-and-paste to download them.

vonage-usage.pl

#!/usr/bin/perl

# Use Selenium to fetch your Vonage usage.
#
# Copyright (c) 2013 Jonathan Kamens <jik@kamens.us>. You can do
# whatever you want with this script, as long as you give me credit
# and don't make any money from it.
#
# You got this from http://blog.kamens.us/2013/01/17/using-selenium-to-monitor-your-vonage-balance/.
#
# There's a donate link there if you want to show your
# appreciation. :-) Or you can post comments or questions there or
# just email them to me.

use strict;
use warnings;

use Date::Parse;
use Getopt::Long;
use WWW::Selenium;

use vars qw($vonage_username $vonage_password);
my $debug = undef;

die "Bad usage" if (! GetOptions("username=s" => \$vonage_username,
				 "password=s" => \$vonage_password,
				 "debug" => \$debug));

do "$ENV{HOME}/closed/vonage-config.pl";

my $sel = WWW::Selenium->new(browser => '*firefox',
			     browser_url => 'http://www.vonage.com') or die;
$sel->start or die;
$sel->open("https://secure.vonage.com/account/viewBill.html") or die;
$sel->wait_for_page_to_load(30000) or die;
$sel->type("identifier=username", $vonage_username) or die;
$sel->type("identifier=password", $vonage_password) or die;
$sel->click("identifier=submitButton") or die;
$sel->wait_for_page_to_load(30000) or die;
my($page) = $sel->get_html_source();
$sel->open("https://secure.vonage.com/account/logout.html");

# Figure out where we are in the current billing period
$page =~ m,\((\d+/\d+/\d+)\s+-\s+(\d+/\d+/\d+)\)\s+Current Billing Statement, or die;
my($from, $to) = ($1, $2);
$from = str2time($from) or die "Bad start of billing statement period";
$to = str2time($to) or die "Bad end of billing statement period";
$to += 60 * 60 * 24; # Billing period ends at the end of the day
my $pct_of_month = (time() - $from) / ($to - $from);

my %usage;
# Now figure out whether we're on track for usage
while ($page =~ /(\d+)\s+(\S+)\s+Minutes\s+Used\s+of\s+(\d+)\s+Allowed/ig) {
    my($used, $type, $allowed) = ($1, $2, $3);
    my $old = $usage{$type};
    if ($old) {
	if ($used != $usage{$type}{'used'}) {
	    die "Usage mismatch for $type";
	}
	if ($allowed != $usage{$type}{'allowed'}) {
	    die "Allowed mismatch for $type";
	}
    }
    else {
	$usage{$type}{'used'} = $used;
	$usage{$type}{'allowed'} = $allowed;
    }
}

if (! %usage) {
    die "Found no usage metering";
}

foreach my $type (keys %usage) {
    my $used = $usage{$type}{'used'};
    my $allowed = $usage{$type}{'allowed'};
    my($pct_used) = $used / $allowed;
    my $tag;

    if ($pct_used > $pct_of_month) {
	$tag = "WARNING";
    }
    elsif ($debug) {
	$tag = "DEBUG";
    }
    if ($tag) {
	printf("%s: Used %.0f%% of $type allowance (%d of %d minutes), %.0f%% through the month\n",
	       $tag, $pct_used*100, $used, $allowed, $pct_of_month*100);
    }
}

vonage-usage-cron.sh

#!/bin/bash -e

# Cron wrapper script for vonage-usage.pl.
#
# Copyright (c) 2013 Jonathan Kamens <jik@kamens.us>. You can do
# whatever you want with this script, as long as you give me credit
# and don't make any money from it.
#
# You got this from http://blog.kamens.us/2013/01/17/using-selenium-to-monitor-your-vonage-balance/.
#
# There's a donate link there if you want to show your
# appreciation. :-) Or you can post comments or questions there or
# just email them to me.

# Set to "false" to use current X server
XVFB=true

if [ $(nmap -p T:4444 localhost | grep -cw open) != 0 ]; then
    echo "ERROR: Something is already listening on port 4444" 1>&2
    exit 1
fi

if $XVFB; then
    if [ $(nmap -p T:6099 localhost | grep -cw open) != 0 ]; then
	echo "ERROR: Something is already listening on port 6099" 1>&2
	exit 1
    fi

    Xvfb :99 >/tmp/$$.X.log 2>&1 &
    X_PID=$!
    export DISPLAY=:99
fi

java -jar ~/random/selenium-server-standalone-2.28.0.jar \
    >/tmp/$$.selenium.log 2>&1 &
S_PID=$!

tries=0
while [ $(nmap -p T:4444 localhost | grep -cw open) != 1 ]; do
    ((tries += 1))
    if [ $tries = 10 ]; then
	echo "ERROR: Selenium took too long to start up" 1>&2
	kill $X_PID $S_PID || :
	exit 1
    fi
    sleep 1
done

if $XVFB; then
    tries=0
    while [ $(nmap -p T:6099 localhost | grep -cw open) != 1 ]; do
	((tries += 1))
	if [ $tries = 10 ]; then
	    echo "ERROR: X took too long to start up" 1>&2
	    kill $X_PID $S_PID || :
	    exit 1
	fi
	sleep 1
    done
fi

# Omit --debug to only generate output if there are warnings.
~/scripts/vonage-usage.pl --debug

kill $X_PID $S_PID
rm -f /tmp/$$.*
Print Friendly

Tags:

3 Responses to “Using Selenium to monitor your Vonage balance”

  1. matt says:

    don’t listen to the troll – this worked great for me – thanks!

  2. Nate says:

    I’ve heard there are three great virtues of a programmer: Laziness, Impatience, and Hubris. And this post shows why.

Leave a Reply