Webspell 4.2.5 Teamspeak Integration

By | 13. September 2017

Hiho!

Entwicklungen nach Bedarf habe ich am liebsten und so kam es, dass vor einigen Tagen ein Teamspeak-Webpanel für das alte Content-Management-System „WebSpell“ erstellt werden musste. Im Vordergrund standen erstmal nur kleine Funktionen, welche das Starten/Stoppen des Server möglich machen sollten und das regelmäßige Beziehen von Serverbackups. In Zuge dessen habe ich das Addon so geschrieben, dass auch jeder damit etwas anfangen kann und es auf webspell.org veröffentlicht. Ich möchte in diesem Artikel ein bisschen auf den Code eingehen und ihn auch hier nochmal zum Download zur Verfügung stellen. Der Code ist hier zu finden: https://git.barny-blog.de/Barny/Teamspeak-Integration
Außerdem ist das Addon mittlerweile durch Webspell.org selber geprüft worden und Version 1.0 steht auf der offiziellen Webspell-Webseite zum Download zur Verfügung: https://www.webspell.org/index.php?site=addons&action=details&addonID=236

Eingehen werde ich hier nur auf den abolsuten Kern des Addons. Die Implementierung in das Theme lasse ich hier aus.

Der Kern besteht aus der Klasse „Ts3Conn“, welche für die vollständige Kommunikation mit dem Teamspeak-Server zuständig ist. Sie befindet sich in der Datei „teamspeak_server_conn.php“. Mit dieser Klasse lässt sein derzeit ein Server starten, stoppen und neustarten. Auch lassen sich „Serversnapshots“ erstellen und wieder einspielen. Es gibt zwar diverse Klassen bereits online, jedoch fand ich diesen Klassen zu „überladen“ und das wäre für so ein simples Modul einfach ein „Overkill“ gewesen. Außerdem fand ich in vielen Klassen die Online zu finden sind kleinere Fehler, welche ich nicht unbedingt auf eigene Faust korrigieren wollte. Demnach ist eine neue Schnittstelle entstanden.

Abb. 1: Funktionen in der Version 1.0.0

Die Kommunikation findet auschließlich über eine Verbindung mit der Server Query Schnittstelle des Teamspeakservers statt. Die benötigten Verbindungsdaten werden in der Datenbank der Webspellinstallation gespeichert und lassen sich jederzeit durch den Benutzer anpassen.

Abb. 2: Einstellungen

Das oben gezeigte Menü ist nahtlos in die Webspelladministration übernommen worden.

Abb. 3: Admin Menü

Auch lassen sich hierfür Benutzerberechtigungen festlegen, um dynamisch entscheiden zu können welcher User den Teamspeakserver steuern darf und welcher nicht. Diese wurden direkt in die Benutzeradministration von Webspell selbst übernommen. Hier ist nun eine weitere Benutzergruppe „Teamspeakadmin“ zu finden, mit der sich bequem alle Benutzer wie gewohnt steuern lassen können.

Sourcecode:

Die Klasse „Ts3Conn“ ist so aufgebaut, dass der Code 1. gut wartbar ist und 2. leicht erweiterbar. Außerdem ist er sehr neutral gehalten worden, sodass seine Benutzung keine Webspellinstallation voraussetzt. Prinzipiell kann ihn also jeder auch für andere Projekte verwenden, solange die Credits daraus nicht verschwinden. 😉

Wie in der Klasse ersichtlich ist, wird eine Verbindung mit dem Server hergestellt und je nachdem welche Methode aufgerufen wird weiter verfahren. In jedem Fall muss sich das Programm authentifizieren. Hierfür werden die oben erwähnten Verbindungsinformationen benötigt.

In unten zu sehenden Quellcode sind bereits mehrere Methoden implementiert worden, welche das Erstellen von Backups möglich machen. Es ist daher (entgegen oben zu sehendem Screenshot der Version 1.0.0) bereits möglich Serverbackups zu erstellen und einzuspielen. Das erstellte Serverbackup wird in der Webspelldatenbank abgelegt und kann jederzeit über das Menü von dort aus wieder eingespielt werden. Ein Download ist aber trotzdem möglich.

<?php
/*
 #------------------------------------------------------------------------#
 # ____                               ____  _                  _          #
 #| __ )  __ _ _ __ _ __  _   _      | __ )| | ___   __ _   __| | ___     #
 #|  _ \ / _` | '__| '_ \| | | |_____|  _ \| |/ _ \ / _` | / _` |/ _ \    #
 #| |_) | (_| | |  | | | | |_| |_____| |_) | | (_) | (_| || (_| |  __/    #
 #|____/ \__,_|_|  |_| |_|\__, |     |____/|_|\___/ \__, (_)__,_|\___|    #
 #                        |___/                     |___/                 #
 #            															 #
 # Copyright 2017 by Barny-Blog.de										 #
 # Changes taken by Barny-Blog.de:                                        #
 #------------------------------------------------------------------------#
 24.07.17 Barny - Added Teamspeakadministration
 06.08.17 Barny - Added Serverbackups
 */

class Ts3Conn {
	
	var $address;
	var $serverqueryport;
	var $virtualServerPort;
	var $conn;
	var $connected;
	var $username = "";
	var $password = "";
	var $serverBackup = "";
	
	// Contants
	var $WELCOMEMESSAGE = "Welcome to the TeamSpeak 3 ServerQuery interface";
	
	public function Ts3Conn($address,$serverqueryport,$virtualServerPort="9987") {
		$this->address = $address;
		$this->serverqueryport= $serverqueryport;
		$this->virtualServerPort = $virtualServerPort;
		if(!$this->connect()) {
			$this->connected = false;
			$this->closeConnection();
		}else {
			$this->connected = $this->readWelcomeMessage();
		}
	}
	
	public function startTeamspeakServer() {
		if($this->connected) {
			if($this->username == "" && $this->password == "") {
				return false;
			}
			if(!$this->authenticate()) {
				return false;
			}
			$serverId = $this->getRightServer();
			if($serverId == "-1") {
				return false;
			}
			$out = "serverstart sid=".$serverId."\n";
			socket_write($this->conn, $out, strlen($out));
			$response = $this->readMessage();
			if($this->queryWasOk($response)) {
				$this->closeConnection();
				return strpos($response,"msg=ok") !== false;
			}
		}else {
			$this->closeConnection();
			return false;
		}
	}
	
	public function stopTeamspeakServer() {
		if($this->connected) {
			if($this->username == "" && $this->password == "") {
				return false;
			}
			if(!$this->authenticate()) {
				return false;
			}
			$serverId = $this->getRightServer();
			if($serverId == "-1") {
				return false;
			}
			$out = "serverstop sid=".$serverId."\n";
			socket_write($this->conn, $out, strlen($out));
			$response = $this->readMessage();
			if($this->queryWasOk($response)) {
				$this->closeConnection();
				return strpos($response,"msg=ok") !== false;
			}
		}else {
			$this->closeConnection();
			return false;
		}
	}
	
	public function restartTeamspeakServer() {
		if($this->connected) {
			if($this->username == "" && $this->password == "") {
				return false;
			}
			if(!$this->authenticate()) {
				return false;
			}
			$serverId = $this->getRightServer();
			if($serverId == "-1") {
				return false;
			}
			$out = "serverstop sid=".$serverId."\n";
			socket_write($this->conn, $out, strlen($out));
			$response = $this->readMessage();
			if($this->queryWasOk($response)) {
				if(strpos($response,"msg=ok") !== false) {
					$out = "serverstart sid=".$serverId."\n";
					sleep(3);
					socket_write($this->conn, $out, strlen($out));
					$response = $this->readMessage();
					$this->closeConnection();
					return strpos($response,"msg=ok") !== false;
				}
			}
		}else {
			$this->closeConnection();
			return false;
		}
	}
	
	public function createServerBackup() {
		if($this->connected) {
			if($this->username == "" && $this->password == "") {
				return false;
			}
			if(!$this->authenticate()) {
				return false;
			}
			$out = "use port=".$this->virtualServerPort."\n";
			socket_write($this->conn, $out, strlen($out));
			$response = $this->readMessage();
			if(!$this->queryWasOk($response)) {
				return false;
			}
			$out = "serversnapshotcreate\n";
			socket_write($this->conn, $out, strlen($out));
			$serverBackup = $this->readServerBackup();
			if(!$this->queryWasOk($serverBackup)) {
				return false;
			}
			$this->serverBackup = $this->stripStatus($serverBackup);
			return true;
		}
	}
	
	public function deployServerBackup($backup) {
		if($this->connected) {
			if($this->username == "" && $this->password == "") {
				return false;
			}
			if(!$this->authenticate()) {
				return false;
			}
			$out = "use port=".$this->virtualServerPort."\n";
			socket_write($this->conn, $out, strlen($out));
			$response = $this->readMessage();
			if(!$this->queryWasOk($response)) {
				return false;
			}
			$out = "serversnapshotdeploy ".$backup."\n";
			socket_write($this->conn, $out, strlen($out));
			$serverBackup = $this->readServerBackup();
			if(!$this->queryWasOk($serverBackup)) {
				return false;
			}
		}
		return true;
	}
	
	public function getServerBackup() {
		return $this->serverBackup;
	}
	
	public function setUsername($username="serveradmin") {
		$this->username = $username;
	}
	
	public function setPassword($password) {
		$this->password = $password;
	}
	
	private function stripStatus($response) {
		$response = str_replace("error id=0","",$response);
		$response = str_replace("msg=ok","",$response);
		return $response;
	}
	
	private function closeConnection() {
		socket_close($this->conn);
	}
	
	private function getRightServer() {
		$toReturn = "-1";
		$out = "serverlist\n";
		socket_write($this->conn, $out, strlen($out));
		$servers = explode("|",$this->readMessage());
		for($i=0;$i<count($servers);$i++) {
			if(strpos($servers[$i],$this->virtualServerPort) !== false) {
				$servers[$i] = trim(preg_replace('/\s\s+/', ' ', $servers[$i]));
				$server = str_split($servers[$i]);
				$k = 17;
				$toReturn = "";
				while($server[$k] != " ") {
					$toReturn += $server[$k];
					$k++;
				}
				return $toReturn;
			}
		}
		return $toReturn;
	}
	
	private function authenticate() {
		$out = "login ".$this->username." ".$this->password."\n";
		socket_write($this->conn, $out, strlen($out));
		$response = $this->readMessage();
		if($this->queryWasOk($response)) {
			return $this->loginWasOk($response);
		}else {
			return false;
		}
	}
	
	private function queryWasOk($response) {
		if(strpos($response,"error id=0") === false) {
			return false;
		}else {
			return true;
		}
	}
	
	private function loginWasOk($response) {
		if(strpos($response,"ok") === false) {
			return false;
		}else {
			return true;
		}
	}
	
	private function readMessage() {
		return socket_read($this->conn, 2048);
	}
	
	private function readServerBackup() {
		$data = "";
		do {
			$data .= socket_read($this->conn, 100000);
		}while(strpos($data, 'msg=') === false or strpos($data, 'error id=') === false);
		return $data;
	}
	
	private function readWelcomeMessage() {
		$response = socket_read($this->conn, 2048);
		return strpos($response,$this->WELCOMEMESSAGE) !== false;
	}
	
	private function connect() {
		$this->conn = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
		if ($this->conn=== false) {
			return false;
		}
		if(socket_connect($this->conn, $this->address, $this->serverqueryport) === false) {
			return false;
		}else {
			return true;
		}
	}	
}
?>

Falls noch Funktionen benötigt werden, dann scheut nicht hier einen Kommentar zu hinterlassen. Ich werde möglichst schnell die gewünschten Funktionen implementieren. Es lohnt sich aber einfach nicht für mich das Modul mit allen Funktionen die der Admin-Query von Teamspeak hergibt auszustatten (die mich Zeit kosten), um dann festzustellen, dass doch nicht alles benötigt wird.

In diesem Sinne wünsche ich viel Spaß damit! Bei Fragen, einfach fragen! 😉

Viele Grüße,

Barny

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

13 − zwölf =