File ts3snapshot of Package teamspeak3-server

#!/bin/sh

usage="\
$0 - create or deploy a snapshot of a virtual Teamspeak 3 server instance

Usage:
$0 [-h host] [-p <port>] [-i <instance>] [-f <file>] [-u <user>] [-P <password>] [cmd]

Commands:
  create        create snapshot (read from server and save to file)
  deploy        deploy snapshot (read from file and write to server)
  clientlist    list clients that are currently online

Options:
  -h <hostname> server hostname   (default: localhost)
  -p <port>     server query port (default: 10011)
  -i <instance> virtual server    (default: only on create: all instances)
  -f <file>     snapshot file     (default: ts3-snapshot-%%i.txt
  -u <user>     admin query user name
  -P <password> admin query user password

Notes:
- if you provide an instance number, only this virtual server is processed.
- if you provide a file name with -f, %%i is replaced with the instance number
- settings from /etc/teamspeak3-server/snapshot are used as defaults"


# read server response from input, return 0 on success
# return 1 and print message, if server returns error
check_ts3_response() {
  local prefix=$1 kw=$2

  read -r kw id msg
  if [ "$kw" != "error" ]; then
    echo $prefix
    echo "Unexpected server response \"$kw $id $msg\""
    return 2
  fi
  [ "$id" = "id=0" ] && return 0
  echo $prefix
  msg=${msg#msg=}
  echo "Server message: \"${msg//\\s/ }\""
  return 1
}

# perform signon to Teamspeak server, return 0 on success
# return 1 and print message, if server returns error
check_ts3_signon() {
  local line line1

  if ! read -r line; then
    echo "Unable to connect to the Teamspeak Server"
    echo "host=\"$1\""
    echo "port=\"$2\""
    return 1
  fi
  if [ "$line" != "TS3" ]; then
    echo "Invalid greeting line(1), expected \"TS3\", got \"$line\""
    return 1
  fi

  read -r line line1
  if [ "$line" != "Welcome" ]; then
    echo "Invalid greeting line(2), expected \"Welcome to the TeamSpeak 3 ServerQuery interface[...]\", got \"$line $line1\""
    return 1
  fi
  return 0
}

# output list of online clients
clientlist() {
  local dir line _host=$1 _port=$2 _instance=$3 _user=$4 _pass=$5

  echo "client list for instance $_instance:"
  echo -e "use $_instance\nlogin $_user $_pass\nclientlist -ip\nquit" | \
  nc $_host $_port | tr -d "\r" | {
    check_ts3_signon $_host $_port || return 1
    check_ts3_response "Unable to select server instance \"$_instance\"" || return 1
    check_ts3_response "Unable to login to the Teamspeak server" || return 1
    read -r line
    for cl in `echo "$line"|xargs -n 1 -d "|"`; do
      echo "$cl"|grep -E "^client_nickname"
    done

    check_ts3_response "Unable to get clientlist" || return 1
  } || return 1
  return 0
}

# get a list of all virtual servers and get the list of online clients for all of them
clientlist_all() {
  local line _host=$1 _port=$2 _user=$3 _pass=$4

  echo -e "login $_user $_pass\nserverlist -short\nquit" | \
  nc $_host $_port | tr -d "\r" | {
    check_ts3_signon $_host $_port || return 1
    check_ts3_response "Unable to login to the Teamspeak server" || return 1
    read -r line
    check_ts3_response "Unable to get server instance list" || return 1

    for i in `echo "$line"|xargs -n 1 -d "|"|grep "virtualserver_status=online"|sed -re 's/virtualserver_id=([0-9]+).*/\1/g'`; do
      if ! clientlist "$_host" "$_port" "$i" "$_user" "$_pass"; then
        echo "clientlist for server instance $i failed."
      fi
    done
  } || return 1
  return 0
}


# deploy a snapshot to given virtual server instance
snapshot_deploy() {
  local _host=$1 _port=$2 _instance=$3 _user=$4 _pass=$5 _file=$6

  if [ ! -f $_file ]; then
    echo "Unable to find input file '$_file', aborting"
    exit 1
  fi
  echo -e "use $_instance\nlogin $_user $_pass\n serversnapshotdeploy `cat $_file`\nquit" | \
  nc -4 $_host $_port | tr -d "\r" | {
    check_ts3_signon $_host $_port || return 1
    check_ts3_response "Unable to select server instance \"$_instance\"" || return 1
    check_ts3_response "Unable to login to the Teamspeak server" || return 1
    check_ts3_response "Unable to deploy snapshot" || return 1
  } || return 1
  return 0
}

# create a snapshot from given vitual server instance and write to file
snapshot_create() {
  local dir line _host=$1 _port=$2 _instance=$3 _user=$4 _pass=$5 _file=$6

  dir=`dirname "$_file"`
  echo -e "use $_instance\nlogin $_user $_pass\nserversnapshotcreate\nquit" | \
  nc -4 $_host $_port | tr -d "\r" | {
    check_ts3_signon $_host $_port || return 1
    check_ts3_response "Unable to select server instance \"$_instance\"" || return 1
    check_ts3_response "Unable to login to the Teamspeak server" || return 1
    read -r line
    [ -z "$dir" -o -d "$dir" ] || mkdir -p "$dir"
    echo -n "$line" > "$_file"
    check_ts3_response "Unable to get snapshot" || { rm -f "$_file"; return 1; }
  } || return 1
  return 0
}

# get a list of all virtual servers and create snapshots for each of them
# Put a %%i into the filename to avoid that the snaphots overwrite each other
snapshot_create_all() {
  local line _host=$1 _port=$2 _user=$3 _pass=$4 _file=$5

  echo -e "login $_user $_pass\nserverlist -short\nquit" | \
  nc -4 $_host $_port | tr -d "\r" | {
    check_ts3_signon $_host $_port || return 1
    check_ts3_response "Unable to login to the Teamspeak server" || return 1
    read -r line
    check_ts3_response "Unable to get server instance list" || return 1

    for i in `echo "$line"|xargs -n 1 -d "|"|grep "virtualserver_status=online"|sed -re 's/virtualserver_id=([0-9]+).*/\1/g'`; do
      if ! snapshot_create "$_host" "$_port" "$i" "$_user" "$_pass" "${_file//\%%i/$i}"; then
        echo "Snapshot for server instance $i failed."
      fi
    done
  } || return 1
  return 0
}

if [ ! -x /usr/bin/nc ]; then
  echo "/usr/bin/nc not found - please install NetCat!"
  exit 1
fi

[ -f /etc/teamspeak3-server/snapshot ] && . /etc/teamspeak3-server/snapshot

while getopts "f:h:i:p:u:P:" key ; do
  case "$key" in
    f) file="$OPTARG" ;;
    h) host="$OPTARG" ;;
    i) instance="$OPTARG" ;;
    p) port="$OPTARG" ;;
    u) user="$OPTARG" ;;
    P) pass="$OPTARG" ;;
    *) exec echo "$usage" ;;
  esac
done
shift $(( $OPTIND -1 ))
cmd=${1:-}
host=${host:-localhost}
port=${port:-10011}
file=${file:-ts3-snapshot-%%i.txt}

if [ -z "$user" -o -z "$pass" ]; then
  echo -e "error: no username or password given!\n"
  exec echo "$usage"
fi

case "$cmd" in
  deploy)
    if [ -z "$instance" ]; then
      echo -e "deploy requires an instance number\n"
      exec echo "$usage"
    fi
    snapshot_deploy "$host" "$port" "$instance" "$user" "$pass" "${file//\%%i/$instance}"
    ;;
  create)
    if [ -z "$instance" ]; then
      snapshot_create_all "$host" "$port" "$user" "$pass" "$file"
    else
      snapshot_create "$host" "$port" "$instance" "$user" "$pass" "${file//\%%i/$instance}"
    fi
    ;;
  clientlist)
    if [ -z "$instance" ]; then
      clientlist_all  "$host" "$port" "$user" "$pass"
    else
      clientlist "$host" "$port" "$instance" "$user" "$pass"
    fi
    ;;
  *)
    echo -e "Unknown command \"$cmd\"\n"
    exec echo "$usage"
    ;;
esac
openSUSE Build Service is sponsored by