Moritz 13 anos atrás
commit
7818dcf3bc
3 arquivos alterados com 341 adições e 0 exclusões
  1. 239 0
      PyTS3.py
  2. 64 0
      plaudereckenbot.py
  3. 38 0
      run.py

+ 239 - 0
PyTS3.py

@@ -0,0 +1,239 @@
+#!/usr/bin/python2.5
+# -*- coding: utf-8 -*-
+# Copyright (c) 2009 Christoph Heer (Christoph.Heer@googlemail.com)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the \"Software\"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import telnetlib
+import re
+import thread
+import time
+
+
+class TS3Error(Exception):
+
+    def __init__(self, code, msg):
+        self.code = code
+        self.msg = msg
+
+    def __str__(self):
+        return "ID %s (%s)" % (self.code, self.msg)
+
+
+class ServerQuery():
+    TSRegex = re.compile(r"(\w+)=(.*?)(\s|$|\|)")
+
+    def __init__(self, ip='127.0.0.1', query=10011):
+        """
+        This class contains functions to connecting a TS3 Query Port and send
+        command.
+        @param ip: IP adress of the TS3 Server
+        @type ip: str
+        @param query: Query Port of the TS3 Server. Default 10011
+        @type query: int
+        """
+        self.IP = ip
+        self.Query = int(query)
+        self.Timeout = 5.0
+
+    def connect(self):
+        """
+        Open a link to the Teamspeak 3 query port
+        @return: A tulpe with a error code. Example: ('error', 0, 'ok')
+        """
+        try:
+            self.telnet = telnetlib.Telnet(self.IP, self.Query)
+        except telnetlib.socket.error:
+            raise TS3Error(10, 'Can not open a link on the port or IP')
+        output = self.telnet.read_until('TS3', self.Timeout)
+        if output.endswith('TS3') == False:
+            raise TS3Error(20, 'This is not a Teamspeak 3 Server')
+        else:
+            return True
+
+    def disconnect(self):
+        """
+        Close the link to the Teamspeak 3 query port
+        @return: ('error', 0, 'ok')
+        """
+        self.telnet.write('quit \n')
+        self.telnet.close()
+        return True
+
+    def escaping2string(self, string):
+        """
+        Convert the escaping string form the TS3 Query to a human string.
+        @param string: A string form the TS3 Query with ecaping.
+        @type string: str
+        @return: A human string with out escaping.
+        """
+        string = str(string)
+        string = string.replace('\/', '/')
+        string = string.replace('\s', ' ')
+        string = string.replace('\p', '|')
+        string = string.replace('\n', '')
+        string = string.replace('\r', '')
+        try:
+            string = int(string)
+            return string
+        except ValueError:
+            ustring = unicode(string, "utf-8")
+            return ustring
+
+    def string2escaping(self, string):
+        """
+        Convert a human string to a TS3 Query Escaping String.
+        @param string: A normal/human string.
+        @type string: str
+        @return: A string with escaping of TS3 Query.
+        """
+        if type(string) == type(int()):
+            string = str(string)
+        else:
+            string = string.encode("utf-8")
+            string = string.replace('/', '\\/')
+            string = string.replace(' ', '\\s')
+            string = string.replace('|', '\\p')
+        return string
+
+    def command(self, cmd, parameter={}, option=[]):
+        """
+        Send a command with paramters and options to the TS3 Query.
+        @param cmd: The command who wants to send.
+        @type cmd: str
+        @param parameter: A dict with paramters and value.
+        Example: sid=2 --> {'sid':'2'}
+        @type cmd: dict
+        @param option: A list with options. Example: –uid --> ['uid']
+        @type option: list
+        @return: The answer of the server as tulpe with error code and message.
+        """
+        telnetCMD = cmd
+        for key in parameter:
+            telnetCMD += " %s=%s" % (key, self.string2escaping(parameter[key]))
+        for i in option:
+            telnetCMD += " -%s" % (i)
+        telnetCMD += '\n'
+        self.telnet.write(telnetCMD)
+
+        telnetResponse = self.telnet.read_until("msg=ok", self.Timeout)
+        telnetResponse = telnetResponse.split(r'error id=')
+        notParsedCMDStatus = "id=" + telnetResponse[1]
+        notParsedInfo = telnetResponse[0].split('|')
+
+        if (cmd.endswith("list") == True) or (len(notParsedInfo) > 1):
+            returnInfo = []
+            for notParsedInfoLine in notParsedInfo:
+                ParsedInfo = self.TSRegex.findall(notParsedInfoLine)
+                ParsedInfoDict = {}
+                for ParsedInfoKey in ParsedInfo:
+                    ParsedInfoDict[ParsedInfoKey[0]] = self.escaping2string(
+                        ParsedInfoKey[1])
+                returnInfo.append(ParsedInfoDict)
+
+        else:
+            returnInfo = {}
+            ParsedInfo = self.TSRegex.findall(notParsedInfo[0])
+            for ParsedInfoKey in ParsedInfo:
+                returnInfo[ParsedInfoKey[0]] = self.escaping2string(
+                    ParsedInfoKey[1])
+
+        ReturnCMDStatus = {}
+        ParsedCMDStatus = self.TSRegex.findall(notParsedCMDStatus)
+        for ParsedCMDStatusLine in ParsedCMDStatus:
+            ReturnCMDStatus[ParsedCMDStatusLine[0]] = self.escaping2string(
+                ParsedCMDStatusLine[1])
+        if ReturnCMDStatus['id'] != 0:
+            raise TS3Error(ReturnCMDStatus['id'], ReturnCMDStatus['msg'])
+
+        return returnInfo
+
+
+class ServerNotification(ServerQuery):
+    def __init__(self, ip='127.0.0.1', query=10011):
+        """
+        This class contains functions to work with the
+        ServerNotification of TS3.
+        @param ip: IP adress of the TS3 Server
+        @type ip: str
+        @param query: Query Port of the TS3 Server. Default 10011
+        @type query: int
+        """
+        self.IP = ip
+        self.Query = int(query)
+        self.Timeout = 5.0
+        self.LastCommand = 0
+
+        self.Lock = thread.allocate_lock()
+        self.RegistedNotifys = []
+        self.RegistedEvents = []
+        thread.start_new_thread(self.worker, ())
+
+    def worker(self):
+        while True:
+            self.Lock.acquire()
+            RegistedNotifys = self.RegistedNotifys
+            LastCommand = self.LastCommand
+            self.Lock.release()
+            if len(RegistedNotifys) == 0:
+                continue
+            if LastCommand < time.time() - 180:
+                self.command('version')
+                self.Lock.acquire()
+                self.LastCommand = time.time()
+                self.Lock.release()
+            telnetResponse = self.telnet.read_until("\n", 0.1)
+            if telnetResponse.startswith('notify'):
+                notifyName = telnetResponse.split(' ')[0]
+                ParsedInfo = self.TSRegex.findall(telnetResponse)
+                notifyData = {}
+                for ParsedInfoKey in ParsedInfo:
+                    notifyData[ParsedInfoKey[0]] = self.escaping2string(
+                        ParsedInfoKey[1])
+                for RegistedNotify in RegistedNotifys:
+                    if RegistedNotify['notify'] == notifyName:
+                        RegistedNotify['func'](notifyName, notifyData)
+            time.sleep(0.2)
+
+    def registerNotify(self, notify, func):
+        notify2func = {'notify': notify, 'func': func}
+
+        self.Lock.acquire()
+        self.RegistedNotifys.append(notify2func)
+        self.LastCommand = time.time()
+        self.Lock.release()
+
+    def unregisterNotify(self, notify, func):
+        notify2func = {'notify': notify, 'func': func}
+
+        self.Lock.acquire()
+        self.RegistedNotifys.remove(notify2func)
+        self.LastCommand = time.time()
+        self.Lock.release()
+
+    def registerEvent(self, eventName, parameter={}, option=[]):
+        parameter['event'] = eventName
+        self.RegistedEvents.append(eventName)
+        self.command('servernotifyregister', parameter, option)
+        self.Lock.acquire()
+        self.LastCommand = time.time()
+        self.Lock.release()
+
+    def unregisterEvent(self):
+        self.command('servernotifyunregister')

+ 64 - 0
plaudereckenbot.py

@@ -0,0 +1,64 @@
+#!/usr/bin/python
+import os
+try:
+    import PyTS3
+except:
+    print "PyTS3 not found. Aborting"
+    os._exit(7)
+
+
+class pBot:
+    def __init__(self, ip, port, username, password, sid, channellist, cpid):
+        self.ip = ip
+        self.port = port
+        self.username = username
+        self.password = password
+        self.sid = sid
+        self.channellist = channellist
+        self.cpid = cpid
+        self.connect(ip, port, username, password, sid)
+
+    def connect(self, ip, port, username, password, sid):
+        self.teamspeak = PyTS3.ServerQuery(ip, port)
+        if self.teamspeak.connect() == False:
+            print "Could not connect"
+            os._exit(7)
+        self.teamspeak.command("login " + username + " " + password)
+        self.teamspeak.command("use " + str(sid))
+
+    def getUserInfo(self):
+        self.userInfo = self.teamspeak.command("clientlist")
+        self.userInfoArray = list()
+        for i in range(len(self.userInfo)):
+            if(self.userInfo[i]['cid'] == 152):
+                self.userInfoArray.append(self.userInfo[i]['clid'])
+
+    def getChannelUsers(self, cid):
+        x = self.teamspeak.command("channellist")
+        for i in range(len(x)):
+            if(x[i]['cid'] in self.channellist):
+                if(x[i]['cid'] == cid):
+                    return x[i]['total_clients']
+
+    def addChannel(self):
+        #print str(self.channellist[len(self.channellist) - 1])
+        y = str("channelcreate channel_name=Plauderecke\s"
+         + str(len(self.channellist) + 1) + " channel_order="
+         + str(self.channellist[len(self.channellist) - 1]) + "")
+        print y
+        x = self.teamspeak.command("channelcreate channel_name=Plauderecke\s"
+        + str(len(self.channellist) + 1) + " channel_order="
+        + str(self.channellist[len(self.channellist) - 1]) +
+        " cpid=" + str(self.cpid) + " channel_flag_semi_permanent=1 CHANNEL CODEC")
+        print x
+        if isinstance(x['cid'], int):
+            self.channellist.append(x['cid'])
+        print self.channellist
+        #print x  # dbg
+
+    def delChannel(self, cid):
+        print "deleteChannel: " + str(cid) + " "
+        x = self.teamspeak.command("channeldelete cid=" + str(cid) + " force=1")
+        self.channellist.remove(cid)
+        print x
+        #  nothing

+ 38 - 0
run.py

@@ -0,0 +1,38 @@
+#!/usr/bin/python
+import plaudereckenbot
+import time
+IP = ""
+PORT = 10011
+USERNAME = "serveradmin"
+PASSWORD = ""
+SID = 1
+ORIGINALCHANNELS = []
+CHANNELLIST = [] # == ORIGINALCHANNELS
+CPID = 54
+pBot = plaudereckenbot.pBot(IP, PORT, USERNAME, PASSWORD,
+     SID, CHANNELLIST, CPID)
+while 1:
+    emptyRooms = 0
+    pBot.getUserInfo()
+    channelUserCount = list()
+    print "userInfo: " + str(pBot.userInfoArray)
+    for i in range(len(pBot.channellist)):
+        channelUserCount.append(pBot.getChannelUsers(pBot.channellist[i]))
+    for i in range(len(channelUserCount)):
+        if(channelUserCount[i] > 0):
+            channelUserCount[i] = True
+        else:
+            emptyRooms = emptyRooms + 1
+    print "ChanUserCount: " + str(channelUserCount)
+    print "lenSetUserCount: " + str(len(set(channelUserCount)) == 1
+        and channelUserCount[0] == True)
+    if len(set(channelUserCount)) == 1 and channelUserCount[0] == True:
+        pBot.addChannel()
+    print "emptyRooms: " + str(emptyRooms)
+    if emptyRooms > 1:
+        for i in reversed(range(len(pBot.channellist))):
+            if channelUserCount[i] == 0:
+                if pBot.channellist[i] not in ORIGINALCHANNELS:
+                    pBot.delChannel(pBot.channellist[i])
+                    break
+    time.sleep(5)