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")
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
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)
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)
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
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
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")
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()
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"))
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)
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)
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()
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()
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
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)
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)
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
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"]))
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()
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)
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)
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)
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) """
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)
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
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
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
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))
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
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
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)
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)))
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)
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)
#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():
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)
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
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
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