#!/usr/bin/perl -w
# ts3v2_ (perl)
# Munin Plugin for Teamspeak3 Servers
# displays the number of connected users on TS3 servers
# and average transferrate per second over 5 min.
#
# You can use it with symlinks for overview and explicit ids.
# Also you can configure the following variables:
#  host
#  port
#
# by Marc Urben, www.oxi.ch or www.oom.ch
#
# Based on Tim Wulkau's script. Thank you!
# www.wulkau.de
#
#######################################################
# 02.10.10 - v0.3
#		    -now works again with 3.0.0-beta29 
#
# 18.04.10 - v0.2
#           -transfer mode added
#
# 13.04.10 - v0.1
#           -initial release
#
######################################################
 
#%# family=auto
#%# capabilities=autoconf suggest
 
use strict;
use Net::Telnet;
 
# CONFIG HERE!
my $hostname =  $ENV{host} || "localhost";    # serveraddress
my $port =      $ENV{port} || 10011;      # querryport
my $user =      $ENV{user} || "serveradmin";
my $password =  $ENV{password} || "";
my $filename =  "ts3v2_";
 
# SCRIPT START!
#init telnet connection
my $name = ""; my $server = ""; my @num; my $id = 0; my $i = 0; my $myserver; my $transfer;
my $telnet = new Net::Telnet(Timeout=>1, Errmode=>"return", Prompt=>"/\r/");
if (!$telnet->open(Host=>$hostname, Port=>$port)) {
        die "Server could not be reached, please check your config!";
}

$telnet->waitfor("/Welcome/");

if ($password ne "") {
  $telnet->cmd("login client_login_name=".$user." client_login_password=".$password);
  my $response = $telnet->getline(Timeout=>1);
  if ($response !~ "error id=0 msg=ok") {
        $telnet->close;
        die "ServerQuery login failed: ".$response;
  }
}
 
#get argument
my $argument = "";
if ($0 =~ /$filename(\w+)$/i) {
        $argument = $1;
} elsif ($ARGV[0] ne "suggest" and $ARGV[0] ne "autoconf") {
        die "Error: We need to know what serverid you want, so link this plugin as "
                .$filename."1, ".$filename."2 or ".$filename."overview.\n";
}
 
#check for overview, transfer or single server mode
my $mode = "";
if ($argument eq "overview" or $argument eq "transfer" or (defined $ARGV[0] and ($ARGV[0] eq "suggest" or $ARGV[0] eq "autoconf"))) {
        if ($argument eq "overview") {
                $mode = "o";
        } elsif($argument eq "transfer") {
                $mode = "t";
        }
        $telnet->cmd("serverlist");
        my $line = $telnet->getline(Timeout=>1);
        my @servers = split(/\|/, $line);
        foreach (@servers) {
                if ($_ =~ m/virtualserver_id=(\d+) virtual/) {
                        push(@num, $1);
                } else {
                        die "ERROR: server string not recognized!\n";
                }
        }
        $telnet->waitfor("/error id=0 msg=ok/");
} elsif ($argument =~ /^[+-]?\d+$/ ) {
        $mode = "s";
        $server = $argument;
} else {
        die "ERROR: unknown plugin mode: $argument\n";
}
 
#check for config mode
if (exists $ARGV[0] and $ARGV[0] eq "autoconf") {
        print "yes";
        exit 0;
} elsif (exists $ARGV[0] and $ARGV[0] eq "suggest") {
        print "overview\n";
        print "transfer\n";
        foreach (@num) {
                print $_."\n";
        }
        exit 0;
} elsif (exists $ARGV[0] and $ARGV[0] eq "config") {
        if ($mode eq "s") {
                #single server mode
                $telnet->cmd("use sid=".$server);
                $telnet->waitfor("/error id=0 msg=ok/");
                $telnet->cmd("serverinfo");
                my $line = $telnet->getline(Timeout=>1);
 
                if ($line =~ m/virtualserver_id=(\d+) virtual/) {
                        my $id = $1;
                } else {
                        die "ERROR: server string not recognized!\n";
                }
                if ($line =~ m/virtualserver_name=(.*) virtualserver_welcomemessage/) {
                        $name = $1;
                        $name =~ s/\\s/ /g;
                } else {
                        die "ERROR: server string not recognized!\n";
                }
                $telnet->waitfor("/error id=0 msg=ok/");
 
                print "graph_title Teamspeak Users ".$name."\n";
                print "graph_vlabel Connected Teamspeak Users\n";
                print "graph_category voip\n";
                print "graph_info This graph shows the number of connected users on a Teamspeak3 server\n";
                print "users.label Users\n";
                print "users.info Connected users to ".$name."\n";
                print "users.type GAUGE\n";
 
                exit 0;
        } elsif ($mode eq "o") {
                #overview mode
                print "graph_title Teamspeak Users Overview\n";
                print "graph_vlabel Connected Teamspeak Users\n";
                print "graph_category voip\n";
                print "graph_info This graph shows the number of connected users on a Teamspeak3 server\n";
 
                foreach (@num) {
                        $telnet->cmd("use sid=".$_);
                        $telnet->waitfor("/error id=0 msg=ok/");
                        $telnet->cmd("serverinfo");
                        my $line = $telnet->getline(Timeout=>1);
                        if ($line =~ m/virtualserver_name=(.*) virtualserver_welcomemessage/) {
                                $name = $1;
                                $name =~ s/\\s/ /g;
                        } else {
                                die "ERROR: server string not recognized!\n";
                        }
                        $telnet->waitfor("/error id=0 msg=ok/");
                        print $_.".label ".$name."\n";
                        print $_.".info Users connected on ".$name."\n";
                        print $_.".type GAUGE\n";
                }
                exit 0;
        } elsif ($mode eq "t") {
                #transfer mode
                print "graph_title Teamspeak Transfer Overview\n";
                print "graph_vlabel Teamspeak Transfer\n";
                print "graph_category voip\n";
                print "graph_info This graph shows the Teamspeak3 Transfer Overview\n";
                print "transfer.label ~ Transfer per second\n";
                print "transfer.info Transfer per second over 5 min\n";
                print "transfer.type DERIVE\n";
                exit 0;
        }
} else {
        #go go magic, go!
        if ($mode eq "s") {
                #single mode
                $telnet->cmd("use sid=".$server);
                $telnet->waitfor("/error id=0 msg=ok/");
                $telnet->cmd("serverinfo");
 
                my $line = $telnet->getline(Timeout=>1);
                if ($line =~ m/virtualserver_clientsonline=(\d+) /) {
                        print "users.value ".($1-1)."\n";
                } else {
                        print "users.value 0\n";
                }
                $telnet->waitfor("/error id=0 msg=ok/");
        } elsif ($mode eq "o") {
                #overview mode
                for (@num) {
                        $telnet->waitfor("/Welcome/");
                        $telnet->cmd("use sid=".$_);
                        $telnet->waitfor("/error id=0 msg=ok/");
                        $telnet->cmd("serverinfo");
 
                        my $line = $telnet->getline(Timeout=>1);
                        if ($line =~ m/virtualserver_clientsonline=(\d+) /) {
                                print $_.".value ".($1-1)."\n";
                        } else {
                                print $_.".value 0\n";
                        }
                        $telnet->waitfor("/error id=0 msg=ok/");
                }
        } elsif ($mode eq "t") {
                $telnet->cmd("hostinfo");
                my @tsave;
                my $line = $telnet->getline(Timeout=>1);
                if ($line =~ m/connection_bytes_received_total=(\d+) connection_bandwidth_sent_last_second_total/) {
                        $transfer = $1;
                        print "transfer.value ".(($transfer-($transfer%300))/300)."\n";
                } else {
                        die "ERROR: server string not recognized!\n";
                }
                $telnet->waitfor("/error id=0 msg=ok/");
 
        }
}
 
#close telnet connection
$telnet->close;
exit;
