#!/usr/bin/env perl # -*- perl -*- =head1 NAME freemobile - A plugin to monitor a freemobile subscription =head1 Installation Create a link to this script in /etc/munin/plugins/ I F<$HOME/.config/weboob/munin/> =head1 CONFIGURATION You need to configure the user and the home PATH like that: [freemobile] env.HOME /home/florent user florent group florent You can configure the list of monitored data with the line: C Others monitored options: voicetoint voiceint smsint mmsint dataint specialvoice The cache timeout is 3 hours by default. You can change this value with C (seconds). =head1 LICENSE AGPLv3 =cut use strict; use warnings; use Carp; use English qw(-no_match_vars); use encoding 'iso-8859-1'; # Munin doesn't like utf-8 :-( use Encode; my @monitored = split / /, $ENV{'freemonitored'} || 'voice sms'; my $cachedir = $ENV{'HOME'} . '/.config/weboob/munin/'; my $cachefile = "$cachedir/freemobile-munin"; my $refreshtime = $ENV{'cache_expire'} || 10_800; my $weboob = '/usr/bin/env weboob-cli ICapBill get_details coin -f table'; my $cache_fh; my %label = ( 'voice' => 'Voix en France (min)', 'voicetoint' => 'Voix vers l\'international (min)', 'specialvoice' => 'Numéros spéciaux (min)', 'sms' => 'SMS en France', 'mms' => 'MMS en France', 'data' => 'Data en France', 'voiceint' => 'Voix à l\'international (min)', 'smsint' => 'SMS à l\'international', 'mmsint' => 'MMS à l\'international', 'dataint' => 'Data à l\'international', ); my %linenum = ( 'voice' => 3, 'voicetoint' => 3, 'specialvoice' => 4, 'sms' => 5, 'mms' => 6, 'data' => 7, 'voiceint' => 8, 'smsint' => 9, 'mmsint' => 10, 'dataint' => 11, ); my %regexp = ( 'voice' => 'National : (\d+)h(\d+)min(\d+)s', 'voicetoint' => 'International : (\d+)h(\d+)min(\d+)s', 'specialvoice' => '\| (\d+)h(\d+) min (\d+)s', 'sms' => 'Conso SMS \| (\d+) \/ (.*)', 'mms' => 'Vous avez consommé (\d+) MMS', 'data' => 'Vous avez consommé ([\d\-\.]+) Mo', 'voiceint' => 'Appels émis (\d+)h(\d+)min(\d+)s', 'smsint' => 'Conso SMS (international) \| (\d+)', 'mmsint' => 'Vous avez consommé (\d+) MMS', 'dataint' => 'Vous avez consommé ([\d\-]+) Mo', ); my %post = ( 'voice' => 'postvoice', 'voicetoint' => 'postvoice', 'specialvoice' => 'postvoice', 'sms' => 'simplepost', 'mms' => 'simplepost', 'data' => 'simplepost', 'voiceint' => 'postvoice', 'smsint' => 'simplepost', 'mmsint' => 'simplepost', 'dataint' => 'simplepost', ); sub doubleprint { my $var = shift; print {$cache_fh} $var; print $var; return 0; } sub postvoice { my @args = @_; my $minutes = $args[0] * 60 + $args[1] + $args[2] / 60; doubleprint "$minutes \n"; return 0; } sub simplepost { my @args = @_; doubleprint "$args[0] \n"; return 0; } sub config { binmode STDOUT, ':encoding(iso-8859-1)'; print <<'EOF'; graph_title Conso Free graph_vlabel Suivi conso du forfait Free Mobile graph_category weboob graph_args -l 0 EOF foreach (@monitored) { print "$_.label $label{$_}\n"; } return 0; } sub fetch { # Check if cache exist and not older than the refresh threshold. if ( open $cache_fh, '<', $cachefile ) { my @cache_data = <$cache_fh>; close $cache_fh or croak "unable to close: $ERRNO"; # File not empty? if ( @cache_data > 0 ) { # Data is still fresh. Display cached values and exit. if ( time - $cache_data[0] < $refreshtime ) { print join q{}, @cache_data[ 1 .. $#cache_data ]; exit 0; } } } # Open cache for writing and execute weboob open $cache_fh, '>', $cachefile or croak "Failed to open file $cachefile"; open my $data, q(-|), $weboob or croak "Couldn't execute program: $ERRNO"; my @lines = <$data>; close $data or carp "unable to close: $ERRNO"; print {$cache_fh} time . "\n"; foreach my $monit (@monitored) { doubleprint "$monit.value "; if ( my @results = $lines[ $linenum{$monit} ] =~ /$regexp{$monit}/ ) { my $postfunction = $post{$monit}; &{ \&$postfunction }(@results); } else { doubleprint "0 \n"; } } close $cache_fh or croak "unable to close: $ERRNO"; return 0; } # Create the munin cache dir if missing if ( !-d $cachedir ) { mkdir $cachedir; } if ( $ARGV[0] and $ARGV[0] eq 'config' ) { config; } else { fetch; } __END__