예제 #1
0
class gommeChecker(ts3plugin):
    name = "Gomme Checker"

    apiVersion = 22
    requestAutoload = False
    version = "1.0"
    author = "Bluscream"
    description = "Obwohl ich die meisten Gomme mods hasse ♥"
    offersConfigure = False
    commandKeyword = ""
    infoTitle = None
    iconPath = path.join(getPluginPath(), "scripts", "gommeChecker", "icons")
    menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Check all Channels", ""), (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 1, "Open Support", ""), (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 2, "Close Support", "")]
    hotkeys = []
    ini = path.join(getPluginPath(), "scripts", "gommeChecker", "settings.ini")
    cfg = ConfigParser()
    supchans = []
    supmain = 0

    @staticmethod
    def timestamp(): return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now())

    def __init__(self):
        if path.isfile(self.ini):
            self.cfg.read(self.ini)
        else:
            self.cfg['general'] = {"cfgversion": "1", "debug": "False", "enabled": "False", "uid": "QTRtPmYiSKpMS8Oyd4hyztcvLqU="}
            with open(self.ini, 'w') as configfile:
                self.cfg.write(configfile)
        if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab("{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded.".format(self.timestamp(),self.name,self.author))

    def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
        if atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL:
            if menuItemID == 0:
                self.dlg = CheckerDialog(self)
                self.dlg.show()
            elif menuItemID == 1: pass

    def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber):
        if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED:
            (error, uid) = ts3lib.getServerVariableAsString(schid, ts3defines.VirtualServerProperties.VIRTUALSERVER_UNIQUE_IDENTIFIER)
            if uid == self.cfg.get("general", "uid"):
                # ts3lib.getChannelIDFromChannelNames(serverConnectionHandlerID, channelNameArray)
                (error, clist) = ts3lib.getChannelList(schid)
                for c in clist:
                    (error, permanent) = ts3lib.getChannelVariableAsInt(schid, c, ts3defines.ChannelProperties.CHANNEL_FLAG_PERMANENT)
                    if permanent:
                        (error, name) = ts3lib.getChannelVariableAsString(schid, c, ts3defines.ChannelProperties.CHANNEL_NAME)
                        if name.startswith("Support "):
                            self.supchans.append(c)
                        elif name.startswith("[cspacer10]● Support"):
                            self.supmain = c
                self.cfg.set("general", "enabled", "True")
            else: self.cfg.set("general", "enabled", "False")
예제 #2
0
파일: devtools.py 프로젝트: pathmann/pyTSon
def installedPackages():
    """
    Returns a list of installed packages (installed with pip).
    @returns: a list of dictionaries containing name, version,
    directory (dir) and dist-info directory (distdir)
    @rtype: list[dict{str: str}]
    """
    # pip list (or freeze) does not work with the --target option, so
    # we have to collect the packages manually
    ret = []
    inclpath = pytson.getPluginPath("include")
    for d in glob.glob(os.path.join(inclpath, "*.dist-info/")):
        mfile = os.path.join(d, "metadata.json")
        if os.path.isfile(mfile):
            with open(mfile, "r") as f:
                metadata = json.load(f)

            name = metadata["name"]
            version = metadata["version"]

            tlf = os.path.join(d, "top_level.txt")
            if os.path.isfile(tlf):
                with open(tlf, "r") as f:
                    tld = f.read().strip()

                ret.append({"name": name, "version": version,
                            "dir": os.path.join(inclpath, tld),
                            "distdir": d})

    return ret
예제 #3
0
파일: devtools.py 프로젝트: pathmann/pyTSon
def removePackage(name, version):
    """
    Removes a package (installed with pip). Throws an exception if the
    package could not be found
    @param name: the name of the package
    @type name: str
    @param version: the version string of the package
    @type version: str
    """
    inclpath = pytson.getPluginPath("include")

    distdir = os.path.join(inclpath, "%s-%s.dist-info" % (name, version))
    if not os.path.isdir(distdir):
        raise Exception("dist-info directory not found")

    tlf = os.path.join(distdir, "top_level.txt")
    if not os.path.isfile(tlf):
        raise Exception("top_level.txt not found")

    with open(tlf, "r") as f:
        tld = f.read().strip()

    packdir = os.path.join(inclpath, tld)
    if not os.path.isdir(packdir):
        raise Exception("package directory not found")

    shutil.rmtree(packdir)
    shutil.rmtree(distdir)
예제 #4
0
 def __init__(self, parent=None):
     try:
         super(QWidget, self).__init__(parent)
         setupUi(self, path.join(pytson.getPluginPath(), "scripts", "queryConsole", "console.ui"))
         self.setAttribute(Qt.WA_DeleteOnClose)
         self.setWindowTitle("Query Console")
     except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
예제 #5
0
 def __init__(self, schid, cgid, dbid, name, channel, groups, parent=None):
     try:
         super(QDialog, self).__init__(parent)
         setupUi(self, path.join(getPluginPath(), "scripts", "channelGroupChanger", "channelGroupSelect.ui"))
         self.setAttribute(Qt.WA_DeleteOnClose)
         self.setWindowTitle("%s | %i"%(name,channel))
         cache = False
         try:
             icons = IconPack.current()
             icons.open()
             cache = ServerCache(schid)
         except: from traceback import format_exc;ts3lib.logMessage("Could not load icons: {}".format(format_exc()), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
         # self.channelGroups.addItems(list(groups.values()))
         self.channelGroups.clear()
         for key,p in groups.items():
             try:
                 item = QListWidgetItem(self.channelGroups)
                 item.setText(p[0])
                 item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                 item.setCheckState(Qt.Checked if key == cgid else Qt.Unchecked)
                 item.setData(Qt.UserRole, key)
                 if (cache):
                     try:
                         if p[1] == 0: continue;
                         elif p[1] in range(100, 700, 100):
                             item.setIcon(QIcon(IconPack.icon(icons,"group_{}".format(p[1]))))
                         else: item.setIcon(QIcon(ServerCache.icon(cache,p[1]&0xFFFFFFFF)))
                     except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
             except: from traceback import format_exc;ts3lib.logMessage("Could set icon: {}".format(format_exc()), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
         icons.close()
         # self.channelGroups.sortItems()
         self.channelGroups.connect("itemChanged(QListWidgetItem*)", self.onSelectedChannelGroupChangedEvent)
         self.schid = schid;self.dbid = dbid;self.channel = channel
     except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0);pass
예제 #6
0
파일: devtools.py 프로젝트: pathmann/pyTSon
    def createPlugin(name, withfile=True, content=None):
        """
        Creates the infrastructure for a new plugin.
        @param name: the name of the plugin
        @type name: str
        @param withfile: if True, the file __init__.py is created in the plugin
        directory, defaults to True
        @type withfile: bool
        @param content: content of __ini__.py; defaults to None; if None, an
        empty plugin skeleton is written to the file (if withfile is True)
        @type content: str
        @return: the path to the __init__.py of the new created plugin
        @rtype: str
        """
        ename = PluginInstaller._escapeString(name)

        p = pytson.getPluginPath("scripts", ename)
        if os.path.isdir(p):
            raise Exception("Directory already exist")

        os.mkdir(p)

        fp = os.path.join(p, "__init__.py")
        if withfile:
            with open(fp, "w") as f:
                if content:
                    f.write(content)
                else:
                    f.write(PluginInstaller.PLUGIN_SKELETON % (ename, ename))

        return fp
예제 #7
0
 def __init__(self, addons, name, cfg, parent=None):
     try:
         super(QWidget, self).__init__(parent)
         setupUi(
             self,
             path.join(pytson.getPluginPath(), "scripts", "addonList",
                       "addons.ui"))
         self.cfg = cfg
         self.setAttribute(Qt.WA_DeleteOnClose)
         self.setWindowTitle("{0}'s Addons".format(name))
         self.txt_description.setVisible(False)
         self.tbl_addons.horizontalHeader().setSectionResizeMode(
             0, QHeaderView.Stretch)
         self.tbl_addons.horizontalHeader().setSectionResizeMode(
             2, QHeaderView.Stretch)
         self.setupList(addons.getchildren())
         self.resize(1000, 600)
         self.adddons = addons
     except:
         try:
             from traceback import format_exc
             ts3.logMessage("addonList: " + format_exc(),
                            ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
         except:
             try:
                 from traceback import format_exc
                 print("addonList: " + format_exc())
             except:
                 print("addonList: Unknown Error")
예제 #8
0
class purgeContacts(ts3plugin):
    name = "Purge Contacts"
    try: apiVersion = getCurrentApiVersion()
    except: apiVersion = 21
    requestAutoload = True
    version = "1"
    author = "Bluscream"
    description = "Allows you to clean your contact list "
    offersConfigure = False
    commandKeyword = ""
    infoTitle = ""
    menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, name, "")]
    hotkeys = []
    scriptpath = path.join(getPluginPath(), "scripts", "purgeContacts")
    dlg = None

    def __init__(self):
        if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab("{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded.".format(timestamp(), self.name, self.author))

    def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
        if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL or menuItemID != 0: return
        self.dlg = calendarDialog(self)
        self.dlg.show()
        self.dlg.raise_()
        self.dlg.activateWindow()
예제 #9
0
 def __init__(self, this, parent=None):
     self.this = this
     super(QDialog, self).__init__(parent)
     setupUi(
         self,
         path.join(pytson.getPluginPath(), "scripts", "NoX", "settings.ui"))
     self.setWindowTitle("%s Settings" % this.name)
     self.chk_debug.setChecked(this.cfg.getboolean("general", "debug"))
예제 #10
0
 def __init__(self, schid, uids, parent=None):
     try:
         self.schid = schid;self.uids = uids
         super(QDialog, self).__init__(parent)
         setupUi(self, path.join(pytson.getPluginPath(), "scripts", "onlineOfflineMessages", "message.ui"))
         self.setAttribute(Qt.WA_DeleteOnClose)
         self.setWindowTitle("Offline Message to {0} clients.".format(len(uids)))
     except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
예제 #11
0
 def __init__(self, plugin, parent=None):
     try:
         # self.schid = schid;self.uids = uids
         super(QDialog, self).__init__(parent)
         setupUi(self, os.path.join(pytson.getPluginPath(), "scripts", "passwordCracker", "status.ui"))
         self.setAttribute(Qt.WA_DeleteOnClose)
         self.setWindowTitle('{0} - Idle'.format(plugin.name))
     except: from traceback import format_exc;ts3lib.logMessage(format_exc(), LogLevel.LogLevel_ERROR, "pyTSon", 0)
예제 #12
0
    def __init__(self, localfile, remotefile, isdownload, multi, parent=None):
        """
        Instantiates a new dialog.
        @param localfile: the path to the local file
        @type localfile: str
        @param remotefile: the remote file
        @type remotefile: File
        @param isdownload: set to True if remotefile should be downloaded
        @type isdownload: bool
        @param multi: set to True, if there are multiple files which could
        collide
        @type multi: bool
        @param parent: parent widget of the dialog; optional; defaults to None
        @type parent: QWidget
        """
        super(QDialog, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        try:
            setupUi(self, pytson.getPluginPath("ressources",
                                               "filecollision.ui"))
        except Exception as e:
            self.delete()
            raise e

        if not multi:
            self.multiButton.setVisible(False)
            self.skipallButton.setVisible(False)

        locsize = os.path.getsize(localfile)
        if locsize == remotefile.size:
            self.resumeButton.hide()

            self.actionLabel.text = self._tr("Do you want to overwrite the "
                                             "existing file")
        else:
            self.actionLabel.text = self._tr("Do you want to overwrite or "
                                             "resume the existing file")

        self.filenameLabel.text = "<b>%s</b>" % remotefile.name

        datefmt = pytson.tr("filetransfer", "%Y-%m-%d %H:%M:%S")
        locdate = datetime.fromtimestamp(os.path.getmtime(localfile))
        filefmt = "Size: <b>%s</b><br />Date: <b>%s</b>"

        locstr = filefmt % (bytesToStr(locsize), locdate.strftime(datefmt))
        remstr = filefmt % (bytesToStr(
            remotefile.size), remotefile.datetime.strftime(datefmt))

        if isdownload:
            self.existingLabel.text = locstr
            self.newLabel.text = remstr
        else:
            self.existingLabel.text = remstr
            self.newLabel.text = locstr

        self.adjustSize()
예제 #13
0
    def __init__(self, localfile, remotefile, isdownload, multi, parent=None):
        """
        Instantiates a new dialog.
        @param localfile: the path to the local file
        @type localfile: str
        @param remotefile: the remote file
        @type remotefile: File
        @param isdownload: set to True if remotefile should be downloaded
        @type isdownload: bool
        @param multi: set to True, if there are multiple files which could
        collide
        @type multi: bool
        @param parent: parent widget of the dialog; optional; defaults to None
        @type parent: QWidget
        """
        super(QDialog, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        try:
            setupUi(self, pytson.getPluginPath("ressources",
                                               "filecollision.ui"))
        except Exception as e:
            self.delete()
            raise e

        if not multi:
            self.multiButton.setVisible(False)
            self.skipallButton.setVisible(False)

        locsize = os.path.getsize(localfile)
        if locsize == remotefile.size:
            self.resumeButton.hide()

            self.actionLabel.text = self._tr("Do you want to overwrite the "
                                             "existing file")
        else:
            self.actionLabel.text = self._tr("Do you want to overwrite or "
                                             "resume the existing file")

        self.filenameLabel.text = "<b>%s</b>" % remotefile.name

        datefmt = pytson.tr("filetransfer", "%Y-%m-%d %H:%M:%S")
        locdate = datetime.fromtimestamp(os.path.getmtime(localfile))
        filefmt = "Size: <b>%s</b><br />Date: <b>%s</b>"

        locstr = filefmt % (bytesToStr(locsize), locdate.strftime(datefmt))
        remstr = filefmt % (bytesToStr(remotefile.size),
                            remotefile.datetime.strftime(datefmt))

        if isdownload:
            self.existingLabel.text = locstr
            self.newLabel.text = remstr
        else:
            self.existingLabel.text = remstr
            self.newLabel.text = locstr

        self.adjustSize()
예제 #14
0
class nameSwitcher(ts3plugin):
    name = "Name Switcher"
    try: apiVersion = getCurrentApiVersion()
    except: apiVersion = 21
    requestAutoload = False
    version = "1.0"
    author = "Bluscream"
    description = ""
    offersConfigure = False
    commandKeyword = ""
    infoTitle = None
    menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Toggle " + name, "")]
    hotkeys = []
    timer = QTimer()
    interval = 1 * 1000 * 60
    prefix = "Danny"
    suffixes = path.join(getPluginPath(), "scripts", "nameSwitcher", "suffixes.txt")
    last = ""
    schid = 0
    retcode = ""

    def __init__(self):
        self.timer.timeout.connect(self.tick)
        self.timer.setTimerType(2)
        with open(self.suffixes) as f:
            self.suffixes = f.read().splitlines()
        if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab("{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded.".format(timestamp(), self.name, self.author))

    def stop(self):
        if self.timer.isActive(): self.timer.stop()

    def tick(self):
        new = choice(self.suffixes)
        while new == self.last: new = choice(self.suffixes)
        ts3lib.setClientSelfVariableAsString(self.schid, ts3defines.ClientProperties.CLIENT_NICKNAME, self.prefix + new)
        self.retcode = ts3lib.createReturnCode()
        ts3lib.flushClientSelfUpdates(self.schid, self.retcode)
        self.last = new

    def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
        if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL or menuItemID != 0: return
        if self.timer.isActive(): self.timer.stop()
        else:
            self.schid = schid
            self.timer.start(self.interval)
            self.tick()

    def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber):
        if newStatus == ts3defines.ConnectStatus.STATUS_DISCONNECTED:
            if self.timer.isActive(): self.timer.stop()

    def onServerErrorEvent(self, schid, errorMessage, error, returnCode, extraMessage):
        if returnCode != self.retcode: return
        self.retcode = ""
        if error == ts3defines.ERROR_client_nickname_inuse: self.tick()
        return True
예제 #15
0
파일: devtools.py 프로젝트: pathmann/pyTSon
 def removePlugin(name):
     """
     Uninstall a plugin (delete all data in scripts directory).
     @param name: the name of the plugin
     @type name: str
     """
     ename = PluginInstaller._escapeString(name)
     p = pytson.getPluginPath("scripts", ename)
     if os.path.isdir(p):
         shutil.rmtree(p)
예제 #16
0
class dataChanger(ts3plugin):
    name = "Name Changer"

    apiVersion = 22
    requestAutoload = False
    version = "1.0"
    author = "Bluscream"
    description = "Changes what you want after a preiod of time."
    offersConfigure = False
    commandKeyword = ""
    infoTitle = None
    menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0,
                  "Nickname changer", "")]
    hotkeys = []
    debug = False
    ini = path.join(getPluginPath(), "scripts", "dataChanger", "settings.ini")
    cfg = ConfigParser()
    dlg = None
    int = 0

    def timestamp(self):
        return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now())

    def __init__(self):
        if path.isfile(self.ini): self.cfg.read(self.ini)
        else:
            self.cfg['general'] = {
                "cfgversion": "1",
                "debug": "False",
                "enabled": "True"
            }
            with open(self.ini, 'w') as configfile:
                self.cfg.write(configfile)
        if self.debug:
            ts3lib.printMessageToCurrentTab(
                "{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded."
                .format(self.timestamp(), self.name, self.author))

    def onMenuItemEvent(self, serverConnectionHandlerID, atype, menuItemID,
                        selectedItemID):
        if atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL:
            if menuItemID == 0:
                timer = QTimer(self)
                connect(
                    timer, SIGNAL(timeout()), this,
                    SLOT(
                        self.changeName(serverConnectionHandlerID,
                                        names[self.i])))
                timer.start(5000)

    def changeName(self, schid, name=""):
        ts3lib.setClientSelfVariableAsString(
            schid, ts3defines.ClientProperties.CLIENT_NICKNAME, name)
        ts3lib.flushClientSelfUpdates(schid)
예제 #17
0
    def __init__(self, host, parent=None):
        super(QDialog, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.host = host

        self.pending = 0

        try:
            with open(pytson.getConfigPath("repositorymaster.json"), "r") as f:
                repmaster = json.loads(f.read())
                self.replist = {x["name"]: x for x in repmaster}
        except:
            ts3print(self._tr("Error opening repositorymaster"),
                     ts3defines.LogLevel.LogLevel_ERROR,
                     "pyTSon.RepositoryDialog", 0)
            raise Exception("Error opening repositorymaster")

        try:
            setupUi(self, pytson.getPluginPath("ressources", "repository.ui"))
            self.updateMasterlist()

            movie = QMovie(pytson.getPluginPath("ressources", "loading.gif"),
                           "", self)
            movie.start()
            self.loadingLabel.setMovie(movie)

            self.masterloadingLabel.setMovie(movie)
            self.masterloadingLabel.hide()

            self.nwm = QNetworkAccessManager(self)
            self.nwm.connect("finished(QNetworkReply*)", self.onNetworkReply)

            self.updateRepositories()

            self.connect("finished(int)", self.onClosed)
        except Exception as e:
            self.delete()
            raise e
예제 #18
0
 def __init__(self, Class, parent=None):
     self.dynamicAvatar = Class
     super(QDialog, self).__init__(parent)
     setupUi(
         self,
         path.join(getPluginPath(), "scripts", "dynamicAvatar",
                   "settings.ui"))
     s = Class.config["GENERAL"]
     b = self.buhl
     self.url.setChecked(s["mode"] == "url")
     self.path.setChecked(s["mode"] == "path")
     self.imgurl.setText(s["imgurl"])
     self.imgpath.setText(s["imgpath"])
     self.debug.setChecked(b(s["debug"]))
     self.refresh.setValue(int(s["refresh"]))
예제 #19
0
    def showChangelog(cls):
        fname = pytson.getPluginPath("Changelog.html")
        if not os.path.isfile(fname):
            QMessageBox.critical(None, cls._tr("Error"), cls._tr("Can't find "
                                                                 "Changelog"))
            return

        with open(fname, "r") as f:
            # store it just to keep it in scope
            cls.viewer = viewer = QTextBrowser()
            viewer.setAttribute(Qt.WA_DeleteOnClose)
            viewer.openExternalLinks = True
            viewer.setHtml(f.read())

            viewer.show()
예제 #20
0
    def showChangelog(cls):
        fname = pytson.getPluginPath("Changelog.html")
        if not os.path.isfile(fname):
            QMessageBox.critical(None, cls._tr("Error"),
                                 cls._tr("Can't find "
                                         "Changelog"))
            return

        with open(fname, "r") as f:
            # store it just to keep it in scope
            cls.viewer = viewer = QTextBrowser()
            viewer.setAttribute(Qt.WA_DeleteOnClose)
            viewer.openExternalLinks = True
            viewer.setHtml(f.read())

            viewer.show()
예제 #21
0
 def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
     try:
         if menuItemID == 0:
             pluginPath = pytson.getPluginPath("scripts", self.name)
             mainWindow = [
                 item for item in QApplication.instance().topLevelWidgets()
                 if type(item).__name__ == "MainWindow"
             ][0]
             if not mainWindow:
                 return
             mainWindow.setWindowIcon(
                 QIcon(os.path.join(pluginPath, "small.ico")))
     except:
         from traceback import format_exc
         ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR,
                           "pyTSon", 0)
예제 #22
0
    def reload(cls):
        cls.verboseLog(cls._tr("Reloading plugins"),
                       "pyTSon.PluginHost.reload")
        # stop all running modules
        for key, p in cls.active.items():
            try:
                p.stop()
            except:
                logprint(cls._tr("Error stopping python plugin {name}: "
                                 "{trace}").format(name=key,
                                                   trace=traceback.
                                                   format_exc()),
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.reload")

        cls.active = {}
        cls.plugins = {}

        # import all modules
        spath = pytson.getPluginPath("scripts")
        for d in glob.glob(os.path.join(spath, "*/")):
            if not os.path.isdir(d):
                continue

            base = os.path.relpath(d, spath)
            try:
                if base in cls.modules:
                    cls.modules[base] = importlib.reload(cls.modules[base])
                else:
                    cls.modules[base] = importlib.__import__(base)
            except:
                logprint(cls._tr(
                         "Error loading python plugin from {path}: {trace}").
                         format(path=d, trace=traceback.format_exc()),
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.reload")

        # save local menu ids
        for globid, (p, locid) in cls.menus.items():
            # previously reloaded?
            if not type(p) is str:
                cls.menus[globid] = (p.name, locid)

        # save local hotkeys
        for keyword, (p, lockey) in cls.hotkeys.items():
            if not type(p) is str:
                cls.hotkeys[keyword] = (p.name, lockey)
예제 #23
0
    def reload(cls):
        cls.verboseLog(cls._tr("Reloading plugins"),
                       "pyTSon.PluginHost.reload")
        # stop all running modules
        for key, p in cls.active.items():
            try:
                p.stop()
            except:
                logprint(
                    cls._tr("Error stopping python plugin {name}: "
                            "{trace}").format(name=key,
                                              trace=traceback.format_exc()),
                    ts3defines.LogLevel.LogLevel_ERROR,
                    "pyTSon.PluginHost.reload")

        cls.active = {}
        cls.plugins = {}

        # import all modules
        spath = pytson.getPluginPath("scripts")
        for d in glob.glob(os.path.join(spath, "*/")):
            if not os.path.isdir(d):
                continue

            base = os.path.relpath(d, spath)
            try:
                if base in cls.modules:
                    cls.modules[base] = importlib.reload(cls.modules[base])
                else:
                    cls.modules[base] = importlib.__import__(base)
            except:
                logprint(
                    cls._tr("Error loading python plugin from {path}: {trace}"
                            ).format(path=d, trace=traceback.format_exc()),
                    ts3defines.LogLevel.LogLevel_ERROR,
                    "pyTSon.PluginHost.reload")

        # save local menu ids
        for globid, (p, locid) in cls.menus.items():
            # previously reloaded?
            if not type(p) is str:
                cls.menus[globid] = (p.name, locid)

        # save local hotkeys
        for keyword, (p, lockey) in cls.hotkeys.items():
            if not type(p) is str:
                cls.hotkeys[keyword] = (p.name, lockey)
예제 #24
0
class dataDump(ts3plugin):
    name = "Data Dump"
    apiVersion = 22
    requestAutoload = False
    version = "1.0"
    author = "Bluscream"
    description = "Dump any data"
    offersConfigure = True
    commandKeyword = ""
    infoTitle = None
    menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0,
                  "Data Dumps", "")]
    hotkeys = []
    ini = path.join(pytson.getPluginPath(), "scripts", "dataDump",
                    "settings.ini")
    cfg = ConfigParser()
    dlg = None

    def timestamp(self):
        return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now())

    def __init__(self):
        if path.isfile(self.ini):
            self.cfg.read(self.ini)
        else:
            self.cfg['general'] = {
                "cfgversion": "1",
                "debug": "False",
                "enabled": "True",
                "infodata": "False",
                "activeonly": "False"
            }
            with open(self.ini, 'w') as cfg:
                self.cfg.write(cfg)
        schid = ts3.getCurrentServerConnectionHandlerID()
        err, ownid = ts3.getClientID(schid)
        # if not err: self.setMeta(ts3.getCurrentServerConnectionHandlerID())
        if self.cfg.getboolean("general", "debug"):
            ts3.printMessageToCurrentTab(
                "{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded."
                .format(self.timestamp(), self.name, self.author))

    def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber):
        pass  # if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED: self.setMeta(schid)

    """
예제 #25
0
    def __init__(self, schid, cid, password, parent=None):
        super(QDialog, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        try:
            setupUi(self, pytson.getPluginPath("ressources",
                                               "filetransfer.ui"))

            self.delegate = FileTransferDelegate(self)
            self.table.setItemDelegate(self.delegate)

            self.model = FileTransferModel(schid, cid, password, self)
            self.table.setModel(self.model)
        except Exception as e:
            self.delete()
            raise e

        self.resize(770, 250)
예제 #26
0
    def __init__(self, schid, cid, password, parent=None):
        super(QDialog, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        try:
            setupUi(self, pytson.getPluginPath("ressources",
                                               "filetransfer.ui"))

            self.delegate = FileTransferDelegate(self)
            self.table.setItemDelegate(self.delegate)

            self.model = FileTransferModel(schid, cid, password, self)
            self.table.setModel(self.model)
        except Exception as e:
            self.delete()
            raise e

        self.resize(770, 250)
예제 #27
0
    def __init__(self, host, parent=None):
        super(QDialog, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setModal(True)

        self.host = host
        self.addon = None

        try:
            setupUi(self, pytson.getPluginPath("ressources", "installer.ui"))

            self.pip = devtools.PluginInstaller(self.consoleEdit.append)
            self.nwm = QNetworkAccessManager(self)
            self.nwm.connect("finished(QNetworkReply*)", self.onNetworkReply)

            self.closeFrame.hide()
        except Exception as e:
            self.delete()
            raise e
예제 #28
0
    def setupTranslator(cls):
        lang = cls.cfg.get("general", "language")
        if lang == "inherited":
            ccfg = ts3client.Config()
            q = ccfg.query("SELECT * FROM application WHERE key='Language'")

            if q.next():
                lang = q.value("value")
            else:
                lang = "en_US"
                logprint(cls._tr("Error querying language from client config"),
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
            del ccfg

        if cls.translator:
            if not QCoreApplication.removeTranslator(cls.translator):
                logprint(cls._tr("Error removing translator"),
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
            cls.translator = None

        p = pytson.getPluginPath("ressources", "i18n", "pyTSon-%s.qm" % lang)

        if os.path.isfile(p):
            cls.verboseLog(
                cls._tr("Using translator from {file}").format(file=p),
                "pyTSon.PluginHost.setupTranslator")

            cls.translator = QTranslator()
            if not cls.translator.load(p):
                logprint("Error loading translator from %s" % p,
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
                cls.translator = None
                return

            if not QCoreApplication.installTranslator(cls.translator):
                logprint("Error installing translator from %s" % p,
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
                cls.translator = None
예제 #29
0
파일: devtools.py 프로젝트: pathmann/pyTSon
    def installPackages(self, deps):
        """
        Installs packages from pypi.python.org into the include directory.
        @param deps: A list of package names
        @type deps: list[str]
        @return: True on success, False otherwise
        @rtype: bool
        """
        p = subprocess.Popen([sys.executable, "-m", "pip", "install",
                              "--target", pytson.getPluginPath("include")] +
                             deps, stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        out, err = p.communicate()

        if err:
            self._print(err)
        if out:
            self._print(out)

        return p.returncode == 0
예제 #30
0
 def __init__(self):
     self.installer = PluginInstaller(self.print_msg)
     # if self.auto_update_pip: self.to_install.append("--upgrade pip")
     _installed = installedPackages()
     installed = []
     for package in _installed:
         name = package["name"]
         if not name in installed: installed.append(name)
     """
     dir = listdir(getPluginPath("scripts"))
     print(dir)
     """
     # noinspection PyTypeChecker
     for subdir, dirs, files in walklevel(getPluginPath("scripts"), 1):
         for file in files:
             file_lower = file.lower()
             if not file_lower.endswith(".txt"): continue
             if file_lower == "requirements.txt":
                 requirements = []
                 # noinspection PyArgumentList
                 with open(path.join(subdir, file), encoding="utf-8") as f:
                     requirements = [line.strip() for line in f.readlines()]
                 if len(requirements) < 1: continue
                 for requirement in requirements:
                     requirement_stripped = self.strip(requirement)
                     if requirement in self.to_install: continue
                     if requirement_stripped in installed: continue
                     try:
                         __import__(requirement_stripped)
                     except ImportError:
                         self.to_install.append(requirement)
                 break
     if len(self.to_install) > 0:
         ts3lib.printMessageToCurrentTab(
             "[color=red]Found missing dependencies %s in \"requirements.txt\" files from scrips, installing..."
             % self.to_install)
         QTimer.singleShot(0, self.install)
     if PluginHost.cfg.getboolean("general", "verbose"):
         ts3lib.printMessageToCurrentTab(
             "{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded."
             .format(timestamp(), self.name, self.author))
예제 #31
0
    def setupTranslator(cls):
        lang = cls.cfg.get("general", "language")
        if lang == "inherited":
            ccfg = ts3client.Config()
            q = ccfg.query("SELECT * FROM application WHERE key='Language'")

            if q.next():
                lang = q.value("value")
            else:
                lang = "en_US"
                logprint(cls._tr("Error querying language from client config"),
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
            del ccfg

        if cls.translator:
            if not QCoreApplication.removeTranslator(cls.translator):
                logprint(cls._tr("Error removing translator"),
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
            cls.translator = None

        p = pytson.getPluginPath("ressources", "i18n", "pyTSon-%s.qm" % lang)

        if os.path.isfile(p):
            cls.verboseLog(cls._tr("Using translator from {file}").
                           format(file=p), "pyTSon.PluginHost.setupTranslator")

            cls.translator = QTranslator()
            if not cls.translator.load(p):
                logprint("Error loading translator from %s" % p,
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
                cls.translator = None
                return

            if not QCoreApplication.installTranslator(cls.translator):
                logprint("Error installing translator from %s" % p,
                         ts3defines.LogLevel.LogLevel_ERROR,
                         "pyTSon.PluginHost.setupTranslator")
                cls.translator = None
예제 #32
0
    def __init__(self, cfg, host, parent=None):
        super(QDialog, self).__init__(parent)

        self.setAttribute(Qt.WA_DeleteOnClose)

        self.cfg = cfg
        self.host = host
        self.rpd = None
        self.sitepkgs = None

        try:
            setupUi(self, pytson.getPluginPath("ressources",
                                               "pyTSon-configdialog.ui"),
                    widgets=self.CONF_WIDGETS)
            self.pluginsTable.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
            self.siteTable.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)

            self.setupValues()
            self.setupSlots()
        except Exception as e:
            self.delete()
            raise e
예제 #33
0
 def __init__(self, rotateNick, parent=None):
     try:
         self.rotateNick = rotateNick
         super(QDialog, self).__init__(parent)
         setupUi(
             self,
             path.join(pytson.getPluginPath(), "scripts",
                       rotateNick.__class__.__name__, "dialog.ui"))
         self.setAttribute(Qt.WA_DeleteOnClose)
         self.setWindowTitle(rotateNick.name)
         self.nick.setText(self.rotateNick.config.get('general', 'nick'))
         self.separator.setText(self.rotateNick.separator())
         customNick = boolean(
             self.rotateNick.config.get('general', 'customNick'))
         self.currentNick.setChecked(not customNick)
         self.customNick.setChecked(customNick)
         self.nick.setEnabled(customNick)
         self.interval.value = int(
             self.rotateNick.config.get('general', 'interval'))
     except:
         from traceback import format_exc
         ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR,
                           "pyTSon", 0)
예제 #34
0
def setIcon(obj, iconpack, pluginicons=None):
    """
    Sets the icon of a QWidget (if it has a property Icon) to an icon in the
    iconpack represented by a variable which is acquired by the property
    'pytsonicon' of the object.
    If the property instead contains a string formated as
    "octicons:filename.png", the icon is set to filename.png of the octicons
    pack.
    If no such property is available, nothing is done.
    @param obj: the widget
    @type obj: QWidget
    @param iconpack: the iconpack
    @type iconpack: ts3client.IconPack
    @param pluginicons: callable which gets a string and either returns the
    path to the image file or returns a QPixmap to set the icon property to;
    defaults to None
    @type pluginicons: Callable(str) -> str or QIcon
    """
    if iconpack:
        if hasattr(obj, "setIcon") and hasattr(obj, "pytsonicon"):
            var = obj.pytsonicon

            if var.startswith("octicons:"):
                fname = os.path.join(pytson.getPluginPath("ressources",
                                     "octicons", var.split(":")[1]))
                if os.path.isfile(fname):
                    obj.setIcon(QIcon(fname))
            elif var.startswith("plugin:"):
                if pluginicons:
                    ico = pluginicons(var.split(":")[1])
                    if type(ico) is str:
                        obj.setIcon(QIcon(ico))
                    else:
                        obj.setIcon(ico)
            else:
                obj.setIcon(QIcon(iconpack.icon(var)))
예제 #35
0
    def __init__(self, schid, cid, password='', path='/', parent=None, *,
                 staticpath=False, readonly=False, downloaddir=None,
                 iconpack=None):
        """
        Instantiates a new object.
        @param schid: the id of the serverconnection handler
        @type schid: int
        @param cid: the id of the channel
        @type cid: int
        @param password: password to the channel, defaults to an empty string
        @type password: str
        @param path: path to display, defaults to the root path
        @type path: str
        @param parent: parent of the dialog; optional keyword arg;
        defaults to None
        @type parent: QWidget
        @param staticpath: if set to True, the initial path can't be
        changed by the user; optional keyword arg; defaults to False
        @type staticpath: bool
        @param readonly: if set to True, the user can't download, upload
        or delete files, or create new directories; optional keyword arg;
        defaults to False
        @type readonly: bool
        @param downloaddir: directory to download files to; optional keyword
        arg; defaults to None; if set to None, the TS3 client's download
        directory is used
        @type downloaddir: str
        @param iconpack: iconpack to load icons from; optional keyword arg;
        defaults to None; if set to None, the current iconpack is used
        @type iconpack: ts3client.IconPack
        """
        super(QDialog, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        iconpackopened = False
        if not iconpack:
            try:
                iconpack = ts3client.IconPack.current()
                iconpack.open()
                iconpackopened = True
            except Exception as e:
                self.delete()
                raise e

        try:
            setupUi(self, pytson.getPluginPath("ressources", "filebrowser.ui"),
                    iconpack=iconpack)

            self.statusbar = SmartStatusBar(self)
            self.layout().addWidget(self.statusbar)
            self.statusbar.hide()
        except Exception as e:
            self.delete()
            raise e

        err, cname = ts3lib.getChannelVariableAsString(schid, cid,
                                                       ChannelProperties.
                                                       CHANNEL_NAME)

        if err == ERROR_ok:
            self.setWindowTitle(self._tr("File Browser - {cname}").format(
                                cname=cname))
        else:
            self.setWindowTitle(self._tr("File Browser"))

        self.schid = schid
        self.cid = cid
        self.password = password
        self.path = None

        self.staticpath = staticpath
        self.readonly = readonly

        self.createretcode = None
        self.delretcode = None

        if not self.readonly and not downloaddir:
            cfg = ts3client.Config()
            q = cfg.query("SELECT value FROM filetransfer "
                          "WHERE key='DownloadDir'")
            del cfg

            if q.next():
                self.downloaddir = q.value("value")
            else:
                self.delete()
                raise Exception("Error getting DownloadDir from config")
        else:
            self.downloaddir = downloaddir

        if not self.readonly:
            menu = self.menu = QMenu(self)

            self.openAction = menu.addAction(QIcon(iconpack.icon("FILE_UP")),
                                             self._tr("Open"))
            self.openAction.connect("triggered()",
                                    self.on_openAction_triggered)

            self.downAction = menu.addAction(QIcon(iconpack.icon("DOWN")),
                                             self._tr("Download"))
            self.downAction.connect("triggered()", self.downloadFiles)
            self.renameAction = menu.addAction(QIcon(iconpack.icon("EDIT")),
                                               self._tr("Rename"))
            self.renameAction.connect("triggered()",
                                      self.on_renameAction_triggered)
            self.copyAction = menu.addAction(QIcon(iconpack.icon("COPY")),
                                             self._tr("Copy URL"))
            self.copyAction.connect("triggered()",
                                    self.on_copyAction_triggered)
            self.delAction = menu.addAction(QIcon(iconpack.icon("DELETE")),
                                            self._tr("Delete"))
            self.delAction.connect("triggered()", self.deleteFiles)

            self.upAction = menu.addAction(QIcon(iconpack.icon("UP")),
                                           self._tr("Upload files"))
            self.upAction.connect("triggered()", self.uploadFiles)
            self.createAction = menu.addAction(QIcon.fromTheme("folder"),
                                               self._tr("Create Folder"))
            self.createAction.connect("triggered()", self.createFolder)
            self.refreshAction = menu.addAction(QIcon(iconpack.icon(
                                                "FILE_REFRESH")),
                                                self._tr("Refresh"))
            self.refreshAction.connect("triggered()", self.refresh)

            self.allactions = [self.openAction, self.downAction,
                               self.renameAction, self.copyAction,
                               self.delAction, self.upAction,
                               self.createAction, self.refreshAction]

        self.collector = FileCollector(schid, cid, password, self.downloaddir)
        self.collector.collectionFinished.connect(self._startDownload)
        self.collector.collectionError.connect(self.showError)

        self.fileDoubleClicked = Signal()
        self.contextMenuRequested = Signal()

        self.transdlg = None

        self.listmodel = FileListModel(schid, cid, password, self,
                                       readonly=readonly)
        self.listmodel.pathChanged.connect(self.onPathChanged)
        self.listmodel.error.connect(self.showError)

        self.proxy = QSortFilterProxyModel(self)
        self.proxy.setSortRole(Qt.UserRole)
        self.proxy.setSortCaseSensitivity(Qt.CaseInsensitive)
        self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.proxy.setSourceModel(self.listmodel)

        self.listmodel.path = path

        self._adjustUi()

        if iconpackopened:
            iconpack.close()

        PluginHost.registerCallbackProxy(self)
예제 #36
0
class faker(ts3plugin):
    name = "Fake Anything"
    apiVersion = 22
    requestAutoload = False
    version = "1.0"
    author = "Bluscream"
    description = "Fake almost anything ;)"
    offersConfigure = False
    commandKeyword = ""
    infoTitle = None
    iconPath = path.join(getPluginPath(), "scripts", "faker", "icons")
    menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CHANNEL, 0,
                  "Fake this channel", iconPath + "/fake.png"),
                 (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT, 0,
                  "Fake this client", iconPath + "/fake.png")]
    hotkeys = []

    def timestamp(self):
        return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now())

    def __init__(self):
        if self.debug:
            ts3lib.printMessageToCurrentTab(
                "{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded."
                .format(self.timestamp(), self.name, self.author))

    def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
        if atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CHANNEL and menuItemID == 0:
            self.fakeChannel(schid, selectedItemID)
        elif atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT and menuItemID == 0:
            self.fakeClient(schid, selectedItemID)

    def fakeChannel(self, schid, channelID):
        (error, nick) = ts3lib.getChannelVariableAsString(
            schid, channelID, ts3defines.ChannelProperties.CHANNEL_NAME)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_NAME, nick)

        (error, phonetic) = ts3lib.getChannelVariableAsString(
            schid, channelID,
            ts3defines.ChannelProperties.CHANNEL_NAME_PHONETIC)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_NAME, phonetic)

        (error, pw) = ts3lib.getChannelVariableAsInt(
            schid, channelID, ts3defines.ChannelProperties.CHANNEL_PASSWORD)
        if pw:
            ts3lib.setChannelVariableAsString(
                schid, 0, ts3defines.ChannelProperties.CHANNEL_PASSWORD, ".")

        (error, topic) = ts3lib.getChannelVariableAsString(
            schid, channelID, ts3defines.ChannelProperties.CHANNEL_TOPIC)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_TOPIC, topic)

        (error, description) = ts3lib.getChannelVariableAsString(
            schid, channelID, ts3defines.ChannelProperties.CHANNEL_DESCRIPTION)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_DESCRIPTION,
            description)

        (error, neededtp) = ts3lib.getChannelVariableAsInt(
            schid, channelID,
            ts3defines.ChannelProperties.CHANNEL_NEEDED_TALK_POWER)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_NEEDED_TALK_POWER,
            neededtp)

        (error, codec) = ts3lib.getChannelVariableAsInt(
            schid, channelID, ts3defines.ChannelProperties.CHANNEL_CODEC)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_CODEC, codec)

        (error, quality) = ts3lib.getChannelVariableAsInt(
            schid, channelID,
            ts3defines.ChannelProperties.CHANNEL_CODEC_QUALITY)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_CODEC_QUALITY,
            quality)

        (error, latency) = ts3lib.getChannelVariableAsString(
            schid, channelID,
            ts3defines.ChannelProperties.CHANNEL_CODEC_LATENCY_FACTOR)
        ts3lib.setChannelVariableAsString(
            schid, 0,
            ts3defines.ChannelProperties.CHANNEL_CODEC_LATENCY_FACTOR, latency)

        (error, unencrypted) = ts3lib.getChannelVariableAsInt(
            schid, channelID,
            ts3defines.ChannelProperties.CHANNEL_CODEC_IS_UNENCRYPTED)
        ts3lib.setChannelVariableAsString(
            schid, 0,
            ts3defines.ChannelProperties.CHANNEL_CODEC_IS_UNENCRYPTED,
            unencrypted)

        (error, maxclients) = ts3lib.getChannelVariableAsInt(
            schid, channelID, ts3defines.ChannelProperties.CHANNEL_MAXCLIENTS)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_MAXCLIENTS,
            maxclients)

        (error, maxfamilyclients) = ts3lib.getChannelVariableAsInt(
            schid, channelID,
            ts3defines.ChannelProperties.CHANNEL_MAXFAMILYCLIENTS)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_MAXFAMILYCLIENTS,
            maxfamilyclients)

        (error, iconid) = ts3lib.getChannelVariableAsUint64(
            schid, channelID, ts3defines.ChannelProperties.CHANNEL_ICON_ID)
        ts3lib.setChannelVariableAsString(
            schid, 0, ts3defines.ChannelProperties.CHANNEL_ICON_ID, iconid)

        (error, _clid) = ts3lib.getClientID(schid)

    def fakeClient(self, schid, clientID):
        (error, _clid) = ts3lib.getClientID(schid)
        (error, tnick) = ts3lib.getClientVariableAsUInt64(
            schid, clientID, ts3defines.ClientProperties.CLIENT_NICKNAME)
        (error, tnickp) = ts3lib.getClientVariableAsUInt64(
            schid, clientID,
            ts3defines.ClientProperties.CLIENT_NICKNAME_PHONETIC)
예제 #37
0
#else: ts3host = ts3Ext.ts3SessionHost(next(iter(PluginHost.active.values())))

print('(pyTSon v{} on {} | Console started at: {:%Y-%m-%d %H:%M:%S})'.format(
    pytson.getVersion(), pytson.platformstr(), datetime.now()))
print("Client curAPI: {} | LibVer: {} | LibVerNum: {}".format(
    pytson.getCurrentApiVersion(), ts3lib.getClientLibVersion(),
    ts3lib.getClientLibVersionNumber()))
print("Python {} {} API: {}".format(sys.platform, sys.version,
                                    sys.api_version))
print("sys.executable: %s" % sys.executable)
print("ts3lib.getAppPath(): %s" % ts3lib.getAppPath())
print("ts3lib.getConfigPath(): %s" % ts3lib.getConfigPath())
print("ts3lib.getResourcesPath(): %s" % ts3lib.getResourcesPath())
print("ts3lib.getPluginPath(): %s" % ts3lib.getPluginPath())
print("pytson.getConfigPath(): %s" % pytson.getConfigPath())
print("pytson.getPluginPath(): %s" % pytson.getPluginPath())
print("bluscream.getScriptPath(): %s" % getScriptPath("console"))
i = 0
for item in sys.path:
    print('sys.path[{}]"{}"'.format(i, item))
    i += 1
print("")
print(sys.flags)
print("")


class testClass(object):
    def __init__():
        pass

    def testFunction():
예제 #38
0
    class channelWatcher(ts3plugin):
        name = "Channel Watcher"
        apiVersion = 22
        requestAutoload = False
        version = "1.0"
        author = "Bluscream"
        description = "Helps you keeping your channel moderated.\n\nCheck out https://r4p3.net/forums/plugins.68/ for more plugins."
        offersConfigure = False
        commandKeyword = "cw"
        infoTitle = None
        menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Toggle Channel Watcher", ""),(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CHANNEL, 0, "Add to watched channels", ""),(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CHANNEL, 1, "Remove from watched channels", ""),(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT, 0, "Check this client!", "")]
        hotkeys = []
        debug = False
        toggle = True
        autoBan = True
        autoMod = True
        autoBanOnKick = True
        checkRecording = True
        autoCheckOnChannel = False
        requested = False
        #requestedUID = []
        requestedC = []
        banned = False
        banned_names = ["BAN", "NOT WELCOME"]
        mod_names = ["MOD", "OPERATOR"]
        admin_names = ["ADMIN"]
        sbgroup = 0
        smgroup = 0
        sagroup = 0
        ownchannels = []
        check = False
        checkcurrent = ""
        reason = ""
        ini = path.join(getPluginPath(), "scripts", "channelWatcher", "settings.ini")
        cfg = ConfigParser()

        def timestamp(self): return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now())

        def __init__(self):
            if path.isfile(self.ini): self.cfg.read(self.ini)
            else:
                self.cfg['general'] = {"cfgversion": "1", "debug": "False", "enabled": "True"}
                self.cfg['autoban'] = {"enabled": "True"}
                self.cfg['automod'] = {"enabled": "True", "autotp": "True"}
                self.cfg['antirecord'] = {"enabled": "True"}
                self.cfg['autokickonban'] = {"enabled": "True"}
                self.cfg['groups'] = {"banned": ["BAN", "NOT WELCOME"], "mod": ["MOD", "OPERATOR"], "admin": ["ADMIN"]}
                with open(self.ini, 'w') as configfile: self.cfg.write(configfile)
            self.db = QSqlDatabase.addDatabase("QSQLITE","channelWatcher")
            self.db.setDatabaseName(ts3lib.getConfigPath() + "settings.db")
            if self.db.isValid(): self.db.open()
            schid = ts3lib.getCurrentschid()
            if schid:
                self.requested = True
                ts3lib.requestChannelGroupList(schid)
                (error, ownID) = ts3lib.getClientID(schid)
                (error, cid) = ts3lib.getChannelOfClient(schid, ownID)
                self.ownchannels.extend([cid])
            if self.debug: ts3lib.printMessageToCurrentTab("{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded.".format(self.timestamp(),self.name,self.author))

        def stop(self):
            self.db.close();self.db.delete()
            QSqlDatabase.removeDatabase("channelWatcher")

        def clientURL(self, schid=None, clid=1, uid=None, nickname=None, encodednick=None):
            if not self.check: return False
            if schid == None:
                try: schid = ts3lib.getCurrentschid()
                except: pass
            if uid == None:
                try: (error, uid) = ts3lib.getClientVariableAsString(schid, clid, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
                except: pass
            if nickname == None:
                try: (error, nickname) = ts3lib.getClientDisplayName(schid, clid)
                except: nickname = uid
            if encodednick == None:
                try: encodednick = urlencode(nickname)
                except: pass
            return "[url=client://%s/%s~%s]%s[/url]" % (clid, uid, encodednick, nickname)

        def InContacts(self, uid):
            if not self.check: return False
            q = self.db.exec_("SELECT * FROM contacts WHERE value LIKE '%%IDS=%s%%'" % uid)
            ret = 2
            if q.next():
                val = q.value("value")
                for l in val.split('\n'):
                    if l.startswith('Friend='):
                        ret = int(l[-1])
            q.delete();return ret

        def checkUser(self, uid):
            if not self.check: return False
            if self.toggle:
                if len(self.ownchannels) > 0:
                    if uid != "serveradmin" and uid != "ServerQuery":
                        _in = self.InContacts(uid)
                        if _in < 2:
                            _schid = ts3lib.getCurrentschid()
                            self.requestedC.extend([_in])
                            ts3lib.requestClientDBIDfromUID(_schid, uid)

        def checkAllUsers(self):
            if not self.check: return False
            if self.toggle:
                _schid = ts3lib.getCurrentschid()
                (error, _clid) = ts3lib.getClientID(_schid)
                (error, cl) = ts3lib.getClientList(_schid)
                for user in cl:
                    if user != _clid:
                        (error, uid) = ts3lib.getClientVariableAsString(_schid, user, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
                        self.checkUser(uid)

        def processCommand(self, schid, command):
            cmd = command.lower()
            if cmd.startswith("test"):
                ts3lib.printMessageToCurrentTab("Status: "+str(self.toggle))
                ts3lib.printMessageToCurrentTab("Ban: "+str(self.sbgroup))
                ts3lib.printMessageToCurrentTab("Mod: "+str(self.smgroup))
                ts3lib.printMessageToCurrentTab("Admin: "+str(self.sagroup))
                ts3lib.printMessageToCurrentTab("Own Channels: "+str(self.ownchannels))
                ts3lib.printMessageToCurrentTab("requestedCs: "+str(self.requestedC))
                return True
            elif cmd.startswith("addchan"):
                command = int(command.split("addchan ")[1])
                self.ownchannels.extend([command])
                ts3lib.printMessageToCurrentTab("[color=green]Added[/color] #"+str(command)+" to list of channels: "+str(self.ownchannels))
                return True
            elif cmd.startswith("delchan"):
                command = int(command.split("delchan ")[1])
                self.ownchannels.remove([command])
                ts3lib.printMessageToCurrentTab("[color=red]Removed[/color] #"+str(command)+" from list of channels: "+str(self.ownchannels))
                return True
            elif cmd == "checkall":
                self.checkAllUsers()
                return True
            elif cmd == "load":
                self.requested = True
                ts3lib.requestChannelGroupList(ts3lib.getCurrentschid())
                return True

        def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
            if atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL:
                if menuItemID == 0:
                    self.toggle = not self.toggle
                    ts3lib.printMessageToCurrentTab('[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.datetime.now())+" Set Auto Channel Commander to [color=yellow]"+str(self.toggle)+"[/color]")
            elif atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CHANNEL:
                if menuItemID == 0:
                    self.ownchannels.extend([selectedItemID])
                    ts3lib.printMessageToCurrentTab("[color=green]Added[/color] #"+str(selectedItemID)+" to list of channels: "+str(self.ownchannels))
                elif menuItemID == 1:
                    self.ownchannels.remove(selectedItemID)
                    ts3lib.printMessageToCurrentTab("[color=red]Removed[/color] #"+str(selectedItemID)+" from list of channels: "+str(self.ownchannels))
            elif atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT:
                if menuItemID == 0:
                    (error, uid) = ts3lib.getClientVariableAsString(schid, selectedItemID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER);self.checkUser(uid)

        def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber):
            if self.toggle:
                if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED:
                    self.requested = True
                    ts3lib.requestChannelGroupList(schid)
                elif newStatus == ts3defines.ConnectStatus.STATUS_DISCONNECTED:
                    self.check = False;self.ownchannels.clear()

        def onChannelGroupListEvent(self, schid, channelGroupID, name, atype, iconID, saveDB):
            if self.toggle:
                if self.requested == True:
                    for _name in self.banned_names:
                        if name.upper().__contains__(_name): self.sbgroup = channelGroupID;return
                    for _name in self.mod_names:
                        if name.upper().__contains__(_name): self.smgroup = channelGroupID;return
                    for _name in self.admin_names:
                        if name.upper().__contains__(_name): self.sagroup = channelGroupID;return

        def onChannelGroupListFinishedEvent(self, schid):
            if self.toggle:
                self.requested = False;self.check = True

        def onClientChannelGroupChangedEvent(self, schid, channelGroupID, channelID, clientID, invokerClientID, invokerName, invokerUniqueIdentity):
            if not self.check: return False
            if self.toggle:
                (error, _clid) = ts3lib.getClientID(schid)
                (error, _cid) = ts3lib.getChannelOfClient(schid, _clid)
                if clientID == _clid:
                    if channelGroupID == self.sagroup:
                        if self.ownchannels.__contains__(channelID):
                            _t = False
                        else:
                            self.ownchannels.append(channelID)
                    elif channelGroupID == self.smgroup:
                        (error, neededTP) = ts3lib.getChannelVariableAsInt(schid, _cid, ts3defines.ChannelPropertiesRare.CHANNEL_NEEDED_TALK_POWER)
                        if neededTP > 0:
                            (error, clients) = ts3lib.getChannelClientList(schid, _cid)
                            for client in clients:
                                if client == _clid: continue
                                (error, _cgid) = ts3lib.getClientVariableAsInt(schid, client, ts3defines.ClientPropertiesRare.CLIENT_CHANNEL_GROUP_ID)
                                if _cgid == self.sagroup: continue
                                (error, uid) = ts3lib.getClientVariableAsString(schid, client, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
                                if self.InContacts(uid) == 0:
                                    ts3lib.requestClientSetIsTalker(schid, client, True)
                elif channelID == _cid and channelGroupID == self.sbgroup:
                    #(error, uid) = ts3lib.getClientVariableAsString(schid, clientID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
                    (error, _cid) = ts3lib.getChannelOfClient(schid, clientID)
                    if _cid in self.ownchannels:
                        ts3lib.requestClientKickFromChannel(schid, clientID, "You were banned by \"%s\""%invokerName + (" for \"%s\""%invokerName) if self.reason != "" else "")

        def onClientMoveEvent(self, schid, clientID, oldChannelID, newChannelID, visibility, moveMessage):
            if not self.check: return False
            if self.toggle:
                (error, _clid) = ts3lib.getClientID(schid)
                (error, _cid) = ts3lib.getChannelOfClient(schid, _clid)
                (error, _cgid) = ts3lib.getClientVariableAsInt(schid, _clid, ts3defines.ClientPropertiesRare.CLIENT_CHANNEL_GROUP_ID)
                if not clientID == _clid:
                    (error, uid) = ts3lib.getClientVariableAsString(schid, clientID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
                    if oldChannelID == 0: self.checkUser(uid) # and _cgid == self.smgroup or _cgid == self.sagroup
                    if newChannelID == _cid and _cgid == self.smgroup:
                        (error, neededTP) = ts3lib.getChannelVariableAsInt(schid, _cid, ts3defines.ChannelPropertiesRare.CHANNEL_NEEDED_TALK_POWER)
                        if neededTP > 0:
                            if self.InContacts(uid) == 0: ts3lib.requestClientSetIsTalker(schid, clientID, True)

        def onClientMoveSubscriptionEvent(self, schid, clientID, oldChannelID, newChannelID, visibility):
            if not self.check: return False
            if self.toggle:
                (error, _clid) = ts3lib.getClientID(schid)
                if clientID != _clid:
                    (error, uid) = ts3lib.getClientVariableAsString(schid, clientID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
                    self.checkUser(uid)

        def onNewChannelCreatedEvent(self, schid, channelID, channelParentID, invokerID, invokerName, invokerUniqueIdentifier):
            if not self.check: return False
            if self.toggle and self.autoCheckOnChannel:
                (error, _clid) = ts3lib.getClientID(schid)
                if invokerID == _clid:
                    self.checkAllUsers()

        def onDelChannelEvent(self, schid, channelID, invokerID, invokerName, invokerUniqueIdentifier):
            if not self.check: return False
            if self.toggle:
                if self.ownchannels.__contains__(channelID):
                    self.ownchannels.remove(channelID)

        def onClientDBIDfromUIDEvent(self, schid, uniqueClientIdentifier, clientDatabaseID):
            if self.toggle:
                if self.check:
                    _cid = self.requestedC.pop(0)
                    if _cid == 0 and self.autoMod:
                        ts3lib.requestSetClientChannelGroup(schid, [self.smgroup]*len(self.ownchannels), self.ownchannels, [clientDatabaseID]*len(self.ownchannels))
                        ts3lib.printMessageToCurrentTab("[color=green]Gave Client "+self.clientURL(schid, None, uniqueClientIdentifier)+" Channel Mod in #"+str(self.ownchannels)+"[/color]")
                    elif _cid == 1 and self.autoBan:
                        ts3lib.requestSetClientChannelGroup(schid, [self.sbgroup]*len(self.ownchannels), self.ownchannels, [clientDatabaseID]*len(self.ownchannels))
                        ts3lib.printMessageToCurrentTab("[color=red]Banned Client "+self.clientURL(schid, None, uniqueClientIdentifier)+" from Channels #"+str(self.ownchannels)+"[/color]")
                elif self.checkcurrent == uniqueClientIdentifier:
                    ts3lib.requestSetClientChannelGroup(schid, [self.sbgroup]*len(self.ownchannels), self.ownchannels, [clientDatabaseID]*len(self.ownchannels))
                    self.checkcurrent = ""
                    ts3lib.printMessageToCurrentTab("[color=orange]KickBanned Client "+self.clientURL(schid, None, uniqueClientIdentifier)+" from Channels #"+str(self.ownchannels)+"[/color]")

        def onUpdateClientEvent(self, schid, clientID, invokerID, invokerName, invokerUniqueIdentifier):
            return
            if self.check and self.toggle:
                (error, _clid) = ts3lib.getClientID(schid)
                if not clientID == _clid:
                    (error, _tcid) = ts3lib.getChannelOfClient(schid, clientID)
                    if _tcid in self.ownchannels:
                        (error, _cgid) = ts3lib.getClientVariableAsInt(schid, _clid, ts3defines.ClientPropertiesRare.CLIENT_CHANNEL_GROUP_ID)
                        if _cgid in [self.smgroup, self.sagroup]:
                            if self.checkRecording:
                                (error, clientRecStatus) = ts3lib.getClientVariableAsInt(schid, clientID, ts3defines.ClientProperties.CLIENT_IS_RECORDING)
                                if clientRecStatus == 1:
                                    self.reason == "Recording"
                                    _schid = ts3lib.getCurrentschid()
                                    self.requestedC.extend([1])
                                    _dbid = ts3lib.requestClientDBIDfromUID(_schid, invokerUniqueIdentifier)

        def onClientKickFromChannelEvent(self, schid, clientID, oldChannelID, newChannelID, visibility, kickerID, kickerName, kickerUniqueIdentifier, kickMessage):
            if not self.autoBanOnKick: return False
            if self.toggle:
                (error, _clid) = ts3lib.getClientID(schid)
                if not clientID == _clid:
                    (error, _cgid) = ts3lib.getClientVariableAsInt(schid, _clid, ts3defines.ClientPropertiesRare.CLIENT_CHANNEL_GROUP_ID)
                    if _cgid == self.smgroup or _cgid == self.sagroup:
                        (error, _cid) = ts3lib.getChannelOfClient(schid, _clid)
                        (error, uid) = ts3lib.getClientVariableAsString(schid, clientID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
                        if oldChannelID == _cid and kickMessage == "": self.checkcurrent = uid;ts3lib.requestClientDBIDfromUID(schid, uid)
예제 #39
0
class serverSwitcher(ts3plugin):
    tag = "tabs"
    name = 'Server Switcher'
    apiVersion = 22
    requestAutoload = False
    version = '1.0'
    author = 'Bluscream'
    description = 'Show others that you just switched to another tab.\n\nCheck out https://r4p3.net/forums/plugins.68/ for more plugins.'
    offersConfigure = True
    commandKeyword = ""
    infoTitle = None
    menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT, 0, "Join",
                  "")]
    hotkeys = []
    debug = False
    ini = path.join(pytson.getPluginPath(), "scripts", "serverSwitcher",
                    "settings.ini")
    cfg = ConfigParser()

    @staticmethod
    def timestamp():
        return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now())

    def parseMeta(self, schid, clid):
        (error, meta) = ts3.getClientVariable(
            schid, clid, ts3defines.ClientProperties.CLIENT_META_DATA)
        # print(re.search('(<{0}.*>.*</{0}>)'.format(self.tag), meta))
        try:
            meta = re.search('<{0}>(.*)</{0}>'.format(self.tag), meta).group(0)
        except AttributeError:
            return False
        # print('meta_strip: %s'%meta.strip())
        # print('xml: %s'%xml.fromstring(meta.strip(), parser = xml.XMLParser(encoding="utf-8")))
        # print('xml_sub: %s'%xml.fromstring(meta.strip(), parser = xml.XMLParser(encoding="utf-8")).getchildren())
        # print('xml_sub[0]: %s'%xml.fromstring(meta.strip(), parser = xml.XMLParser(encoding="utf-8")).getchildren()[0])
        return xml.fromstring(
            meta.strip(),
            parser=xml.XMLParser(encoding="utf-8")).getchildren()[0]

    def __init__(self):
        if path.isfile(self.ini):
            self.cfg.read(self.ini)
        else:
            self.cfg['general'] = {
                "cfgversion": "1",
                "debug": "False",
                "enabled": "True",
                "pw": "False",
                "channel": "False",
                "channelpw": "False",
                "status": "switched servers"
            }
            with open(self.ini, 'w') as cfg:
                self.cfg.write(cfg)
            schid = ts3.getCurrentServerConnectionHandlerID()
            err, status = ts3.getConnectionStatus(schid)
            if status == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED:
                self.setStatus(schid)
        if self.debug:
            ts3.printMessageToCurrentTab(
                '{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded.'
                .format(self.timestamp(), self.name, self.author))

    def configure(self, qParentWidget):
        try:
            d = dict()
            d['debug'] = (ValueType.boolean, "Debug",
                          self.cfg['general']['debug'] == "True", None, None)
            d['enabled'] = (ValueType.boolean, "Broadcast own changes",
                            self.cfg['general']['enabled'] == "True", None,
                            None)
            d['pw'] = (ValueType.boolean, "Broadcast server passwords",
                       self.cfg['general']['pw'] == "True", None, None)
            d['channel'] = (ValueType.boolean, "Broadcast new channel",
                            self.cfg['general']['channel'] == "True", None,
                            None)
            d['channelpw'] = (ValueType.boolean, "Broadcast channel pw",
                              self.cfg['general']['channelpw'] == "True", None,
                              None)
            d['status'] = (ValueType.string, "AFK status text:",
                           self.cfg['general']['status'], None, 1)
            getValues(None, "{} Settings".format(self.name), d,
                      self.configDialogClosed)
        except:
            from traceback import format_exc
            try:
                ts3.logMessage(format_exc(),
                               ts3defines.LogLevel.LogLevel_ERROR,
                               "PyTSon::" + self.name, 0)
            except:
                print("Error in " + self.name + ".configure: " + format_exc())

    def configDialogClosed(self, r, vals):
        if r == QDialog.Accepted:
            self.cfg['general'] = {
                "cfgversion": self.cfg.get('general', 'cfgversion'),
                "debug": str(vals['debug']),
                "enabled": str(vals['enabled']),
                "pw": str(vals['pw']),
                "channel": str(vals['channel']),
                "channelpw": str(vals['channelpw']),
                "status": vals['status']
            }
            with open(self.ini, 'w') as configfile:
                self.cfg.write(configfile)

    def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
        if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT or menuItemID != 0:
            return
        server = self.parseMeta(schid, selectedItemID)
        if server is None: return
        # err, tab = ts3.spawnNewServerConnectionHandler(0)
        # err = ts3.startConnection(tab, "", server.attrib["host"], server.attrib["port"] if hasattr(server, "port") else 0, "", [], "", server.attrib["pw"] if hasattr(server, "pw") else "")
        err, tab = ts3.guiConnect(
            ts3defines.PluginConnectTab.
            PLUGIN_CONNECT_TAB_NEW_IF_CURRENT_CONNECTED, server.text
            or "Server",
            '{}:{}'.format(server.attrib["host"], server.attrib["port"])
            if hasattr(server, 'port') else server.attrib["host"],
            server.attrib["pw"] if hasattr(server, "pw") else "",
            "TeamspeakUser", "", "", "", "", "", "", "", "", "")

    """
    def onIncomingClientQueryEvent(self, schid, commandText):
            command = commandText.split()
            if command[0] != 'notifyclientupdated': return
            clid = int(command[1].replace('clid=', ''))
            err, ownid = ts3.getClientID(schid)
            if clid != ownid: return
            var = command[2].split("=")
            if var[0] != 'client_input_hardware': return
            if var[1] != '1': return
            self.setStatus(schid, ownid)
    """

    def onClientSelfVariableUpdateEvent(self, schid, flag, oldValue, newValue):
        try:
            if flag == ts3defines.ClientProperties.CLIENT_INPUT_HARDWARE and newValue == "1":
                self.setStatus(schid)
        except:
            from traceback import format_exc
            ts3.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR,
                           "pyTSon", 0)
            pass

    def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber):
        try:
            if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED:
                err, mic = ts3.getClientSelfVariable(
                    schid, ts3defines.ClientProperties.CLIENT_INPUT_HARDWARE)
                if not err and not mic: self.setStatus(schid)
        except:
            from traceback import format_exc
            ts3.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR,
                           "pyTSon", 0)
            pass

    def setStatus(self, schid):
        try:
            err, ownid = ts3.getClientID(schid)
            err, schids = ts3.getServerConnectionHandlerList()
            regex = re.compile(r'.*(<{0}>.*</{0}>).*'.format(self.tag),
                               re.IGNORECASE)
            for tab in schids:
                err, meta_data = ts3.getClientSelfVariable(
                    tab, ts3defines.ClientProperties.CLIENT_META_DATA)
                meta_data = regex.sub("", meta_data)
                if tab == schid:
                    ts3.setClientSelfVariableAsInt(
                        tab, ts3defines.ClientPropertiesRare.CLIENT_AWAY,
                        ts3defines.AwayStatus.AWAY_NONE)
                else:
                    err, away_message = ts3.getClientSelfVariable(
                        tab,
                        ts3defines.ClientPropertiesRare.CLIENT_AWAY_MESSAGE)
                    err, away = ts3.getClientSelfVariable(
                        tab, ts3defines.ClientPropertiesRare.CLIENT_AWAY)
                    if away != ts3defines.AwayStatus.AWAY_ZZZ:
                        ts3.setClientSelfVariableAsInt(
                            tab, ts3defines.ClientPropertiesRare.CLIENT_AWAY,
                            ts3defines.AwayStatus.AWAY_ZZZ)
                    host = ""
                    port = 0
                    name = ""
                    if self.cfg.getboolean('general', 'enabled'):
                        err, host, port, pw = ts3.getServerConnectInfo(schid)
                        # err, ip = ts3.getConnectionVariableAsString(schid, ownid, ts3defines.ConnectionProperties.CONNECTION_SERVER_IP)
                        # err, port = ts3.getConnectionVariableAsString(schid, ownid, ts3defines.ConnectionProperties.CONNECTION_SERVER_PORT)
                        # err, ip = ts3.getServerVariableAsString(schid, ts3defines.VirtualServerPropertiesRare.VIRTUALSERVER_IP)
                        # err, port = ts3.getServerVariableAsString(schid, ts3defines.VirtualServerPropertiesRare.VIRTUALSERVER_PORT)
                        if host:
                            newmeta = xml.Element(self.tag)
                            c = xml.SubElement(newmeta, "tab")
                            c.set("id", str(schid))
                            err, name = ts3.getServerVariable(
                                schid, ts3defines.VirtualServerProperties.
                                VIRTUALSERVER_NAME)
                            if name: c.text = escape(name.strip())
                            c.set("host", escape(host))
                            if port and port != 9987:
                                c.set("port", "{}".format(port))
                            if pw and self.cfg.getboolean('general', 'pw'):
                                c.set("pw", pw)
                            meta_data = "{old}{new}".format(
                                old=meta_data,
                                new=xml.tostring(newmeta).decode("utf-8"))
                            # meta_data = "{}<server>{}{}</server>".format(meta_data, ip, ":" + port if port else "")
                    _away_message = self.cfg.get('general', 'status').replace(
                        '{host}', host if host else "").replace(
                            '{name}', name if name else "").replace(
                                '{port}',
                                str(port) if port else "")
                    if away_message != _away_message:
                        ts3.setClientSelfVariableAsString(
                            tab, ts3defines.ClientPropertiesRare.
                            CLIENT_AWAY_MESSAGE, _away_message)
                ts3.setClientSelfVariableAsString(
                    tab, ts3defines.ClientProperties.CLIENT_META_DATA,
                    meta_data)
                ts3.flushClientSelfUpdates(tab)
        except:
            from traceback import format_exc
            ts3.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR,
                           "pyTSon", 0)
            pass
예제 #40
0
class countContacts(ts3plugin):
    name = "Count Contacts"
    try:
        apiVersion = getCurrentApiVersion()
    except:
        apiVersion = 21
    requestAutoload = False
    version = "1"
    author = "Bluscream"
    description = "Gives you numbers"
    offersConfigure = True
    commandKeyword = "ccount"
    infoTitle = "[b]Contacts:[/b]"
    menuItems = [
        (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, name, ""),
        (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 1,
         "Online Contacts", ""),
        (ts3defines.PluginItemType.PLUGIN_CHANNEL, 0, "Send Contact Stats",
         ""),
        (ts3defines.PluginItemType.PLUGIN_CLIENT, 0, "Send Contact Stats", "")
    ]
    hotkeys = []
    count = 0
    ini = os.path.join(getPluginPath(), "scripts", "countContacts",
                       "settings.ini")
    ui = os.path.join(getPluginPath(), "scripts", "countContacts",
                      "filters.ui")
    cfg = ConfigParser()
    cfg.optionxform = str
    dlg = None

    def __init__(self):
        if os.path.isfile(self.ini): self.cfg.read(self.ini)
        else:
            self.cfg['filters'] = {"Male": "m/", "Female": "f/"}
            with open(self.ini, 'w') as configfile:
                self.cfg.write(configfile)
        if PluginHost.cfg.getboolean("general", "verbose"):
            ts3lib.printMessageToCurrentTab(
                "{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded."
                .format(timestamp(), self.name, self.author))

    def configure(self, qParentWidget):
        if not self.dlg: self.dlg = contactStatsFilters(self)
        self.dlg.show()
        self.dlg.raise_()
        self.dlg.activateWindow()
        return QDialog.Rejected
        d = dict()
        for k in self.cfg['filters']:
            d[k] = (ValueType.string, k, self.cfg['filters'][k], None, 1)
        getValues(None, "Count Contacts Prefixes", d, self.configDialogClosed)

    def configDialogClosed(self, r, vals):
        if r == QDialog.Rejected: return
        for val in vals:
            self.cfg.set("general", val, vals[val])
        with open(self.ini, 'w') as configfile:
            self.cfg.write(configfile)

    def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID):
        if atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL:
            if menuItemID == 0: self.printContacts()
            elif menuItemID == 1:
                ts3lib.printMessageToCurrentTab("{}{}".format(
                    timestamp(), self.onlineContacts(schid, False)))
        elif atype == ts3defines.PluginItemType.PLUGIN_CHANNEL:
            ts3lib.requestSendChannelTextMsg(schid, self.contactStats(),
                                             selectedItemID)
        elif atype == ts3defines.PluginItemType.PLUGIN_CLIENT:
            ts3lib.requestSendPrivateTextMsg(schid, self.contactStats(),
                                             selectedItemID)

    def processCommand(self, schid, command):
        self.printContacts()
        return True

    def printContacts(self):
        ts3lib.printMessageToCurrentTab("{}{}".format(timestamp(),
                                                      self.contactStats(True)))

    def checkFilters(self, counters, nick):
        for k in self.cfg['filters']:
            tmp = self.cfg.get('filters', k).split('|', 2)
            case = bool(int(tmp[0]))
            mode = tmp[1]
            text = tmp[2]
            if case:
                nick = nick.lower()
                text = text.lower()
            if mode == "Prefix":
                if nick.startswith(text): counters[k] += 1
            elif mode == "Suffix":
                if nick.endswith(text): counters[k] += 1
            elif mode == "Contains":
                if text in nick: counters[k] += 1
            elif mode == "Equals":
                if text == nick: counters[k] += 1

    def onlineContacts(self, schid, neutral=list()):
        contacts = getContacts()
        lst = {}
        for contact in contacts:
            lst[contact["IDS"]] = contact["Friend"]
        del contacts
        (err, clist) = ts3lib.getClientList(schid)
        buddies = []
        blocked = []
        unknown = []
        for clid in clist:
            (err, uid) = ts3lib.getClientVariable(
                schid, clid,
                ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
            if not uid in lst: continue
            if lst[uid] == ContactStatus.FRIEND:
                buddies.append(clientURL(schid, clid, uid))
            elif lst[uid] == ContactStatus.BLOCKED:
                blocked.append(clientURL(schid, clid, uid))
            elif lst[uid] == ContactStatus.NEUTRAL:
                if neutral: neutral.append(clientURL(schid, clid, uid))
            else: unknown.append(clientURL(schid, clid, uid))
        _sum = len(buddies) + len(blocked) + len(unknown)
        if neutral: _sum += len(neutral)
        msg = ["[u]My Online Contacts [/u]: [b]{}[/b]".format(_sum)]
        if len(buddies) > 0:
            msg.append("[b]{}[/b] [color=green]Buddies[/color]: {}".format(
                len(buddies), " | ".join(buddies)))
        if len(blocked) > 0:
            msg.append("[b]{}[/b] [color=red]Blocked[/color]: {}".format(
                len(blocked), " | ".join(blocked)))
        if neutral and len(neutral) > 0:
            msg.append("[b]{}[/b] Neutral: {}".format(len(neutral),
                                                      " | ".join(neutral)))
        if len(unknown) > 0:
            msg.append("[b]{}[/b] [color=orange]Unknown[/color]: {}".format(
                len(unknown), " | ".join(unknown)))
        return "\n".join(msg)

    def contactStats(self, detailed=False):
        buddies = 0
        blocked = 0
        neutral = 0
        unknown = 0
        counters = {}
        bcounters = {}
        blcounters = {}
        ncounters = {}
        ucounters = {}
        for k in self.cfg['filters']:
            counters[k] = 0
            bcounters[k] = 0
            blcounters[k] = 0
            ncounters[k] = 0
            ucounters[k] = 0
        contacts = getContacts()
        if detailed:
            first = round(time.time())
            last = 0
            firstc = None
            lastc = None
        for contact in contacts:
            nick = contact["Nickname"].decode("utf-8")
            for k in self.cfg['filters']:
                tmp = self.cfg.get('filters', k).split('|', 2)
                case = bool(int(tmp[0]))
                mode = tmp[1]
                text = tmp[2]
                if case:
                    nick = nick.lower()
                    text = text.lower()
                if mode == "Prefix":
                    if nick.startswith(text): counters[k] += 1
                elif mode == "Suffix":
                    if nick.endswith(text): counters[k] += 1
                elif mode == "Contains":
                    if text in nick: counters[k] += 1
                elif mode == "Equals":
                    if text == nick: counters[k] += 1
            status = contact["Friend"]
            if status == ContactStatus.FRIEND:
                buddies += 1
                for k in self.cfg['filters']:
                    tmp = self.cfg.get('filters', k).split('|', 2)
                    case = bool(int(tmp[0]))
                    mode = tmp[1]
                    text = tmp[2]
                    if case:
                        nick = nick.lower()
                        text = text.lower()
                    if mode == "Prefix":
                        if nick.startswith(text): bcounters[k] += 1
                    elif mode == "Suffix":
                        if nick.endswith(text): bcounters[k] += 1
                    elif mode == "Contains":
                        if text in nick: bcounters[k] += 1
                    elif mode == "Equals":
                        if text == nick: bcounters[k] += 1
            elif status == ContactStatus.BLOCKED:
                blocked += 1
                for k in self.cfg['filters']:
                    tmp = self.cfg.get('filters', k).split('|', 2)
                    case = bool(int(tmp[0]))
                    mode = tmp[1]
                    text = tmp[2]
                    if case:
                        nick = nick.lower()
                        text = text.lower()
                    if mode == "Prefix":
                        if nick.startswith(text): blcounters[k] += 1
                    elif mode == "Suffix":
                        if nick.endswith(text): blcounters[k] += 1
                    elif mode == "Contains":
                        if text in nick: blcounters[k] += 1
                    elif mode == "Equals":
                        if text == nick: blcounters[k] += 1
            elif status == ContactStatus.NEUTRAL:
                neutral += 1
                for k in self.cfg['filters']:
                    tmp = self.cfg.get('filters', k).split('|', 2)
                    case = bool(int(tmp[0]))
                    mode = tmp[1]
                    text = tmp[2]
                    if case:
                        nick = nick.lower()
                        text = text.lower()
                    if mode == "Prefix":
                        if nick.startswith(text): ncounters[k] += 1
                    elif mode == "Suffix":
                        if nick.endswith(text): ncounters[k] += 1
                    elif mode == "Contains":
                        if text in nick: ncounters[k] += 1
                    elif mode == "Equals":
                        if text == nick: ncounters[k] += 1
            else:
                unknown += 1
                for k in self.cfg['filters']:
                    tmp = self.cfg.get('filters', k).split('|', 2)
                    case = bool(int(tmp[0]))
                    mode = tmp[1]
                    text = tmp[2]
                    if case:
                        nick = nick.lower()
                        text = text.lower()
                    if mode == "Prefix":
                        if nick.startswith(text): ucounters[k] += 1
                    elif mode == "Suffix":
                        if nick.endswith(text): ucounters[k] += 1
                    elif mode == "Contains":
                        if text in nick: ucounters[k] += 1
                    elif mode == "Equals":
                        if text == nick: ucounters[k] += 1
            if "LastSeenEpoch" in contact and detailed:
                if contact["LastSeenEpoch"] < first:
                    first = contact["LastSeenEpoch"]
                    firstc = contact
                if contact["LastSeenEpoch"] > last:
                    last = contact["LastSeenEpoch"]
                    lastc = contact
        sum = buddies + blocked + neutral + unknown
        msg = ["[u]My Contact Stats[/u]:"]
        tmp = []
        for c in counters:
            tmp.append("{}: {} ({}%)".format(c.title(), counters[c],
                                             percentage(counters[c], sum)))
        msg.append("Sum: [b]{}[/b] {}".format(sum, " | ".join(tmp)))
        if buddies > 0:
            tmp = []
            for c in bcounters:
                tmp.append("{}: {} ({}%)".format(c.title(), bcounters[c],
                                                 percentage(bcounters[c],
                                                            sum)))
            msg.append(
                "[color=green]Buddies[/color]: [b]{}[/b] ({}%) {}".format(
                    buddies, percentage(buddies, sum), " | ".join(tmp)))
        if blocked > 0:
            tmp = []
            for c in blcounters:
                tmp.append("{}: {} ({}%)".format(
                    c.title(), blcounters[c], percentage(blcounters[c], sum)))
            msg.append("[color=red]Blocked[/color]: [b]{}[/b] ({}%) {}".format(
                blocked, percentage(blocked, sum), " | ".join(tmp)))
        if neutral > 0:
            tmp = []
            for c in ncounters:
                tmp.append("{}: {} ({}%)".format(c.title(), ncounters[c],
                                                 percentage(ncounters[c],
                                                            sum)))
            msg.append("Neutral: [b]{}[/b] ({}%) {}".format(
                neutral, percentage(neutral, sum), " | ".join(tmp)))
        if unknown > 0:
            tmp = []
            for c in ucounters:
                tmp.append("{}: {} ({}%)".format(c.title(), ucounters[c],
                                                 percentage(ucounters[c],
                                                            sum)))
            msg.append(
                "[color=orange]Unknown[/color]: [b]{}[/b] ({}%) {}".format(
                    unknown, percentage(unknown, sum), " | ".join(tmp)))
        if detailed and first:
            msg.append("First: {} {} {} on {}".format(
                firstc["LastSeen"].replace("T", " "),
                self.readableContactStatus(firstc),
                clientURL(1, 0, firstc["IDS"],
                          firstc["Nickname"].decode("utf-8", "ignore")),
                channelURL(
                    1, 0,
                    firstc["LastSeenServerName"].decode("utf-8", "ignore"))))
        if detailed and last:
            msg.append("Last: {} {} {} on {}".format(
                lastc["LastSeen"].replace("T", " "),
                self.readableContactStatus(firstc),
                clientURL(1, 0, lastc["IDS"],
                          lastc["Nickname"].decode("utf-8", "ignore")),
                channelURL(
                    1, 0,
                    lastc["LastSeenServerName"].decode("utf-8", "ignore"))))
        return "\n".join(msg)

    def readableContactStatus(self, contact):
        if contact["Friend"] == ContactStatus.FRIEND:
            return "[color=green]Friend[/color]"
        elif contact["Friend"] == ContactStatus.BLOCKED:
            return "[color=red]Blocked[/color]"
        elif contact["Friend"] == ContactStatus.NEUTRAL:
            return "Neutral"
        else:
            return "[color=orange]Unknown[/color]"

    def infoData(self, schid, id, atype):
        if self.count < 3:
            self.count += 1
            return None
        clist = list()
        if atype == ts3defines.PluginItemType.PLUGIN_SERVER:
            (err, clist) = ts3lib.getClientList(schid)
        elif atype == ts3defines.PluginItemType.PLUGIN_CHANNEL:
            return None
            (err, clist) = ts3lib.getChannelClientList(schid, id)
        else:
            return None
        sum = 0
        buddies = 0
        blocked = 0
        neutral = 0
        unknown = 0
        uidlist = []
        for clid in clist:
            (err, uid) = ts3lib.getClientVariable(
                schid, clid,
                ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
            uidlist.append(uid)
        db = ts3client.Config()
        q = db.query("SELECT * FROM contacts")
        while q.next():
            sum += 1
            val = q.value("value").split('\n')
            uid = ""
            for line in val:
                if line.startswith('IDS='):
                    uid = line.split('IDS=')[1]
            if not uid in uidlist: continue
            for line in val:
                if line.startswith('Friend='):
                    status = int(line[-1])
                    if status == ContactStatus.FRIEND: buddies += 1
                    elif status == ContactStatus.BLOCKED: blocked += 1
                    elif status == ContactStatus.NEUTRAL: neutral += 1
                    else: unknown += 1
        del db
        _return = list()
        _sum = buddies + blocked + neutral + unknown
        _return.append("Online: {} / {} ({}%)".format(_sum, sum,
                                                      percentage(_sum, sum)))
        _return.append("[color=green]Buddies[/color]: {} ({}%)".format(
            buddies, percentage(buddies, _sum)))
        _return.append("[color=red]Blocked[/color]: {} ({}%)".format(
            blocked, percentage(blocked, _sum)))
        _return.append("Neutral: {} ({}%)".format(neutral,
                                                  percentage(neutral, _sum)))
        if unknown > 0:
            _return.append("[color=orange]Unknown[/color]: {} ({}%)".format(
                unknown, percentage(unknown, _sum)))
        return _return
예제 #41
0
class chatBot(ts3plugin):
    name = "Chat Bot"
    apiVersion = 22
    requestAutoload = False
    version = "1.0"
    author = "Bluscream"
    description = "A simple chatbot for Teamspeak 3 Clients"
    offersConfigure = True
    commandKeyword = ""
    infoTitle = None
    menuItems = []
    hotkeys = []
    ini = path.join(pytson.getPluginPath(), "scripts", "chatBot", "settings.ini")
    cfg = ConfigParser()
    cmdini = path.join(pytson.getPluginPath(), "scripts", "chatBot", "commands.ini")
    cmd = ConfigParser()
    # cmdpy = path.join(pytson.getPluginPath(), "scripts", "chatBot")
    dlg = None
    color = []
    cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}
    lastcmd = {"cmd": "", "params": "", "time": 0, "user": 0}
    returnCode = ""
    noperms = []
    tmpsgroups = []
    tmpcgroups = []

    def timestamp(self): return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now())

    def __init__(self):
        if path.isfile(self.ini):
            self.cfg.read(self.ini)
        else:
            self.cfg['general'] = {"cfgversion": "1", "debug": "False", "enabled": "True", "customprefix": "True", "prefix": "!", "unknowncmd": "True"}
            with open(self.ini, 'w') as configfile:
                self.cfg.write(configfile)
        if path.isfile(self.cmdini):
            self.cmd.read(self.cmdini)
        else:
            self.cmd['about'] = {"enabled": "True", "function": "commandAbout"}
            self.cmd['help'] = {"enabled": "False", "function": "commandHelp"}
            with open(self.cmdini, 'w') as configfile:
                self.cmd.write(configfile)
        if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("{0}[color=orange]{1}[/color] Plugin for pyTSon by [url=https://github.com/{2}]{2}[/url] loaded.".format(self.timestamp(), self.name, self.author))

    def configure(self, qParentWidget):
        try:
            if not self.dlg: self.dlg = SettingsDialog(self.ini, self.cfg, self.cmdini, self.cmd)
            self.dlg.show()
            self.dlg.raise_()
            self.dlg.activateWindow()
            if path.isfile(self.ini):
                self.cfg.read(self.ini)
        except:
            from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon")

    def onTextMessageEvent(self, schid, targetMode, toID, fromID, fromName, fromUniqueIdentifier, message, ffIgnored):
        try:
            if ffIgnored: return False
            (error, ownID) = ts3lib.getClientID(schid)
            lasttime = int(self.lastcmd["time"])
            time = int(timestamp.time())
            (error, _clid) = ts3lib.getClientID(schid)
            if targetMode == ts3defines.TextMessageTargetMode.TextMessageTarget_CLIENT and toID != _clid: return
            # if targetMode == ts3defines.TextMessageTargetMode.TextMessageTarget_CHANNEL and toID != _cid: return False
            # ts3lib.printMessageToCurrentTab(self.clientURL(schid, _clid))
            # ts3lib.printMessageToCurrentTab(message)
            # ts3lib.printMessageToCurrentTab("%s"%message.startswith(self.clientURL(schid, _clid)))
            # ts3lib.printMessageToCurrentTab("%s"%str(self.clientURL(schid, _clid) in message.strip()))
            if message.startswith(self.cfg.get('general', 'prefix')) and self.cfg.getboolean('general', 'customprefix'):
                command = message.split(self.cfg.get('general', 'prefix'), 1)[1]
            elif message.startswith(self.clientURL(schid, _clid)) and not self.cfg.getboolean('general', 'customprefix'):
                command = message.split(self.clientURL(schid, _clid), 1)[1]
            else: return False
            if self.cfg.getboolean("general", "debug"):
                ts3lib.printMessageToCurrentTab("{0}".format(self.lastcmd))
                ts3lib.printMessageToCurrentTab("time: {0}".format(time))
                ts3lib.printMessageToCurrentTab("time -5: {0}".format(time - 5))
                ts3lib.printMessageToCurrentTab("lasttime: {0}".format(lasttime))
            if lasttime > time - 5: ts3lib.printMessageToCurrentTab("is time -5: True")
            cmd = command.split(' ', 1)[0].lower()
            if not cmd in self.cmd.sections():
                if self.cfg.getboolean("general", "unknowncmd"): self.answerMessage(schid, targetMode, toID, fromID, "Command %s does not exist." % cmd)
                return False
            if not self.cmd.getboolean(cmd, "enabled"):
                if self.cfg.getboolean("general", "disabledcmd"): self.answerMessage(schid, targetMode, toID, fromID, "Command %s is disabled." % cmd)
                return False
            params = ""
            _params = ""
            try: _params = command.split(' ', 1)[1].strip()
            except: pass
            if _params != "": params = _params  # ;params = bytes(_params, "utf-8").decode("unicode_escape")
            self.lastcmd = {"cmd": cmd, "params": params, "time": int(timestamp.time()), "user": fromID}
            ts3lib.printMessageToCurrentTab("{0}".format(self.lastcmd))
            if targetMode == ts3defines.TextMessageTargetMode.TextMessageTarget_CHANNEL: (
            error, toID) = ts3lib.getChannelOfClient(schid, _clid)
            evalstring = "self.%s(%s,%s,%s,%s,'%s')" % (
            self.cmd.get(cmd, "function"), schid, targetMode, toID, fromID, params)
            eval(evalstring)
        except:
            from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0)

    def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber):
        if newStatus == ts3defines.ConnectStatus.STATUS_DISCONNECTED:
            if schid in self.noperms: self.noperms.remove(schid)

    def onServerPermissionErrorEvent(self, schid, errorMessage, error, returnCode, failedPermissionID):
        if self.returnCode == returnCode and error == 2568 and failedPermissionID == 217: self.noperms.extend([schid])

    def answerMessage(self, schid, targetMode, toID, fromID, message, hideprefix=False):
        if schid in self.noperms: ts3lib.printMessageToCurrentTab("Insufficient permissions to answer message from {0}".format(fromID)); return
        message = [message[i:i + 1024] for i in range(0, len(message), 1024)]
        if targetMode == ts3defines.TextMessageTargetMode.TextMessageTarget_CLIENT:
            for msg in message: self.returnCode = ts3lib.createReturnCode(); ts3lib.requestSendPrivateTextMsg(schid, msg, fromID, self.returnCode)
        elif targetMode == ts3defines.TextMessageTargetMode.TextMessageTarget_CHANNEL:
            if hideprefix:
                for msg in message: self.returnCode = ts3lib.createReturnCode(); ts3lib.requestSendChannelTextMsg(schid, "{0}".format(msg), toID, self.returnCode)
            else:
                for msg in message: self.returnCode = ts3lib.createReturnCode(); ts3lib.requestSendChannelTextMsg(schid, "[url=client://]@[/url]%s: %s" % ( self.clientURL(schid, fromID), msg), toID, self.returnCode)

    def clientURL(self, schid=None, clid=0, uid=None, nickname=None, encodednick=None):
        if schid == None:
            try: schid = ts3lib.getCurrentServerConnectionHandlerID()
            except: pass
        if uid == None:
            try: (error, uid) = ts3lib.getClientVariableAsString(schid, clid, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
            except: pass
        if nickname == None:
            try: (error, nickname) = ts3lib.getClientVariableAsString(schid, clid, ts3defines.ClientProperties.CLIENT_NICKNAME)
            except: nickname = uid
        if encodednick == None:
            try: encodednick = urlencode(nickname)
            except: pass
        return "[url=client://%s/%s~%s]%s[/url]" % (clid, uid, encodednick, nickname)

    # YOUR COMMANDS HERE:

    def commandAbout(self, schid, targetMode, toID, fromID, params=""):
        self.answerMessage(schid, targetMode, toID, fromID, "%s v%s by %s" % (self.name, self.version, self.author))

    def commandHelp(self, schid, targetMode, toID, fromID, params=""):
        _cmds = "\n"
        if self.cfg.getboolean('general', 'customprefix'):
            prefix = self.cfg.get('general', 'prefix')
        else:
            (error, id) = ts3lib.getClientID(schid);prefix = self.clientURL(schid, id)
        for command in self.cmd.sections():
            if self.cmd.getboolean(command, "enabled"):
                _cmds += prefix + str(command) + "\n"
            else:
                _cmds += prefix + str(command) + " (Disabled)\n"
        self.answerMessage(schid, targetMode, toID, fromID, "Available commands for %s v%s:%s" % (self.name, self.version, _cmds), True)

    def commandToggle(self, schid, targetMode, toID, fromID, params=""):
        (error, ownID) = ts3lib.getClientID(schid)
        if not fromID == ownID: return
        self.cmd.set(params, "enabled", str(not self.cmd.getboolean(params, "enabled")))
        self.answerMessage(schid, targetMode, toID, fromID, "Set command {0} to {1}".format(params, self.cmd.getboolean(params, "enabled")))

    def commandEval(self, schid, targetMode, toID, fromID, params=""):
        (error, ownID) = ts3lib.getClientID(schid)
        if not fromID == ownID: return
        try:
            ev = eval(params)
            self.answerMessage(schid, targetMode, toID, fromID, "Evalualated {0}successfully{1}:\n{2}".format(color.SUCCESS, color.ENDMARKER, ev))
        except TypeError as e:
            if e.strerror == "eval() arg 1 must be a string, bytes or code object":
                self.answerMessage(schid, targetMode, toID, fromID,
                                   "%s%s evalualated successfully: %s" % (color.SUCCESS, params, ev))
            else:
                from traceback import format_exc;
                self.answerMessage(schid, targetMode, toID, fromID, format_exc())
        except SyntaxError as e:
            if e.strerror == "unexpected EOF while parsing":
                self.answerMessage(schid, targetMode, toID, fromID,
                                   "%s%s evalualated successfully: %s" % (color.SUCCESS, params, ev))
            else:
                from traceback import format_exc;
                self.answerMessage(schid, targetMode, toID, fromID, format_exc())
        except: from traceback import format_exc; self.answerMessage(schid, targetMode, toID, fromID, format_exc())

    def commandTime(self, schid, targetMode, toID, fromID, params=""):
        self.answerMessage(schid, targetMode, toID, fromID, 'My current time is: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now()))

    def commandUnix(self, schid, targetMode, toID, fromID, params=""):
        self.answerMessage(schid, targetMode, toID, fromID, datetime.datetime.utcfromtimestamp(int(params)).strftime('%Y-%m-%d %H:%M:%S'))

    def commandTaskList(self, schid, targetMode, toID, fromID, params=""):
        import psutil
        msg = []
        for p in psutil.process_iter():
            try:
                _p = str(p.as_dict(attrs=['name'])['name'])
                if ".exe" in _p.lower(): msg.extend([_p])
            except psutil.Error: pass
        msg = '\n'.join(sorted(msg))
        self.answerMessage(schid, targetMode, toID, fromID, msg)

    def idByName(self,ids,name):
        for i in ids:
            if name.lower() in i["name"].lower(): return i["id"]
        return False

    def commandToggleServerGroup(self, schid, targetMode, toID, fromID, params=""):
        self.cmdevent = {"event": "onServerGroupListEvent", "returnCode": "", "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
        ts3lib.requestServerGroupList(schid)

    def onServerGroupListEvent(self, schid, serverGroupID, name, atype, iconID, saveDB):
        try:
            if not self.cmdevent["event"] == "onServerGroupListEvent": return
            self.tmpsgroups.append({"id": serverGroupID, "name": name})
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0)

    def onServerGroupListFinishedEvent(self, schid):
        try:
            sgid = self.idByName(self.tmpsgroups,self.cmdevent["params"])
            if not sgid: self.answerMessage(schid, self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "Failed to find a servergroup like \"%s\""%self.cmdevent["params"]);return
            (error, dbid) = ts3lib.getClientVariableAsInt(schid, self.cmdevent["fromID"], ts3defines.ClientPropertiesRare.CLIENT_DATABASE_ID)
            (error, sgroups) = ts3lib.getClientVariableAsString(schid, self.cmdevent["fromID"], ts3defines.ClientPropertiesRare.CLIENT_SERVERGROUPS)
            sgroups = [int(n) for n in sgroups.split(",")]
            if sgid in sgroups: _p = "added";p = "Adding"; error = ts3lib.requestServerGroupDelClient(schid, sgid, dbid)
            else: _p = "removed";p = "Removing"; error = ts3lib.requestServerGroupAddClient(schid, sgid, dbid)
            if error == ts3defines.ERROR_ok: _t = "Successfully {0} servergroup #{1}".format(_p, sgid)
            else: _t = "{0} Servergroup #{1} failed!".format(p, sgid)
            self.answerMessage(schid, self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], _t)
            self.tmpsgroups = []
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0)
        self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}

    def commandOP(self, schid, targetMode, toID, fromID, params=""):
        target = int(params)
        (error, dbid) = ts3lib.getClientVariableAsInt(schid, target, ts3defines.ClientPropertiesRare.CLIENT_DATABASE_ID)
        (error, chan) = ts3lib.getChannelOfClient(schid, target)
        (error, name) = ts3lib.getChannelVariableAsString(schid, chan, ts3defines.ChannelProperties.CHANNEL_NAME)
        error = ts3lib.requestSetClientChannelGroup(schid, [11], [chan], [dbid])
        if error == ts3defines.ERROR_ok:
            _t = "You have been made operator of the channel [url=channelid://{0}]{1}[/url].".format(chan,name)
            self.answerMessage(schid, ts3defines.TextMessageTargetMode.TextMessageTarget_CLIENT, toID, target, _t)

    def commandSetChannelGroup(self, schid, targetMode, toID, fromID, params=""):
        self.cmdevent = {"event": "onChannelGroupListEvent", "returnCode": "", "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
        self.tmpcgroups = []
        ts3lib.requestChannelGroupList(schid)

    def onChannelGroupListEvent(self, schid, channelGroupID, name, atype, iconID, saveDB):
        try:
            if not self.cmdevent["event"] == "onChannelGroupListEvent" or not atype == 1: return
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("atype: {0}".format(atype))
            self.tmpcgroups.append({"id": channelGroupID, "name": name})
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0)

    def onChannelGroupListFinishedEvent(self, schid):
        try:
            id = self.idByName(self.tmpcgroups,self.cmdevent["params"])
            if not id: self.answerMessage(schid, self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "Failed to find a channelgroup like \"%s\""%self.cmdevent["params"]);return
            (error, dbid) = ts3lib.getClientVariableAsInt(schid, self.cmdevent["fromID"], ts3defines.ClientPropertiesRare.CLIENT_DATABASE_ID)
            (error, own) = ts3lib.getClientID(schid)
            (error, chan) = ts3lib.getChannelOfClient(schid, own)
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("dbid: {0} | own: {1} | chan: {2} | id: {3}".format(dbid,own,chan,id))
            error = ts3lib.requestSetClientChannelGroup(schid, [id], [chan], [dbid])
            if error == ts3defines.ERROR_ok: _t = "Successfully set your channelgroup to #{0}".format(id)
            else: _t = "Setting your channelgroup #{0} failed!".format(id)
            self.answerMessage(schid, self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], _t)
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0)
        self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}

    def commandSay(self, schid, targetMode, toID, fromID, params=""):
        if targetMode == ts3defines.TextMessageTargetMode.TextMessageTarget_CLIENT:
            ts3lib.requestSendPrivateTextMsg(schid, params, fromID)
        elif targetMode == ts3defines.TextMessageTargetMode.TextMessageTarget_CHANNEL:
            ts3lib.requestSendChannelTextMsg(schid, "{0}: {1}".format(self.clientURL(schid, fromID), params), toID)

    def commandMessage(self, schid, targetMode, toID, fromID, params=""):
        params = params.split(" ",1);target = int(params[0]);message = params[1]
        ts3lib.requestSendPrivateTextMsg(schid, "Message from {0}: {1}".format(self.clientURL(schid, fromID), message), target)

    def commandChannelMessage(self, schid, targetMode, toID, fromID, params=""):
        try:
            _p = params.split(" ",1);target = int(_p[0]);message = _p[1]
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Found Channel ID: {0}".format(target))
        except:
            (error, target) = ts3lib.getChannelOfClient(schid, fromID);message = params
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Found No Channel ID.")
        (error, ownID) = ts3lib.getClientID(schid)
        (error, ownChan) = ts3lib.getChannelOfClient(schid, ownID)
        if not ownChan == target: ts3lib.requestClientMove(schid, ownID, target, "123")
        ts3lib.requestSendChannelTextMsg(schid, "Message from {0}: {1}".format(self.clientURL(schid, fromID), message), target)
        if not ownChan == target: ts3lib.requestClientMove(schid, ownID, ownChan, "123")

    def commandPing(self, schid, targetMode, toID, fromID, params=""):
        self.answerMessage(schid, targetMode, toID, fromID, "Pong!")

    def commandWhoAmI(self, schid, targetMode, toID, fromID, params=""):
        (error, displayName) = ts3lib.getClientDisplayName(schid, fromID)
        self.answerMessage(schid, targetMode, toID, fromID, "I changed your nickname to: %s%s" % (color.ERROR, displayName))

    def commandChannelKickMe(self, schid, targetMode, toID, fromID, params=""):
        if self.cfg.getboolean('general', 'customprefix'):
            prefix = self.cfg.get('general', 'prefix')
        else:
            (error, id) = ts3lib.getClientID(schid);prefix = self.clientURL(schid, id)
        (error, nickname) = ts3lib.getClientVariableAsString(schid, fromID, ts3defines.ClientProperties.CLIENT_NICKNAME)
        if params != "": ts3lib.requestClientKickFromChannel(schid, fromID, params)
        else: ts3lib.requestClientKickFromChannel(schid, fromID, "Command %sckickme used by %s" % (prefix, nickname))

    def commandChannelBanMe(self, schid, targetMode, toID, fromID, params=""):
        (error, ownID) = ts3lib.getClientID(schid)
        if self.cfg.getboolean('general', 'customprefix'): prefix = self.cfg.get('general', 'prefix')
        else: prefix = self.clientURL(schid, ownID)
        (error, nickname) = ts3lib.getClientVariableAsString(schid, fromID, ts3defines.ClientProperties.CLIENT_NICKNAME)
        (error, dbid) = ts3lib.getClientVariableAsInt(schid, fromID, ts3defines.ClientPropertiesRare.CLIENT_DATABASE_ID)
        (error, chan) = ts3lib.getChannelOfClient(schid, ownID)
        if params == "": params = "Command %scbanme used by %s" % (prefix, nickname)
        ts3lib.requestSetClientChannelGroup(schid, [12], [chan], [dbid])
        ts3lib.requestClientKickFromChannel(schid, fromID, params)

    def commandKickMe(self, schid, targetMode, toID, fromID, params=""):
        if self.cfg.getboolean('general', 'customprefix'):
            prefix = self.cfg.get('general', 'prefix')
        else:
            (error, id) = ts3lib.getClientID(schid);prefix = self.clientURL(schid, id)
        (error, nickname) = ts3lib.getClientVariableAsString(schid, fromID, ts3defines.ClientProperties.CLIENT_NICKNAME)
        if params != "": ts3lib.requestClientKickFromServer(schid, fromID, params)
        else: ts3lib.requestClientKickFromServer(schid, fromID, "Command %skickme used by %s" % (prefix, nickname))

    def commandBanMe(self, schid, targetMode, toID, fromID, params=""):
        if self.cfg.getboolean('general', 'customprefix'):
            prefix = self.cfg.get('general', 'prefix')
        else:
            (error, id) = ts3lib.getClientID(schid);prefix = self.clientURL(schid, id)
        (error, nickname) = ts3lib.getClientVariableAsString(schid, fromID, ts3defines.ClientProperties.CLIENT_NICKNAME)
        if params != "": _params = params.split(' ', 1)
        delay = 1;
        delay = _params[0]
        if len(_params) > 1: ts3lib.banclient(schid, fromID, int(delay), _params[1])
        else: ts3lib.banclient(schid, fromID, int(delay), "Command %sbanme used by %s" % (prefix, nickname))

    def commandQuit(self, schid, targetMode, toID, fromID, params=""):
        try: import sys;sys.exit()
        except: pass
        try: QApplication.quit()
        except: pass
        try: QCoreApplication.instance().quit()
        except: pass

    def commandDisconnect(self, schid, targetMode, toID, fromID, params=""):
        if self.cfg.getboolean('general', 'customprefix'):
            prefix = self.cfg.get('general', 'prefix')
        else:
            (error, id) = ts3lib.getClientID(schid);prefix = self.clientURL(schid, id)
        (error, nickname) = ts3lib.getClientVariableAsString(schid, fromID, ts3defines.ClientProperties.CLIENT_NICKNAME)
        if params != "":
            ts3lib.stopConnection(schid, params)
        else:
            ts3lib.stopConnection(schid, "Command %sdisconnect used by %s" % (prefix, nickname))

    def commandConnect(self, schid, targetMode, toID, fromID, params=""):
        params = params.split(' ', 1)
        ip = params[0].split(':')
        nickname = ""
        if params[1]: nickname = params[1]
        ts3lib.stopConnection(schid, "Connecting to %s" % ip)
        ts3lib.startConnection(schid, "", ip[0], int(ip[1]), nickname, [], "", "")

    def commandVersion(self, schid, targetMode, toID, fromID, params=""): pass

    def commandToggleRecord(self, schid, targetMode, toID, fromID, params=""):
        (error, clid) = ts3lib.getClientID(schid)
        (error, recording) = ts3lib.getClientVariableAsInt(schid, clid, ts3defines.ClientProperties.CLIENT_IS_RECORDING)
        if not recording:
            ts3lib.startVoiceRecording(schid)
        elif recording:
            ts3lib.stopVoiceRecording(schid)

    def commandNick(self, schid, targetMode, toID, fromID, params=""):
        ts3lib.setClientSelfVariableAsString(schid, ts3defines.ClientProperties.CLIENT_NICKNAME, params)
        ts3lib.flushClientSelfUpdates(schid)

    def commandBanList(self, schid, targetMode, toID, fromID, params=""):
        # try:
        returnCode = ts3lib.createReturnCode()
        self.cmdevent = {"event": "onBanListEvent", "returnCode": returnCode, "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
        self.banlist = ""
        QTimer.singleShot(2500, self.sendBanList)
        ts3lib.requestBanList(schid)

    # except:

    def onBanListEvent(self, schid, banid, ip, name, uid, creationTime, durationTime, invokerName, invokercldbid, invokeruid, reason, numberOfEnforcements, lastNickName):
        item = ""
        item += "#%s" % banid
        if name: item += " | Name: %s" % name
        if ip: item += " | IP: %s" % ip
        if uid: item += " | UID: %s" % uid
        if reason: item += " | Reason: %s" % reason
        self.banlist += "\n%s" % item


    def sendBanList(self):
        ts3lib.requestSendPrivateTextMsg(self.cmdevent.schid, "%s" % self.banlist, self.cmdevent.fromID)
        self.answerMessage(self.cmdevent.schid, self.cmdevent.targetMode, self.cmdevent.toID, self.cmdevent.fromID, "%s" % self.banlist)
        self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}

    def commandMessageBox(self, schid, targetMode, toID, fromID, params=""):
        msgBox = QMessageBox()
        # if params.lower().startswith("[url]"):
        # params = params.split("[URL]")[1]
        # params = params.split("[/URL]")[0]
        # msgBox.setIconPixmap(QPixMap(params));
        # else:
        msgBox.setText(params)
        msgBox.setIcon(QMessageBox.Warning)
        msgBox.exec()

    def commandGoogle(self, schid, targetMode, toID, fromID, params=""):
        try:
            from PythonQt.QtNetwork import QNetworkAccessManager, QNetworkRequest
            from urllib.parse import quote_plus
            googleAPI = "https://www.googleapis.com/customsearch/v1"
            googleAPIKey = "AIzaSyDj5tgIBtdiL8pdVV_tqm7aw45jjdFP1hw"
            googleSearchID = "008729515406769090877:33fok_ycoaa"
            params = quote_plus(params)
            url = "{0}?key={1}&cx={2}&q={3}".format(googleAPI, googleAPIKey, googleSearchID, params)
            self.nwmc = QNetworkAccessManager()
            self.nwmc.connect("finished(QNetworkReply*)", self.googleReply)
            self.cmdevent = {"event": "", "returnCode": "", "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
            self.nwmc.get(QNetworkRequest(QUrl(url)))
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)


    def googleReply(self, reply):
        try:
            import json;from PythonQt.QtNetwork import QNetworkRequest, QNetworkReply
            results = json.loads(reply.readAll().data().decode('utf-8'))["items"]
            for result in results:
                self.answerMessage(self.cmdevent["schid"], self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "[url={0}]{1}[/url]".format(result["link"],result["title"]), True)
            self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)

    def commandFlood(self, schid, targetMode, toID, fromID, params=""):
        self.answerMessage(schid, targetMode, toID, fromID, "Flooding {0} started...".format(params))

    def commandFindMe(self, schid, targetMode, toID, fromID, params=""):
        (error, ownID) = ts3lib.getClientID(schid)
        if not fromID == ownID: self.answerMessage(schid, targetMode, toID, fromID, "Insufficient permissions to run this command");return

    def commandLookup(self, schid, targetMode, toID, fromID, params=""):
        try:
            from PythonQt.QtNetwork import QNetworkAccessManager, QNetworkRequest
            from urllib.parse import quote_plus
            lookupAPI = "https://api.opencnam.com/v3/phone/"
            lookupSID = "ACda22b69608b743328772059d32b63f26"
            lookupAuthToken = "AUc9d9217f20194053bf2989c7cb75a368"
            if params.startswith("00"): params = params.replace("00", "+", 1)
            params = quote_plus(params)
            url = "{0}{1}?format=json&casing=title&service_level=plus&geo=rate&account_sid={2}&auth_token={3}".format(lookupAPI, params, lookupSID, lookupAuthToken)
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Requesting: {0}".format(url))
            self.nwmc = QNetworkAccessManager()
            self.nwmc.connect("finished(QNetworkReply*)", self.lookupReply)
            self.cmdevent = {"event": "", "returnCode": "", "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
            self.nwmc.get(QNetworkRequest(QUrl(url)))
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)

    def lookupReply(self, reply):
        try:
            import json;from PythonQt.QtNetwork import QNetworkRequest, QNetworkReply
            result = json.loads(reply.readAll().data().decode('utf-8'))
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Result: {0}".format(result))
            try: self.answerMessage(self.cmdevent["schid"], self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "{0}: {1} ({2}$/min)".format(result["number"],result["name"],result["price"]), True)
            except: self.answerMessage(self.cmdevent["schid"], self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "{0}{1}{2} ({3})".format(color.ERROR, result["err"], color.ENDMARKER,self.cmdevent["params"]))
            self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)

    def commandRegister(self, schid, targetMode, toID, fromID, params=""):
        (error, uid) = ts3lib.getServerVariableAsString(schid, ts3defines.VirtualServerProperties.VIRTUALSERVER_UNIQUE_IDENTIFIER)
        if uid == "QTRtPmYiSKpMS8Oyd4hyztcvLqU=": # GommeHD
            (error, uid) = ts3lib.getClientVariableAsString(schid, int(params), ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
            self.answerMessage(schid, targetMode, toID, int(params), ""+
            "Um dich auf diesem Teamspeak Server zu registrieren musst du folgendes tun:\n\n"+
            "1. Auf den Minecraft Server [color=green]gommehd.net[/color] joinen.\n"+
            "2. In den Minecraft chat [color=red]/ts set {0}[/color] eingeben.\n".format(uid)+
            "3. Im Teamspeak Chat dem User [URL=client://0/serveradmin~Gomme-Bot]Gomme-Bot[/URL] deinen Minecraft Namen schreiben (Groß/Kleinschreibung beachten)\n"+
            "4. Wenn die Registrierung erfolgreich warst erhälst du die Server Gruppe \"Registriert\". Es kann eine Zeit lang dauern bis dein Minecraft Kopf hinter deinem Namen erscheint.")
        elif uid == "U3UjHePU9eZ9bvnzIyLff4lvXBM=": pass
        else: self.answerMessage(schid, targetMode, toID, fromID, "Server not recognized or does not have a registration feature.")

    def commandDoxx(self, schid, targetMode, toID, fromID, params=""):
        try:
            from PythonQt.QtNetwork import QNetworkAccessManager, QNetworkRequest
            url = "https://randomuser.me/api/?gender={0}&nat=de&noinfo".format(params.split(" ")[1])
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Requesting: {0}".format(url))
            self.nwmc = QNetworkAccessManager()
            self.nwmc.connect("finished(QNetworkReply*)", self.doxxReply)
            self.cmdevent = {"event": "", "returnCode": "", "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
            self.nwmc.get(QNetworkRequest(QUrl(url)))
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)

    def doxxReply(self, reply):
        try:
            import json;from PythonQt.QtNetwork import QNetworkRequest, QNetworkReply;from random import randint
            result = json.loads(reply.readAll().data().decode('utf-8'))["results"][0]
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Result: {0}".format(result))
            params = self.cmdevent["params"].split(" ")
            (error, name) = ts3lib.getClientVariableAsString(int(self.cmdevent["schid"]), int(params[0]), ts3defines.ClientProperties.CLIENT_NICKNAME)
            (error, uid) = ts3lib.getClientVariableAsString(int(self.cmdevent["schid"]), int(params[0]), ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER)
            #try:
            self.answerMessage(self.cmdevent["schid"], self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"],
                "\nTS Name: [url=http://ts3index.com/?page=searchclient&nickname={0}]{0}[/url] | UID: [url=http://ts3index.com/?page=searchclient&uid={1}]{1}[/url]\n".format(name, uid)+
                "{0} {1}\n".format(result["name"]["first"], result["name"]["last"]).title()+
                "{0} {1}\n".format(result["location"]["street"][5:],randint(0,50)).title()+
                "{0} {1}\n".format(result["location"]["postcode"],result["location"]["city"]).title()+
                "☎ {0} ({1})\n".format(result["phone"],result["cell"])+
                "[url=https://adguardteam.github.io/AnonymousRedirect/redirect.html?url={0}]Bild 1[/url]\n".format(result["picture"]["large"]), True)
            #except: self.answerMessage(self.cmdevent["schid"], self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "Unable to doxx {0}".format(name))
            self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)

    perms = {}
    def commandPerms(self, schid, targetMode, toID, fromID, params=""):
        self.cmdevent = {"event": "onPermissionListEvent", "returnCode": "", "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
        ts3lib.requestPermissionList(schid)

    def onPermissionListEvent(self, schid, permissionID, permissionName, permissionDescription):
        #ts3lib.printMessageToCurrentTab("self.name: {0}".format(self.__name__))
        if self.cmdevent["event"] == "onPermissionListEvent" and self.cmdevent["schid"] == schid:
            ts3lib.printMessageToCurrentTab("#{0} | {1} | {2}".format(permissionID, permissionName, permissionDescription))
            #self.perms

    def onPermissionListFinishedEvent(self, serverConnectionHandlerID):
        ts3lib.printMessageToCurrentTab("{0}".format(self.perms))
        self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}

    def commandWhois(self, schid, targetMode, toID, fromID, params=""):
        try:
            from PythonQt.QtNetwork import QNetworkAccessManager, QNetworkRequest
            from urllib.parse import quote_plus
            params = quote_plus(params)
            url = "https://jsonwhois.com/api/v1/whois?domain={0}".format(params)
            token = "fe1abe2646bdc7fac3d36a688d1685fc"
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Requesting: {0}".format(url))
            request = QNetworkRequest()
            request.setHeader( QNetworkRequest.ContentTypeHeader, "application/json" );
            request.setRawHeader("Authorization", "Token token={0}".format(token));
            request.setUrl(QUrl(url))
            self.nwmc = QNetworkAccessManager()
            self.nwmc.connect("finished(QNetworkReply*)", self.whoisReply)
            self.cmdevent = {"event": "", "returnCode": "", "schid": schid, "targetMode": targetMode, "toID": toID, "fromID": fromID, "params": params}
            self.nwmc.get(request)
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)

    def whoisReply(self, reply):
        try:
            import json;from PythonQt.QtNetwork import QNetworkRequest, QNetworkReply
            result = json.loads(reply.readAll().data().decode('utf-8'))
            if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("Result: {0}".format(result))
            try: self.answerMessage(self.cmdevent["schid"], self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "Registrant: {0} | Admin: {1} | Tech: {2}".format(result["registrant_contacts"][0]["name"],result["admin_contacts"][0]["name"],result["technical_contacts"][0]["name"]), True)
            except: self.answerMessage(self.cmdevent["schid"], self.cmdevent["targetMode"], self.cmdevent["toID"], self.cmdevent["fromID"], "{0}{1}{2}".format(color.ERROR, result["status"], color.ENDMARKER))
            self.cmdevent = {"event": "", "returnCode": "", "schid": 0, "targetMode": 4, "toID": 0, "fromID": 0, "params": ""}
        except: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)

    oldChannelID = 0
    def commandJoin(self, schid, targetMode, toID, fromID, params=""):
        (error, target) = ts3lib.getChannelOfClient(schid, fromID)
        (error, ownID) = ts3lib.getClientID(schid)
        (error, ownChan) = ts3lib.getChannelOfClient(schid, ownID)
        if not ownChan == target: ts3lib.requestClientMove(schid, ownID, target, "123")

    def commandBack(self, schid, targetMode, toID, fromID, params=""):
        (error, ownID) = ts3lib.getClientID(schid)
        ts3lib.requestClientMove(schid, ownID, self.oldChannelID, "123")
        if self.cfg.getboolean("general", "debug"): ts3lib.printMessageToCurrentTab("self.oldChannelID: {0}".format(self.oldChannelID))

    def commandB64Encode(self, schid, targetMode, toID, fromID, params=""):
        try: msg = b64encode(params.encode('utf-8')).decode('utf-8')
        except Exception as ex: msg = "Error while encoding: {}".format(ex.__class__.__name__)
        self.answerMessage(schid, targetMode, toID, fromID, msg)

    def commandB64Decode(self, schid, targetMode, toID, fromID, params=""):
        try: msg = b64decode(params.encode('utf-8')).decode('utf-8')
        except Exception as ex: msg = "Error while decoding: {}".format(ex.__class__.__name__)
        self.answerMessage(schid, targetMode, toID, fromID, msg)

    def commandShutdown(self, schid, targetMode, toID, fromID, params=""):
        self.answerMessage(schid, targetMode, toID, fromID, "Executing \"shutdown -s -f -t 60\"")
        os.system('shutdown -s -f -t 60')

    def commandAbortShutdown(self, schid, targetMode, toID, fromID, params=""):
        self.answerMessage(schid, targetMode, toID, fromID, "Executing \"shutdown -a\"")
        os.system('shutdown -a')

    def onClientMoveEvent(self, schid, clientID, oldChannelID, newChannelID, visibility, moveMessage):
        (error, _clid) = ts3lib.getClientID(schid)
        if clientID == _clid and not oldChannelID == 0: self.oldChannelID = oldChannelID