use POSIX qw/strftime/;
use MIME::Entity;
use Pod::Usage;
+use Config::Auto;
+
+# Try and load a config file first, and then allow the command line
+# to over ride what is in the config file.
+my $c = eval {
+ Config::Auto::parse("mythtv-status.yml",
+ format => 'yaml',
+ )
+};
+if ($@ && $@ !~ /^No config file found/) {
+ # Die on any issues loading the config file, apart from it not existing.
+ die $@;
+}
# Some sane defaults.
-my $host = "localhost";
-my $port = "6544";
-my $description = undef;
-my $episode = undef;
-my $encoder_details = undef;
-my $colour = undef;
-my %display;
-my @email;
-my $email_only_on_alert = 0;
-my $help = undef;
-my $xml_file = undef;
+$c->{'host'} ||= "localhost";
+$c->{'port'} ||= "6544";
+$c->{'description'} ||= 0;
+$c->{'episode'} ||= 0;
+$c->{'encoder_details'} ||= 0;
+$c->{'colour'} ||= 0;
+#my %display;
+# my @email;
+$c->{'email_only_on_alert'} ||= 0;
+my $help = 0;
+$c->{'xml_file'} ||= undef;
my $verbose = 0;
-my $disk_space_warn = 95; # Percent to warn at.
-my $guide_days_warn = 2; # How many days we require.
-my $auto_expire_count = 10; # How many auto expire shows to display.
-my $recording_in_warn = 60 * 60; # When is the next recording considered critical? (seconds)
+$c->{'disk_space_warn'} ||= 95; # Percent to warn at.
+$c->{'guide_days_warn'} ||= 2; # How many days we require.
+$c->{'auto_expire_count'} ||= 10; # How many auto expire shows to display.
+$c->{'recording_in_warn'} ||= 60 * 60; # When is the next recording considered critical? (seconds)
# What units we have available for converting diskspaces.
my @size_thresholds = (
my $return_code_only = 0;
-my $VERSION = '0.9.1';
+my $VERSION = '0.9.2';
# Some display blocks are disabled by default:
-$display{'Shows due to Auto Expire'} = 0;
+$c->{'display'}{'Shows due to Auto Expire'} = 0;
GetOptions(
- 'c|colour|color' => \$colour,
- 'd|description' => \$description,
- 'e|episode' => \$episode,
- 'encoder-details' => \$encoder_details,
- 'h|host=s' => \$host,
- 'p|port=i' => \$port,
+ 'c|colour|color!' => \$c->{'colour'},
+ 'd|description!' => \$c->{'description'},
+ 'e|episode!' => \$c->{'episode'},
+ 'encoder-details!' => \$c->{'encoder_details'},
+ 'h|host=s' => \$c->{'host'},
+ 'p|port=i' => \$c->{'port'},
'v|version' => \&print_version,
- 'email=s@' => \@email,
+ 'email=s@' => \@{ $c->{'email'} },
'email-only-on-conflict|email-only-on-alert|email-only-on-alerts'
- => \$email_only_on_alert,
- 'disk-space-warn=i' => \$disk_space_warn,
- 'guide-days-warn=i' => \$guide_days_warn,
- 'auto-expire-count=i' => \$auto_expire_count,
- 'recording-in-warn=i' => \$recording_in_warn,
-
- 'status!' => \$display{'Status'},
- 'encoders!' => \$display{'Encoders'},
- 'recording-now!' => \$display{'Recording Now'},
- 'scheduled-recordings!' => \$display{'Scheduled Recordings'},
- 'schedule-conflicts!' => \$display{'Schedule Conflicts'},
- 'next-recording!' => \$display{'Next Recording In'},
- 'total-disk-space!' => \$display{'Total Disk Space'},
- 'disk-space!' => \$display{'Disk Space'},
- 'guide-data!' => \$display{'Guide Data'},
- 'auto-expire!' => \$display{'Shows due to Auto Expire'},
+ => \$c->{'email_only_on_alert'},
+ 'disk-space-warn=i' => \$c->{'disk_space_warn'},
+ 'guide-days-warn=i' => \$c->{'guide_days_warn'},
+ 'auto-expire-count=i' => \$c->{'auto_expire_count'},
+ 'recording-in-warn=i' => \$c->{'recording_in_warn'},
+
+ 'status!' => \$c->{'display'}{'Status'},
+ 'encoders!' => \$c->{'display'}{'Encoders'},
+ 'recording-now!' => \$c->{'display'}{'Recording Now'},
+ 'scheduled-recordings!' => \$c->{'display'}{'Scheduled Recordings'},
+ 'schedule-conflicts!' => \$c->{'display'}{'Schedule Conflicts'},
+ 'next-recording!' => \$c->{'display'}{'Next Recording In'},
+ 'total-disk-space!' => \$c->{'display'}{'Total Disk Space'},
+ 'disk-space!' => \$c->{'display'}{'Disk Space'},
+ 'guide-data!' => \$c->{'display'}{'Guide Data'},
+ 'auto-expire!' => \$c->{'display'}{'Shows due to Auto Expire'},
'return-code-only' => \$return_code_only,
- 'file=s' => \$xml_file,
+ 'file=s' => \$c->{'xml_file'},
'verbose' => \$verbose,
- 'help|?' => \$help,
+ 'help|?' => \$help,
) || pod2usage("\nUse --help for help.\n");
pod2usage(verbose => 1)
- if defined $help;
+ if $help;
# Get the email address into a format we can use.
-@email = split(',', join(',', @email));
+@{ $c->{'email'} } = split(',', join(',', @{ $c->{'email'} }));
# Default to not showing some blocks if we're sending email, but let the
# user override us.
-if (scalar(@email) > 0) {
+if (scalar(@{ $c->{'email'} }) > 0) {
for my $block ('Encoders', 'Recording Now', 'Next Recording In') {
- if (! defined $display{$block}) {
- $display{$block} = 0;
+ if (! defined $c->{'display'}{$block}) {
+ $c->{'display'}{$block} = 0;
}
}
}
my $safe = '';
my $warning = '';
my $normal = '';
-if (defined $colour && scalar(@email) == 0) {
+if ($c->{'colour'} && scalar(@{ $c->{'email'} }) == 0) {
$safe = "\033[0;32m";
$warning = "\033[1;31m";
$normal = "\033[0m";
'schedule' => {
'attrs' => [ qw/title startTime NODE_TEXT subTitle channelName:.\/Channel[@channelName] chanNum:.\/Channel[@chanId] inputId:.\/Channel[@inputId]/ ],
'template' => "__startTime__"
- . (defined $encoder_details ? " - Enc: __inputId__, Chan: __chanNum__" : '')
+ . ($c->{'encoder_details'} ? " - Enc: __inputId__, Chan: __chanNum__" : '')
. " - __title__"
- . (defined $episode ? " - __subTitle__" : '')
+ . ($c->{'episode'} ? " - __subTitle__" : '')
. " (__channelName__)"
- . (defined $description ? "\n__NODE_TEXT__" : ''),
+ . ($c->{'description'} ? "\n__NODE_TEXT__" : ''),
'filter' => {
# Only show recordings for today and tomorrow.
'id' => sub { return $_[0] eq 'total' },
'used' => sub {
return ! (
- (defined $display{'Disk Space'} && $display{'Disk Space'})
- || ($_[1]->{'used'} / $_[1]->{'total'}) * 100 > $disk_space_warn)
+ (defined $c->{'display'}{'Disk Space'} && $c->{'display'}{'Disk Space'})
+ || ($_[1]->{'used'} / $_[1]->{'total'}) * 100 > $c->{'disk_space_warn'})
}
},
'subs' => {
$str =~ s/^0 Hours, //;
$str =~ s/ 0 Minutes//;
- if ($seconds <= $recording_in_warn) {
+ if ($seconds <= $c->{'recording_in_warn'}) {
$warn_present ||= 1;
$str = "$warning$str$normal";
}
'template' => 'There is __guideDays__ days worth of data, through to __guideThru__',
'filter' => {
'guideDays' => sub {
- if ($_[0] > $guide_days_warn) {
+ if ($_[0] > $c->{'guide_days_warn'}) {
return
- (defined $display{'Guide Data'} && ! $display{'Guide Data'}) || 1;
+ (defined $c->{'display'}{'Guide Data'} && ! $c->{'display'}{'Guide Data'}) || 1;
} else {
$warn_present ||= 1;
push @alerts, "GUIDE DATA";
},
'rewrite' => {
'&guideDays' => sub {
- if ($_[0] <= $guide_days_warn) {
+ if ($_[0] <= $c->{'guide_days_warn'}) {
$warn_present ||= 1;
return "$warning$_[0]$normal";
} else {
},
'/guideThru/' => { 'T\d+:\d+:\d+' => ' ' },
'&guideThru' => sub {
- if ($_[1]->{'guideDays'} <= $guide_days_warn) {
+ if ($_[1]->{'guideDays'} <= $c->{'guide_days_warn'}) {
$warn_present ||= 1;
return "$warning$_[0]$normal";
} else {
if $verbose;
for my $block (@blocks) {
- $display{ $block->{'name'} } ||= 0;
+ $c->{'display'}{ $block->{'name'} } ||= 0;
}
}
my %version;
my $exit_value = 0;
-my $title = "MythTV status for $host";
+my $title = "MythTV status for $c->{'host'}";
my $output = "$title\n";
$output .= '=' x length($title) . "\n";
if $verbose;
my $hide = undef;
- if (defined $display{ $block->{'name'} }
- && $display{ $block->{'name'} } == 0) {
+ if (defined $c->{'display'}{ $block->{'name'} }
+ && $c->{'display'}{ $block->{'name'} } == 0) {
if (defined $block->{'hide'} && lc($block->{'hide'}) eq 'after') {
$hide = 1;
} else {
# Either print the status out, or email it.
if ($return_code_only) {
exit $exit_value;
-} elsif (scalar(@email) == 0) {
+} elsif (scalar(@{ $c->{'email'} }) == 0) {
print "\n$output";
} else {
- if ((! $email_only_on_alert) ||
- ($email_only_on_alert && scalar(@alerts) > 0)) {
+ if ((! $c->{'email_only_on_alert'}) ||
+ ($c->{'email_only_on_alert'} && scalar(@alerts) > 0)) {
my $suffix = undef;
if (@alerts == 1) {
$suffix = $alerts[0];
}
my $mail = MIME::Entity->build(
- To => \@email,
+ To => $c->{'email'},
Subject => $title . (defined $suffix ? " - $suffix" : ''),
Data => $output
);
sub load_xml {
my $status = "";
- if (defined $xml_file) {
- open (IN, "< $xml_file")
- || die "Failed to open $xml_file for reading: $!\n";
+ if (defined $c->{'xml_file'}) {
+ open (IN, "< $c->{'xml_file'}")
+ || die "Failed to open $c->{'xml_file'} for reading: $!\n";
$status = join("", <IN>);
close IN;
} else {
- my $url = "http://$host:$port/xml";
+ my $url = "http://$c->{'host'}:$c->{'port'}/xml";
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm(30);
$version{'xml'} = @{ $items }[0]->getAttribute('xmlVer') || 0;
$version{'protocol'} = @{ $items }[0]->getAttribute('protoVer');
- warn "Loaded XML from $host\n"
+ warn "Loaded XML from " . ($c->{'xml_file'} || $c->{'host'}) . "\n"
if $verbose;
return $xml;
if defined $str;
# Don't do more work than is required.
- last if --$auto_expire_count <= 0;
+ last if --$c->{'auto_expire_count'} <= 0;
}
return join("\n", @lines);
my $percent = sprintf("%.1f",
$used / $total * 100);
- if ($percent >= $disk_space_warn) {
+ if ($percent >= $c->{'disk_space_warn'}) {
$exit_value ||= 1;
push @alerts, "DISK SPACE";
return "$warning$percent\%$normal";