def getFile(url): """ :param url: """ nwmc = QNetworkAccessManager() nwmc.connect("finished(QNetworkReply*)", _getFileReply) nwmc.get(QNetworkRequest(QUrl(url)))
class InstallDialog(QDialog, pytson.Translatable): 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 install(self, addon): self.addon = addon req = QNetworkRequest(QUrl(addon["url"])) req.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) self.nwm.get(req) self.consoleEdit.append("Downloading %s ..." % addon["url"]) def installPackage(self, pkgstr): self.pip.installPackages([pkgstr]) self.closeFrame.show() def onNetworkReply(self, reply): if reply.error() == QNetworkReply.NoError: self.consoleEdit.append("Download finished.") try: if ("application/zip" not in reply.header(QNetworkRequest.ContentTypeHeader)): self.pip.installPlugin(self.addon, reply.readAll().data(). decode('utf-8')) else: self.pip.installPlugin(self.addon, io.BytesIO(reply.readAll().data())) except Exception as e: self.consoleEdit.append("Exception during installation: %s" % e) else: self.consoleEdit.append("Network error: %s" % reply.error()) reply.deleteLater() self.closeFrame.show() def on_closeButton_clicked(self): self.accept()
def downloadFile(url, path): """ :param url: :param path: """ nwmc = QNetworkAccessManager() nwmc.connect("finished(QNetworkReply*)", _downloadFileReply) dlpath = path nwmc.get(QNetworkRequest(QUrl(url)))
def url(url): try: from PythonQt.QtNetwork import QNetworkAccessManager, QNetworkRequest #if urlrequest: return urlrequest = QNetworkAccessManager() urlrequest.connect("finished(QNetworkReply*)", urlResponse) urlrequest.get(QNetworkRequest(QUrl(url))) except: from traceback import format_exc try: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon::autorun", 0) except: print("Error in autorun: "+format_exc())
class testplugin(ts3plugin): name = "Link Steam" requestAutoload = False version = "1" apiVersion = 21 author = "OhanesianAndreiLaurentiu" description = "Link Steam, add a feature in teamspeak 3 where you can click a steam link and is open in your steam client instead of your default browser." offersConfigure = False commandKeyword = "" infoTitle = "" menuItems = [] hotkeys = [] domains = ["steamcommunity.com", "store.steampowered.com"] updateurl = "https://raw.githubusercontent.com/oandreilaurentiu/linksteam/master/version.json" repourl = "https://github.com/{}/{}/releases".format(author, name) def __init__(self): ts3lib.printMessageToCurrentTab("Steamlinker " + self.version + " loaded") self.nwmc = QNetworkAccessManager() self.nwmc.connect("finished(QNetworkReply*)", self.updateReply) self.nwmc.get(QNetworkRequest(QUrl(self.updateurl))) def updateReply(self, reply): version = loads(reply.readAll().data().decode('utf-8'))["version"] if version != self.version: x = QDialog() x.setAttribute(Qt.WA_DeleteOnClose) _x = QMessageBox.question( x, "{} v{} by {}".format(self.name, self.version, self.author), "Noua versiune v{} la linksteam a fost gasita, dai update acum?" .format(version), QMessageBox.Yes, QMessageBox.No) if _x == QMessageBox.Yes: QDesktopServices.openUrl(QUrl(self.repourl)) def onTextMessageEvent(self, schid, targetMode, toID, fromID, fromName, fromUniqueIdentifier, message, ffIgnored): for url in self.domains: if url in message: ts3lib.printMessageToCurrentTab("[URL=steam://openurl/" + message[5:-6] + "]Open in Steam.[/URL]") return
class autoTPRequest(ts3plugin): name = "Auto Talk Power Request" apiVersion = 22 requestAutoload = False version = "1.0" author = "Bluscream" description = "Automatically request talk power when switching channels.\n\nCheck out https://r4p3.net/forums/plugins.68/ for more plugins." offersConfigure = False commandKeyword = "" infoTitle = None menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Toggle Auto Talk Power", "")] hotkeys = [] debug = False msg = "" toggle = True schid = 0 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 menuItemID == 0: self.toggle = not self.toggle ts3lib.printMessageToCurrentTab( "{0}Set {1} to [color=yellow]{2}[/color]".format( self.timestamp(), self.name, self.toggle)) def onClientMoveEvent(self, schid, clientID, oldChannelID, newChannelID, visibility, moveMessage): if not self.toggle: return try: (error, ownid) = ts3lib.getClientID(schid) if ownid == clientID: (error, ntp) = ts3lib.getChannelVariableAsInt( schid, newChannelID, ts3defines.ChannelPropertiesRare.CHANNEL_NEEDED_TALK_POWER) if self.debug: ts3lib.printMessageToCurrentTab( 'error: {0} | ntp: {1}'.format(error, ntp)) if ntp < 1: return (error, tp) = ts3lib.getClientVariableAsInt( schid, ownid, ts3defines.ClientPropertiesRare.CLIENT_IS_TALKER) if self.debug: ts3lib.printMessageToCurrentTab( 'error: {0} | tp: {1}'.format(error, tp)) if tp: return self.nwmc = QNetworkAccessManager() self.nwmc.connect("finished(QNetworkReply*)", self.jokeReply) self.schid = schid self.nwmc.get( QNetworkRequest( QUrl("http://tambal.azurewebsites.net/joke/random"))) except: from traceback import format_exc ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def jokeReply(self, reply): joke = json.loads(reply.readAll().data().decode('utf-8'))["joke"] ts3lib.logMessage("Requesting talk power with joke\n%s" % joke, ts3defines.LogLevel.LogLevel_INFO, self.name, self.schid) if self.msg == "": msg = joke[:50] else: msg = self.msg if self.debug: ts3lib.printMessageToCurrentTab('[{0}] msg: {1}'.format( self.name, msg)) try: ts3lib.requestIsTalker(self.schid, True, msg) self.schid = 0 except: from traceback import format_exc ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
class BanDialog(QDialog): moveBeforeBan = False clid = 0 def __init__(self, script, schid, clid, uid, name, ip, parent=None): try: super(QDialog, self).__init__(parent) setupUi(self, "%s/ban.ui"%script.path) self.setAttribute(Qt.WA_DeleteOnClose) self.cfg = script.cfg self.ini = script.ini self.schid = schid self.templates = script.templates self.whitelist = script.whitelist self.name = script.name if script.cfg.getboolean("last", "expanded"): self.disableReasons(True) height = script.cfg.get("last", "height") if height: self.resize(self.width, int(height)) else: self.disableReasons() alt = script.cfg.getboolean("last", "alternate") if alt: self.chk_alternate.setChecked(True) dblclick = script.cfg.getboolean("last", "ban on doubleclick") if dblclick: self.chk_doubleclick.setChecked(True) for reason in script.templates: self.lst_reasons.addItem(reason) self.box_reason.addItem(reason) self.box_reason.setEditText(script.cfg.get("last", "reason")) # setItemText(0, ) self.setup(script, schid, clid, uid, name, ip) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def setup(self, script, schid, clid, uid, name, ip): self.setWindowTitle("Ban \"{}\" ({})".format(name, clid)) self.clid = clid url = script.cfg.getboolean("general", "ipapi") if url: self.nwmc_ip = QNetworkAccessManager() self.nwmc_ip.connect("finished(QNetworkReply*)", self.checkIP) self.countries = CountryFlags() self.countries.open() self.disableISP() self.grp_ip.setChecked(script.cfg.getboolean("last", "ip")) if ip: self.txt_ip.setText(ip) self.grp_name.setChecked(script.cfg.getboolean("last", "name")) if name: self.txt_name.setText(name) self.grp_uid.setChecked(script.cfg.getboolean("last", "uid")) if uid: self.txt_uid.setText(uid) self.int_duration.setValue(script.cfg.getint("last", "duration")) def disableReasons(self, enable=False): for item in [self.lst_reasons,self.line,self.chk_alternate,self.chk_doubleclick,self.chk_keep]: item.setVisible(enable) if enable: self.btn_reasons.setText("Reasons <") self.setFixedWidth(675) # self.resize(675, self.height) else: self.btn_reasons.setText("Reasons >") self.setFixedWidth(320) # self.resize(320, self.height) def disableISP(self, enable=False): # if not enable and self.txt_loc.isVisible(): return # elif enable and not self.txt_loc.isVisible(): return for item in [self.lbl_isp,self.txt_isp,self.lbl_flag,self.txt_loc]: item.setVisible(enable) def disableAlt(self, enable=False): self.lst_reasons.setAlternatingRowColors(enable) self.lst_reasons.setStyleSheet(self.cfg.get("general", "stylesheet") if enable else "") def checkIP(self, reply): try: data = reply.readAll().data().decode('utf-8') # if PluginHost.cfg.getboolean("general", "verbose"): print(self.name,"> checkIP() data:",data) data = loads(data) if PluginHost.cfg.getboolean("general", "verbose"): print(self.name, "> Resolved IP ", self.txt_ip.text,":", data) if data["status"] != "success": self.disableISP(); return self.txt_isp.setText(data["isp"]) self.txt_loc.setText("{}, {}, {}".format(data["city"], data["regionName"], data["country"])) code = data["countryCode"] self.lbl_flag.setToolTip(code) self.lbl_flag.setPixmap(self.countries.flag(code)) if not self.txt_isp.isVisible(): self.disableISP(True) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_txt_ip_textChanged(self, text): try: if not hasattr(self, "nwmc_ip"): self.disableISP(); return if not text: self.disableISP(); return if len(text) < 7: self.disableISP(); return ip = QHostAddress(text) if ip.isNull() or ip.isLoopback() or ip.isMulticast(): self.disableISP(); return if text.strip() in ["127.0.0.1", "0.0.0.0", "255.255.255"]: self.disableISP(); return self.nwmc_ip.get(QNetworkRequest(QUrl("http://ip-api.com/json/{ip}".format(ip=text)))) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_box_reason_currentTextChanged(self, text): if not text in self.templates: return self.int_duration.setValue(self.templates[text]) def on_lst_reasons_itemClicked(self, item): try: self.box_reason.setEditText(item.text()) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_lst_reasons_itemDoubleClicked(self, item): if not self.chk_doubleclick.isChecked(): return self.box_reason.setEditText(item.text()) self.on_btn_ban_clicked() def on_chk_alternate_toggled(self, enabled): self.disableAlt(enabled) def on_btn_ban_clicked(self): try: ip = self.txt_ip.text if self.grp_ip.isChecked() else "" name = self.txt_name.text if self.grp_name.isChecked() else "" uid = self.txt_uid.text if self.grp_uid.isChecked() else "" reason = self.box_reason.currentText if reason[0].isdigit(): reason = "§" + reason duration = self.int_duration.value if self.moveBeforeBan: ts3lib.requestClientMove(self.schid, self.clid, 26, "") if ip: check = True if len(self.whitelist) < 1: check = confirm("Empty IP Whitelist!", "The IP whitelist is empty! Are you sure you want to ban \"{}\"?\n\nMake sure your whitelist URL\n{}\nis working!".format(ip, self.cfg.get("general", "whitelist"))) if ip in self.whitelist: ts3lib.printMessageToCurrentTab("{}: [color=red]Not banning whitelisted IP [b]{}".format(self.name, ip)) elif check: ts3lib.banadd(self.schid, ip, "", "", duration, reason) if name: ts3lib.banadd(self.schid, "", name, "", duration, reason) if uid: ts3lib.banadd(self.schid, "", "", uid, duration, reason) # msgBox("schid: %s\nip: %s\nname: %s\nuid: %s\nduration: %s\nreason: %s"%(self.schid, ip, name, uid, duration, reason)) self.cfg["last"] = { "ip": str(self.grp_ip.isChecked()), "name": str(self.grp_name.isChecked()), "uid": str(self.grp_uid.isChecked()), "reason": reason, "duration": str(duration), "expanded": str(self.lst_reasons.isVisible()), "height": str(self.height), "alternate": str(self.chk_alternate.isChecked()), "ban on doubleclick": str(self.chk_doubleclick.isChecked()), } if not self.chk_keep.isChecked(): self.close() except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_btn_cancel_clicked(self): self.cfg.set("last", "expanded", str(self.lst_reasons.isVisible())) self.cfg.set("last", "height", str(self.height)) self.cfg.set("last", "alternate", str(self.chk_alternate.isChecked())) self.cfg.set("last", "ban on doubleclick", str(self.chk_doubleclick.isChecked())) self.close() def on_btn_reasons_clicked(self): if self.lst_reasons.isVisible(): self.disableReasons() else: self.disableReasons(True)
class Linkinfo(ts3plugin): name = "Linkinfo" version = "2.0" try: apiVersion = getCurrentApiVersion() except: apiVersion = 21 author = "Bluscream, Luemmel" description = "Prints a Linkinfolink to the chat." requestAutoload = False offersConfigure = False commandKeyword = "" infoTitle = None hotkeys = [] menuItems = [] wot_api_key = "7132a9b89377c75f81f2ef87aa10896da7c28544" bbcode_url = compile(r'\[url(?:|=[\'"]?([^]"\']+)[\'"]?]([^[]+)|](([^[]+)))\[\/url]', IGNORECASE) messages = [] returnCode = "" 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 stop(self): pass def onTextMessageEvent(self, schid, targetMode, toID, fromID, fromName, fromUniqueIdentifier, message, ffIgnored): if ffIgnored: return (error, myid) = ts3lib.getClientID(schid) _message = message.lower() if myid == fromID and not "~check~" in _message: return if not any(substring in _message for substring in ["[url]", "[url="]): return msg = { "schid": schid, "returnCode": ts3lib.createReturnCode(), "invoker": fromID, "targetMode": targetMode, "urls": parseURLs(message, self.bbcode_url), "response": "[b]Link Checker:[/b]" } hosts = [] for url in msg["urls"]: if url[0] != url[1]: msg["response"] += "\n[color=orange]Suspicous Link [url]{}[/url] points to [url]{}[/url][/color]".format(url[0],url[1]) # answerMessage(schid, targetMode, fromID, "[color=orange]{}: {}".format(url[0], url[1])) host = QUrl(url[1]).host() if host and "." in host and not host in hosts: hosts.append(host) if len(hosts) > 0: self.messages.append(msg) self.getLinkInfo(hosts) def getLinkInfo(self, urls): domains = "/".join(urls) url = "http://api.mywot.com/0.4/public_link_json2?hosts=%s/&key=%s" % (domains,self.wot_api_key) ts3lib.logMessage('Requesting %s'%url, ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Linkinfo Script", 0) self.nwm = QNetworkAccessManager() self.nwm.connect("finished(QNetworkReply*)", self.onWOTReply) self.nwm.get(QNetworkRequest(QUrl(url))) def onWOTReply(self, reply): if reply.error() != QNetworkReply.NoError: print(reply.error()) response = loads(str(reply.readAll().data().decode('utf-8'))) _response = "" for domain in response: parsed = parse_attributes_for_report(response[domain]) _response += "\n{}: {}".format(domain, parsed) # response = "\n" + dumps(response) # , indent=4, sort_keys=True) msg = self.messages[0] msg["response"] += _response answerMessage(msg["schid"], msg["targetMode"], msg["invoker"], msg["response"], msg["returnCode"]) def onServerErrorEvent(self, schid, errorMessage, error, returnCode, extraMessage): return self.onServerPermissionErrorEvent(schid, errorMessage, error, returnCode, 0) def onServerPermissionErrorEvent(self, schid, errorMessage, error, returnCode, failedPermissionID): # (err, permid) = ts3lib.getPermissionIDByName(schid, "") for msg in self.messages: if returnCode == msg["returnCode"]: if error == ts3defines.ERROR_permissions_client_insufficient: if msg["response"]: ts3lib.printMessageToCurrentTab(msg["response"]) del msg return True return False
class autoTPRequest(ts3plugin): name = "Auto Talk Power Request" apiVersion = 22 requestAutoload = False version = "1.0" author = "Bluscream" description = "Automatically request talk power when switching channels.\n\nCheck out https://r4p3.net/forums/plugins.68/ for more plugins." offersConfigure = False commandKeyword = "" infoTitle = None menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Toggle Auto Talk Power", ""), (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 1, "Toggle Talk Power Spam", "")] hotkeys = [] debug = False msg = "Hey du <3" toggle = 0 timer = QTimer() schid = 0 count = 0 interval = 2000 active = False def timestamp(self): return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now()) def __init__(self): try: self.timer.timeout.connect(self.tick) self.schid = ts3lib.getCurrentServerConnectionHandlerID() self.timer.start(self.interval) 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)) except: from traceback import format_exc ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def stop(self): self.timer.stop() ts3lib.printMessageToCurrentTab('Timer restarted!') def tick(self): if self.debug: ts3lib.printMessageToCurrentTab( 'toggle: {0} | schid: {1} | count: {2} | interval: {3} | active: {4}' .format(self.toggle, self.schid, self.count, self.interval, self.active)) if not self.active or self.toggle != 2: return self.count += 1 ts3lib.requestIsTalker(self.schid, False, "") ts3lib.requestIsTalker(self.schid, True, "Request #{}".format(self.count)) def talker(self): (err, id) = ts3lib.getClientID(self.schid) (err, cid) = ts3lib.getChannelOfClient(self.schid, id) (err, ntp) = ts3lib.getChannelVariableAsInt( self.schid, cid, ts3defines.ChannelPropertiesRare.CHANNEL_NEEDED_TALK_POWER) (err, talker) = ts3lib.getClientVariableAsInt( self.schid, id, ts3defines.ClientPropertiesRare.CLIENT_IS_TALKER) ret = True if talker or ntp < 1 else False if self.debug: ts3lib.printMessageToCurrentTab( 'talker() ret: {} | talker: {} | ntp: {} | cid: {} | id: {}'. format(ret, talker, ntp, cid, id)) return ret def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if menuItemID == 0: self.toggle = 1 elif menuItemID == 1: if self.active: self.toggle = 0 self.active = False else: self.schid = schid self.toggle = 2 if self.talker(): self.active = False else: self.active = True ts3lib.printMessageToCurrentTab( "{0}Set {1} to [color=yellow]{2}[/color]".format( self.timestamp(), self.name, self.toggle)) def onClientMoveEvent(self, schid, clientID, oldChannelID, newChannelID, visibility, moveMessage): if not self.toggle or schid != self.schid: return (error, ownid) = ts3lib.getClientID(schid) if ownid != clientID: return if not self.talker(): if self.toggle == 1: if self.msg != "": self.nwmc = QNetworkAccessManager() self.nwmc.connect("finished(QNetworkReply*)", self.jokeReply) self.nwmc.get( QNetworkRequest( QUrl("http://tambal.azurewebsites.net/joke/random") )) else: ts3lib.requestIsTalker(schid, True, self.msg) elif self.toggle == 2: self.active = True else: if self.toggle == 2: self.active = False def onUpdateClientEvent(self, schid, clientID, invokerID, invokerName, invokerUniqueIdentifier): if not self.toggle or schid != self.schid: return (error, cID) = ts3lib.getClientID(self.schid) if not cID == clientID: return (error, ownid) = ts3lib.getClientID(schid) (error, talker) = ts3lib.getClientVariableAsInt( schid, ownid, ts3defines.ClientPropertiesRare.CLIENT_IS_TALKER) if self.debug: ts3lib.printMessageToCurrentTab( 'onUpdateClientEvent talker: {}'.format(talker)) if self.talker(): self.active = False else: self.active = True def jokeReply(self, reply): if not self.toggle == 1: return joke = json.loads(reply.readAll().data().decode('utf-8'))["joke"] ts3lib.logMessage("Requesting talk power with joke\n%s" % joke, ts3defines.LogLevel.LogLevel_INFO, self.name, self.schid) msg = joke[:50] if self.debug: ts3lib.printMessageToCurrentTab('[{0}] msg: {1}'.format( self.name, msg)) ts3lib.requestIsTalker(self.schid, True, msg)
class antiVPN(ts3plugin): path = getScriptPath(__name__) name = "Anti VPN" apiVersion = 22 requestAutoload = False version = "1.0" author = "Bluscream" description = "Kicks users with VPNs" offersConfigure = True commandKeyword = "" infoTitle = None menuItems = [] hotkeys = [] ini = "%s/config.ini" % path cfg = ConfigParser() cfg["general"] = { "cfgversion": "1", "enabled": "True", "api": "http://v2.api.iphub.info/ip/{ip}", "apikey": "Get yours at https://iphub.info/apiKey" } requested = {} def __init__(self): loadCfg(self.ini, self.cfg) 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 onClientMoveEvent(self, schid, clid, oldChannelID, newChannelID, visibility, moveMessage): if not self.cfg.getboolean("general", "enabled"): return if oldChannelID != 0: return (error, _type) = ts3lib.getClientVariable( schid, clid, ts3defines.ClientPropertiesRare.CLIENT_TYPE) if _type == ts3defines.ClientType.ClientType_SERVERQUERY: return self.requested[schid] = [(schid, clid, "")] ts3lib.requestConnectionInfo(schid, clid) def onConnectionInfoEvent(self, schid, clientID): if not self.requested == clientID: return (error, ip) = ts3lib.getConnectionVariableAsString( schid, clientID, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) if error == ts3defines.ERROR_ok: self.ip = ip self.nwm = QNetworkAccessManager() self.nwm.connect("finished(QNetworkReply*)", self.onMainReply) self.nwm.get( QNetworkRequest( QUrl(self.cfg['api']['main'].replace("{ip}", ip)))) if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab( self.cfg['api']['main'].replace("{ip}", ip)) else: (e, msg) = ts3lib.getErrorMessage(error) ts3lib.printMessageToCurrentTab( "[[color=orange]WARNING[/color]] [color=red]ISPValidator could not resolve the IP for '%s' (Reason: %s)" % (clientURL(schid, clientID), msg)) def onMainReply(self, reply): if reply.error() == QNetworkReply.NoError: try: isp = reply.readAll().data().decode('utf-8') if isp.startswith('AS'): isp = isp.split(" ", 1)[1] if not isp or isp == "" or isp == "undefined": ts3lib.printMessageToCurrentTab( "[[color=orange]WARNING[/color]] [color=red]ISPValidator could not resolve the ISP for '%s' (Reason: %s) Falling back to %s" % (clientURL(self.schid, self.requested), format_exc(), self.cfg['api']['fallback'].replace("{ip}", self.ip))) if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab( self.cfg['api']['fallback'].replace( "{ip}", self.ip)) self.nwb = QNetworkAccessManager() self.nwb.connect("finished(QNetworkReply*)", self.onFallbackReply) self.nwb.get( QNetworkRequest( QUrl(self.cfg['api']['fallback'].replace( "{ip}", self.ip)))) return if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab( "%s's ISP: %s" % (clientURL(self.schid, self.requested), isp)) _match = False for _isp in self.isps: if isp == _isp: _match = True if self.cfg.getboolean('general', 'whitelist') and not _match: if self.cfg.getboolean('main', 'kickonly'): ts3lib.requestClientKickFromServer( self.schid, self.requested, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 else: ts3lib.banclient( self.schid, self.requested, 60, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 elif not self.cfg.getboolean('general', 'whitelist') and _match: if self.cfg.getboolean('main', 'kickonly'): ts3lib.requestClientKickFromServer( self.schid, self.requested, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 else: ts3lib.banclient( self.schid, self.requested, 60, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 except: try: ts3lib.printMessageToCurrentTab( "[[color=orange]WARNING[/color]] [color=red]ISPValidator could not resolve the ISP for '%s' (Reason: %s) Falling back to %s" % (clientURL(self.schid, self.requested), format_exc(), self.cfg['api']['fallback'].replace("{ip}", self.ip))) if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab( self.cfg['api']['fallback'].replace( "{ip}", self.ip)) self.nwb = QNetworkAccessManager() self.nwb.connect("finished(QNetworkReply*)", self.onFallbackReply) self.nwb.get( QNetworkRequest( QUrl(self.cfg['api']['fallback'].replace( "{ip}", self.ip)))) except: pass else: ts3lib.printMessageToCurrentTab( "[[color=orange]WARNING[/color]] [color=red]ISPValidator could not resolve the ISP for '%s' (Reason: %s) Falling back to %s" % (clientURL(self.schid, self.requested), reply.errorString(), self.cfg['api']['fallback'].replace("{ip}", self.ip))) if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab( self.cfg['api']['fallback'].replace("{ip}", self.ip)) self.nwb = QNetworkAccessManager() self.nwb.connect("finished(QNetworkReply*)", self.onFallbackReply) self.nwb.get( QNetworkRequest( QUrl(self.cfg['api']['fallback'].replace("{ip}", self.ip)))) reply.deleteLater() def onFallbackReply(self, reply): if reply.error() == QNetworkReply.NoError: try: isp = reply.readAll().data().decode('utf-8') if isp.startswith('AS'): isp = isp.split(" ", 1)[1] if not isp or isp == "" or isp == "undefined": ts3lib.printMessageToCurrentTab( "[[color=orange]WARNING[/color]] [color=red]ISPValidator could not resolve the ISP for '%s' (Reason: %s)" % (clientURL(self.schid, self.requested), format_exc())) if self.cfg.getboolean("failover", "enabled"): if self.cfg.getboolean('failover', 'kickonly'): ts3lib.requestClientKickFromServer( self.schid, self.requested, self.cfg['failover']['reason'].replace( '{isp}', isp)) else: ts3lib.banclient( self.schid, self.requested, int(self.cfg['failover']['bantime']), self.cfg['failover']['reason'].replace( '{isp}', isp)) self.requested = 0 reply.deleteLater() return if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab( "%s's ISP: %s" % (clientURL(self.schid, self.requested), isp)) _match = False for _isp in self.isps: if isp == _isp: _match = True if self.cfg.getboolean('general', 'whitelist') and not _match: if self.cfg.getboolean('main', 'kickonly'): ts3lib.requestClientKickFromServer( self.schid, self.requested, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 else: ts3lib.banclient( self.schid, self.requested, 60, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 elif not self.cfg.getboolean('general', 'whitelist') and _match: if self.cfg.getboolean('main', 'kickonly'): ts3lib.requestClientKickFromServer( self.schid, self.requested, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 else: ts3lib.banclient( self.schid, self.requested, 60, "%s is not a valid Internet Service Provider!" % isp) self.requested = 0 except: ts3lib.printMessageToCurrentTab( "[[color=orange]WARNING[/color]] [color=red]ISPValidator could not resolve the ISP for '%s' (Reason: %s)" % (clientURL(self.schid, self.requested), "")) if self.cfg.getboolean("failover", "enabled"): if self.cfg.getboolean('failover', 'kickonly'): ts3lib.requestClientKickFromServer( self.schid, self.requested, self.cfg['failover']['reason'].replace( '{isp}', isp)) else: ts3lib.banclient( self.schid, self.requested, int(self.cfg['failover']['bantime']), self.cfg['failover']['reason'].replace( '{isp}', isp)) else: ts3lib.printMessageToCurrentTab( "[[color=orange]WARNING[/color]] [color=red]ISPValidator could not resolve the ISP for '%s' (Reason: %s)" % (clientURL(self.schid, self.requested), reply.errorString())) if self.cfg.getboolean("failover", "enabled"): if self.cfg.getboolean('failover', 'kickonly'): ts3lib.requestClientKickFromServer( self.schid, self.requested, self.cfg['failover']['reason'].replace('{isp}', isp)) else: ts3lib.banclient( self.schid, self.requested, int(self.cfg['failover']['bantime']), self.cfg['failover']['reason'].replace('{isp}', isp)) self.requested = 0 reply.deleteLater()
class customBadges(ts3plugin): name = "Custom Badges" apiVersion = 21 requestAutoload = True version = "0.9" author = "Bluscream" description = "Automatically sets some badges for you :)" offersConfigure = True commandKeyword = "" infoTitle = None menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Change " + name, "")] hotkeys = [] ini = path.join(getPluginPath(), "scripts", "customBadges", "settings.ini") ui = path.join(getPluginPath(), "scripts", "customBadges", "badges.ui") badgesinfo = path.join(getPluginPath(), "include", "badges.json") cfg = ConfigParser() dlg = None cfg["general"] = { "cfgversion": "1", "debug": "False", "enabled": "True", "badges": "", "overwolf": "False", } badges = {} def __init__(self): loadCfg(self.ini, self.cfg) try: with open(self.badgesinfo, encoding='utf-8-sig') as json_file: self.badges = load(json_file) except: self.nwmc = QNetworkAccessManager() self.nwmc.connect("finished(QNetworkReply*)", self.loadBadges) self.nwmc.get( QNetworkRequest( QUrl( "https://gist.githubusercontent.com/Bluscream/29b838f11adc409feac9874267b43b1e/raw" ))) 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(timestamp(), self.name, self.author)) def loadBadges(self, reply): data = reply.readAll().data().decode('utf-8') self.badges = loads(data) def stop(self): saveCfg(self.ini, self.cfg) def configure(self, qParentWidget): self.openDialog() def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL or menuItemID != 0: return self.openDialog() def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber): if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED: self.setCustomBadges() def setCustomBadges(self): overwolf = self.cfg.getboolean('general', 'overwolf') badges = self.cfg.get('general', 'badges').split(",") sendCommand(self.name, buildBadges(badges, overwolf)) def openDialog(self): if not self.dlg: self.dlg = BadgesDialog(self) self.dlg.show() self.dlg.raise_() self.dlg.activateWindow()
class ServersDialog(QDialog): requests = 0 page = 1 pages = 1 cooldown = False cooldown_page = False cooldown_time = 5000 cooldown_time_page = 1000 countries = [] NAME_MODIFIERS = ["Contains", "Starts with", "Ends with"] def buhl(self, s): if s.lower() == 'true' or s == 1: return True elif s.lower() == 'false' or s == 0: return False else: raise ValueError("Cannot convert {} to a bool".format(s)) def __init__(self,serverBrowser, parent=None): self.serverBrowser=serverBrowser super(QDialog, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) setupUi(self, os.path.join(ts3.getPluginPath(), "pyTSon", "scripts", "serverBrowser", "ui", "servers.ui")) self.setWindowTitle("PlanetTeamspeak Server Browser") #ts3.printMessageToCurrentTab("Countries: "+str(self.countries)) #try: #self.serverList.doubleClicked.connect(self.table_doubleclicked) #self.serverList.connect("doubleClicked()", self.table_doubleclicked) #self.apply.connect("clicked()", self.on_apply_clicked) #self.reload.connect("clicked()", self.on_reload_clicked) #except: #ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0) #self.ReasonList.connect("currentItemChanged(QListWidgetItem*, QListWidgetItem*)", self.onReasonListCurrentItemChanged) #self.ReasonList.connect("itemChanged(QListWidgetItem*)", self.onReasonListItemChanged) self.serverList.horizontalHeader().setStretchLastSection(True) self.serverList.setColumnWidth(0, 350) self.serverNameModifier.addItems(self.NAME_MODIFIERS) self.serverNameModifier.setEnabled(False) #self.pageLabel.mousePressEvent = self.on_pageLabel_clicked #self.cfg.set("general", "differentApi", "True" if state == Qt.Checked else "False") self.listCountries(True) #ReportDialog.ReasonList.clear() self.setupFilters() # self.serverList.doubleClicked.connect(self.doubleClicked_table) #ts3.printMessageToCurrentTab(str(serverBrowser.filters)) #if serverBrowser.filters.filterServerName != "": #self.filterServerName.setText(serverBrowser.filters.filterServerName) #item.setFlags(item.flags() &~ Qt.ItemIsEditable) # self.countryBox.clear() #for item in countries: #self.countryBox.addItem(str(item[1])) #self.serverList.setStretchLastSection(true) self.listServers() def setupFilters(self): try: _filters = self.serverBrowser.config["FILTERS"] buhl = self.buhl self.hideEmpty.setChecked(buhl(_filters["hideEmpty"])) self.hideFull.setChecked(buhl(_filters["hideFull"])) self.maxUsers.setChecked(buhl(_filters["maxUsers"])) self.maxUsersMin.setValue(int(_filters["maxUsersMin"])) self.maxUsersMax.setValue(int(_filters["maxUsersMax"])) self.maxSlots.setChecked(buhl(_filters["maxSlots"])) self.maxSlotsMin.setValue(int(_filters["maxSlotsMin"])) self.maxSlotsMax.setValue(int(_filters["maxSlotsMax"])) if _filters["filterPassword"] == "none": self.filterPasswordShowWithout.setChecked(True) #self.filterPasswordShowWith.setChecked(False) #self.filterPasswordShowAll.setChecked(False) elif _filters["filterPassword"] == "only": #self.filterPasswordShowWithout.setChecked(False) self.filterPasswordShowWith.setChecked(True) #self.filterPasswordShowAll.setChecked(False) else: #self.filterPasswordShowWithout.setChecked(False) #self.filterPasswordShowWith.setChecked(False) self.filterPasswordShowAll.setChecked(True) if _filters["filterChannels"] == "none": self.filterChannelsCantCreate.setChecked(True) #self.filterChannelsCanCreate.setChecked(False) #self.filterChannelsShowAll.setChecked(False) elif _filters["filterChannels"] == "only": #self.filterChannelsCantCreate.setChecked(False) self.filterChannelsCanCreate.setChecked(True) #self.filterChannelsShowAll.setChecked(False) else: #self.filterChannelsCantCreate.setChecked(False) #self.filterChannelsCanCreate.setChecked(False) self.filterChannelsShowAll.setChecked(True) self.serverNameModifier.setCurrentText(_filters["serverNameModifier"]) self.filterServerName.setText(_filters["filterServerName"]) if self.countryBox.findText(_filters["countryBox"]) < 0: self.countryBox.addItem(_filters["countryBox"]) self.countryBox.setCurrentIndex(self.countryBox.findText(_filters["countryBox"])) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) # def contextMenuEvent(self, event): # try: # self.menu = QMenu(self.serverList) # connectAction = QAction('Connect', self) # #connectAction.triggered.connect(self.connect) # self.menu.addAction(connectAction) # self.menu.popup(QCursor.pos()) # except: # ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def connect(self): index = self.serverList.selectedIndexes()[0] id_us = int(self.serverList.model().data(index).toString()) ts3.printMessageToCurrentTab("index : " + str(id_us)) def setupURL(self): # import urllib # f = { 'eventName' : 'myEvent', 'eventDescription' : "cool event"} # urllib.urlencode(f) _filters = self.serverBrowser.config["FILTERS"] url = self.serverBrowser.config['GENERAL']['api']+"serverlist/?page="+str(self.page)+"&limit="+str(self.serverBrowser.config['GENERAL']['serversperpage']) if _filters["filterPassword"] == "none": url += "&password=false" elif _filters["filterPassword"] == "only": url += "&password=true" if _filters["filterChannels"] == "none": url += "&createchannels=false" elif _filters["filterChannels"] == "only": url += "&createchannels=true" if self.buhl(_filters["maxUsers"]): url += "&minusers="+str(_filters["maxUsersMin"])+"&maxusers="+str(_filters["maxUsersMax"]) if self.buhl(_filters["maxSlots"]): url += "&minslots="+str(_filters["maxSlotsMin"])+"&maxslots="+str(_filters["maxSlotsMax"]) if _filters["filterServerName"] and _filters["filterServerName"] != "": url += "&search="+urllib.parse.quote_plus(_filters["filterServerName"]) cid = self.getCountryIDbyName(_filters["countryBox"]) if _filters["countryBox"] != "All" and cid != '--': url+= "&country="+cid if self.serverBrowser.config["GENERAL"]["debug"] == "True": ts3.printMessageToCurrentTab("Requesting: "+url) return url def getCountryIDbyName(self, name): try: if name.__contains__(" ("): name = name.split(" (")[0] return [c for c in self.countries if c[1]==name][0][0] except: return '-' def getCountryNamebyID(self, cid): try: return [c for c in self.countries if c[0]==cid][0][1] except: return 'Unknown ('+cid+')' def onCountryListReply(self, reply): try: _api = self.serverBrowser.config['GENERAL']['api'] _reply = reply.readAll() countries = json.loads(_reply.data().decode('utf-8'))["result"]["data"] ts3.printMessageToCurrentTab("%s"%countries) _reason = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) self.status.setText("Response from \"{0}\": {1}: {2}".format(_api, _reason, reply.attribute(QNetworkRequest.HttpReasonPhraseAttribute))) palette = QPalette() if _reason == 200: palette.setColor(QPalette.Foreground,Qt.darkGreen) self.countryBox.clear() else: palette.setColor(QPalette.Foreground,Qt.red) self.status.setPalette(palette) y= sum(x[2] for x in countries) #y = 0 #for x in countries: # y = y + x[2] #ts3.printMessageToCurrentTab(str(countries)) if "-" in [h[0] for h in countries]: countries = countries[0:1]+sorted(countries[1:],key=lambda x: x[1]) else: countries = sorted(countries,key=lambda x: x[1]) self.countries = [['ALL', 'All', y]]+countries #if self.serverBrowser.config['GENERAL']['morerequests'] == "True": #self.countryBox.addItems([x[1]+" ("+str(x[2])+")" for x in self.countries]) #else: self.countryBox.addItems([x[1] for x in self.countries]) #__countries = __countries.__add__([['ALL', 'All', 0]]) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def requestCountries(self): self.nwmc = QNetworkAccessManager() self.nwmc.connect("finished(QNetworkReply*)", self.onCountryListReply) self.nwmc.get(QNetworkRequest(QUrl(self.serverBrowser.config['GENERAL']['api']+"servercountries"))) ts3.printMessageToCurrentTab("requestCountries: "+self.serverBrowser.config['GENERAL']['api']+"servercountries") def listCountries(self, force=False): if force or self.serverBrowser.config['GENERAL']['morerequests'] == "True": self.requestCountries() def serversReply(self, reply): try: _api = self.serverBrowser.config['GENERAL']['api'] _reason = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) _reply = reply.readAll() servers = json.loads(_reply.data().decode('utf-8')) ts3.printMessageToCurrentTab("servers: %s"%servers) self.status.setText("Response from \"{0}\": {1}: {2}".format(_api, _reason, reply.attribute(QNetworkRequest.HttpReasonPhraseAttribute))) palette = QPalette() if not _reason == 200: palette.setColor(QPalette.Foreground,Qt.red) self.status.setPalette(palette) self.status.setText("Status: %s"%reply.attribute(QNetworkRequest.HttpReasonPhraseAttribute)) if servers["status"] == "success": self.pages = servers["result"]["pagestotal"] self.pageLabel.setText(str(servers["result"]["pageactive"])+" / "+str(servers["result"]["pagestotal"])) self.pageLabel.updateGeometry() self.info.setText(str(servers["result"]["itemsshown"])+" / "+str(servers["result"]["itemstotal"])+" Servers shown.") self.serverList.setRowCount(0) elif servers["status"] == "error": self.info.setText("Requested Page: "+str(self.page)) self.status.setText(servers["status"].title()+": "+servers["result"]["message"]+" ("+str(servers["result"]["code"])+")") palette = QPalette() palette.setColor(QPalette.Foreground,Qt.red) self.status.setPalette(palette) return else: self.info.setText("Requested Page: "+str(self.page)) palette = QPalette() palette.setColor(QPalette.Foreground,Qt.red) self.status.setPalette(palette) return _list = self.serverList _filters = self.serverBrowser.config["FILTERS"] if servers["result"]["pageactive"] == 1: self.previous.setEnabled(False) else: self.previous.setEnabled(True) if servers["result"]["pageactive"] == servers["result"]["pagestotal"]: self.next.setEnabled(False) else: self.next.setEnabled(True) for key in servers["result"]["data"]: if self.buhl(_filters["hideFull"]) and key["users"] >= key["slots"]: continue elif self.buhl(_filters["hideEmpty"]) and key["users"] <= 0: continue else: rowPosition = _list.rowCount _list.insertRow(rowPosition) # if key['premium']: # _list.setItem(rowPosition, 0, QTableWidgetItem("Yes")) # else: # _list.setItem(rowPosition, 0, QTableWidgetItem("No")) _list.setItem(rowPosition, 0, QTableWidgetItem(key['name'])) _list.setItem(rowPosition, 1, QTableWidgetItem(str(key['users'])+' / '+str(key['slots']))) if key['users'] >= key['slots']: palette = QPalette() palette.setColor(QPalette.Foreground,Qt.red) _list.setPalette(palette) _list.setItem(rowPosition, 2, QTableWidgetItem(self.getCountryNamebyID(key['country']))) if key['createchannels']: _list.setItem(rowPosition, 3, QTableWidgetItem("Yes")) else: _list.setItem(rowPosition, 3, QTableWidgetItem("No")) if key['password']: _list.setItem(rowPosition, 4, QTableWidgetItem("Yes")) else: _list.setItem(rowPosition, 4, QTableWidgetItem("No")) #item.setData(Qt.UserRole, key['ip']); _list.setAlternatingRowColors(True) _list.styleSheet = "alternate-background-color: grey;" _list.setStyleSheet("alternate-background-color: grey;") except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def requestServers(self, url): if self.serverBrowser.config["GENERAL"]["debug"] == "True": self.requests += 1 ts3.printMessageToCurrentTab("Request: "+str(self.requests)) self.nwm = QNetworkAccessManager() self.nwm.connect("finished(QNetworkReply*)", self.serversReply) self.nwm.get(QNetworkRequest(QUrl(url))) def listServers(self): if self.cooldown: self.status.setText("You have to wait "+str(self.cooldown_time/1000)+" second(s) before retrying!") palette = QPalette() palette.setColor(QPalette.Foreground,Qt.red) self.status.setPalette(palette) return url = self.setupURL() self.requestServers(url) #def onReasonListItemChanged(self, item): #checked = item.checkState() == Qt.Checked #name = item.data(Qt.UserRole) #if checked and name not in self.host.active: #self.host.activate(name) #elif not checked and name in self.host.active: #self.host.deactivate(name) #if self.pluginsList.currentItem() == item: #self.settingsButton.setEnabled(checked and name in self.host.active and self.host.active[name].offersConfigure) def disable_cooldown(self): self.cooldown = False self.reload.setEnabled(True) def disable_cooldown_page(self): self.cooldown_page = False if self.page > 1: self.previous.setEnabled(True) self.first.setEnabled(True) if self.page < self.pages: self.next.setEnabled(True) self.last.setEnabled(True) def on_apply_clicked(self): try: self.serverBrowser.config.set("FILTERS", "hideEmpty", str(self.hideEmpty.isChecked())) self.serverBrowser.config.set("FILTERS", "hideFull", str(self.hideFull.isChecked())) self.serverBrowser.config.set("FILTERS", "maxUsers", str(self.maxUsers.isChecked())) self.serverBrowser.config.set("FILTERS", "maxUsersMin", str(self.maxUsersMin.value)) self.serverBrowser.config.set("FILTERS", "maxUsersMax", str(self.maxUsersMax.value)) self.serverBrowser.config.set("FILTERS", "maxSlots", str(self.maxSlots.isChecked())) self.serverBrowser.config.set("FILTERS", "maxSlotsMin", str(self.maxSlotsMin.value)) self.serverBrowser.config.set("FILTERS", "maxSlotsMax", str(self.maxSlotsMax.value)) if self.filterPasswordShowWithout.isChecked(): self.serverBrowser.config.set("FILTERS", "filterPassword", "none") elif self.filterPasswordShowWith.isChecked(): self.serverBrowser.config.set("FILTERS", "filterPassword", "only") elif self.filterPasswordShowAll.isChecked(): self.serverBrowser.config.set("FILTERS", "filterPassword", "all") if self.filterChannelsCantCreate.isChecked(): self.serverBrowser.config.set("FILTERS", "filterChannels", "none") elif self.filterChannelsCanCreate.isChecked(): self.serverBrowser.config.set("FILTERS", "filterChannels", "only") elif self.filterChannelsShowAll.isChecked(): self.serverBrowser.config.set("FILTERS", "filterChannels", "all") self.serverBrowser.config.set("FILTERS", "serverNameModifier", self.serverNameModifier.currentText) self.serverBrowser.config.set("FILTERS", "filterServerName", self.filterServerName.text) self.serverBrowser.config.set("FILTERS", "countryBox", self.countryBox.currentText.split(" (")[0]) with open(self.serverBrowser.ini, 'w') as configfile: self.serverBrowser.config.write(configfile) if self.buhl(self.serverBrowser.config['GENERAL']['morerequests']): self.listCountries() self.page = 1 self.listServers() if not self.cooldown: self.cooldown = True QTimer.singleShot(self.cooldown_time, self.disable_cooldown) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_navigate(self, page=1, direction=0): try: if self.cooldown_page: self.status.setText("You have to wait "+str(self.cooldown_time_page/1000)+" second(s) before switching pages!") palette = QPalette() palette.setColor(QPalette.Foreground,Qt.red) self.status.setPalette(palette) return if direction == 2: self.page += page elif direction == 1: self.page -= page else: self.page = page self.listServers() if not self.cooldown: self.cooldown_page = True self.previous.setEnabled(False) self.next.setEnabled(False) self.first.setEnabled(False) self.last.setEnabled(False) QTimer.singleShot(self.cooldown_time_page, self.disable_cooldown_page) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0) def on_reload_clicked(self): try: self.listServers() if not self.cooldown: self.cooldown = True self.reload.setEnabled(False) QTimer.singleShot(self.cooldown_time, self.disable_cooldown) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0) def on_previous_clicked(self): try: self.on_navigate(1,1) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0) def on_next_clicked(self): try: self.on_navigate(1,2) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0) def on_first_clicked(self): try: self.on_navigate() except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0) def on_last_clicked(self): try: self.on_navigate(self.pages) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon", 0) def on_pageLabel_clicked(self, event): try: page = QInputDialog.getInt(self, "Goto Page", "Page:") if page > 0: if self.cooldown_page: self.status.setText("You have to wait "+str(self.cooldown_time_page/1000)+" second(s) before switching pages!") palette = QPalette() palette.setColor(QPalette.Foreground,Qt.red) self.status.setPalette(palette) return self.page = page self.listServers() if not self.cooldown: self.cooldown_page = True self.previous.setEnabled(False) self.next.setEnabled(False) QTimer.singleShot(self.cooldown_time_page, self.disable_cooldown_page) except: ts3.logMessage(traceback.format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_serverList_doubleClicked(self): try: ts3.logMessage("test", ts3defines.LogLevel.LogLevel_INFO, "pyTSon", 0) item = self.serverList.selectedItems()[0] item.setData(Qt.UserRole, 22); except: print(traceback.format_exc()) # setContextMenuPolicy(Qt::ActionsContextMenu); # QAction* fooAction = new new QAction("foo"); # QAction* barAction = new new QAction("bar"); # connect(fooAction, SIGNAL(triggered()), this, SLOT(doSomethingFoo())); # connect(barAction, SIGNAL(triggered()), this, SLOT(doSomethingBar())); # addAction(fooAction); # addAction(barAction); # Planetteamspeak: https://api.planetteamspeak.com/servernodes/84.200.62.248:9987/ # TSViewer: https://www.tsviewer.com/ts3viewer.php?ID=904314 # TS3Index: https://ts3index.com/viewer/?id=138009
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
class customBadges(ts3plugin): name = "Custom Badges" apiVersion = 21 requestAutoload = True version = "0.9" author = "Bluscream" description = "Automatically sets some badges for you :)" offersConfigure = True commandKeyword = "" infoTitle = "[b]Badges[/b]" menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Change " + name, ""), (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 1, "Generate Badge UIDs", "")] hotkeys = [] icons = path.join(ts3lib.getConfigPath(), "cache", "badges") ini = path.join(getPluginPath(), "scripts", "customBadges", "settings.ini") ui = path.join(getPluginPath(), "scripts", "customBadges", "badges.ui") badges_local = path.join(getPluginPath(), "include", "badges.json") badges_ext = path.join(getPluginPath(), "include", "badges_ext.json") badges_remote = "https://gist.githubusercontent.com/Bluscream/29b838f11adc409feac9874267b43b1e/raw" badges_ext_remote = "https://raw.githubusercontent.com/R4P3-NET/CustomBadges/master/badges.json" cfg = ConfigParser() dlg = None cfg["general"] = { "cfgversion": "1", "debug": "False", "enabled": "True", "badges": "", "overwolf": "False", } badges = {} extbadges = {} def __init__(self): try: loadCfg(self.ini, self.cfg) self.requestBadges() self.requestBadgesExt() 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)) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def infoData(self, schid, id, atype): if atype != ts3defines.PluginItemType.PLUGIN_CLIENT: return None (err, ownID) = ts3lib.getClientID(schid) if ownID != id: return None # overwolf = self.cfg.getboolean('general', 'overwolf') # badges = self.cfg.get('general', 'badges').split(',') (err, badges) = ts3lib.getClientVariable( schid, id, ts3defines.ClientPropertiesRare.CLIENT_BADGES) (overwolf, badges) = parseBadges(badges) _return = [ "Overwolf: {0}".format("[color=green]Yes[/color]" if overwolf else "[color=red]No[/color]") ] # i = [] # for badge in badges: # if badge for badge in badges: lst = self.badges if badge in self.extbadges: lst = self.extbadges _return.append("{} {}".format( "[img]https://badges-content.teamspeak.com/{}/{}.svg[/img]". format(badge, lst[badge]["filename"] if badge in lst else "unknown"), self.badgeNameByUID(badge, lst) if badge in lst else badge)) return _return def badgeNameByUID(self, uid, lst=badges): for badge in lst: if badge == uid: return lst[badge]["name"] def requestBadges(self): try: with open(self.badges_local, encoding='utf-8-sig') as json_file: self.badges = load(json_file) except: self.nwmc = QNetworkAccessManager() self.nwmc.connect("finished(QNetworkReply*)", self.loadBadges) self.nwmc.get(QNetworkRequest(QUrl(self.badges_remote))) def requestBadgesExt(self): try: with open(self.badges_ext, encoding='utf-8-sig') as json_file: self.extbadges = load(json_file) except: self.nwmc_ext = QNetworkAccessManager() self.nwmc_ext.connect("finished(QNetworkReply*)", self.loadBadgesExt) self.nwmc_ext.get(QNetworkRequest(QUrl(self.badges_ext_remote))) def loadBadgesExt(self, reply): try: data = reply.readAll().data().decode('utf-8') self.extbadges = loads(data) print("extbadges: {}".format(self.extbadges)) if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab("{}".format(self.badges)) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def loadBadges(self, reply): try: # print(reply) _reason = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) _reasonmsg = reply.attribute( QNetworkRequest.HttpReasonPhraseAttribute) print('reason={}|reasonmsg={}'.format(_reason, _reasonmsg)) data = reply.readAll().data().decode('utf-8') self.badges = loads(data) print("badges: {}".format(self.badges)) if PluginHost.cfg.getboolean("general", "verbose"): ts3lib.printMessageToCurrentTab("{}".format(self.badges)) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def stop(self): saveCfg(self.ini, self.cfg) def configure(self, qParentWidget): self.openDialog() def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL: return if menuItemID == 0: self.openDialog() elif menuItemID == 1: for i in range(0, 3): # 0c4u2snt-ao1m-7b5a-d0gq-e3s3shceript uid = [ random_string(size=8, chars=string.ascii_lowercase + string.digits) ] for _i in range(0, 3): uid.append( random_string(size=4, chars=string.ascii_lowercase + string.digits)) uid.append( random_string(size=12, chars=string.ascii_lowercase + string.digits)) ts3lib.printMessageToCurrentTab( "[color=red]Random UID #{}: [b]{}".format( i, '-'.join(uid))) def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber): if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED: self.setCustomBadges() def setCustomBadges(self): try: overwolf = self.cfg.getboolean('general', 'overwolf') badges = self.cfg.get('general', 'badges').split(",") # if len(badges) > 0: badges += ['0c4u2snt-ao1m-7b5a-d0gq-e3s3shceript'] (err, schids) = ts3lib.getServerConnectionHandlerList() for schid in schids: sendCommand(self.name, buildBadges(badges, overwolf), schid) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def openDialog(self): if not self.dlg: self.dlg = BadgesDialog(self) self.dlg.show() self.dlg.raise_() self.dlg.activateWindow()
class customBan(ts3plugin): path = getScriptPath(__name__) name = "Custom Ban" try: apiVersion = pytson.getCurrentApiVersion() except: apiVersion = 22 requestAutoload = True version = "1.0" author = "Bluscream" description = "Requested by @mrcraigtunstall (217.61.6.128)\nExtended for @SossenSystems (ts3public.de)" offersConfigure = False commandKeyword = "" infoTitle = None menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT, 0, "Ban Client", "scripts/%s/ban_client.svg"%__name__)] hotkeys = [] ini = "%s/config.ini"%path dlg = None cfg = ConfigParser() cfg["general"] = { "template": "", "whitelist": "", "ipapi": "True" , "stylesheet": "alternate-background-color: white;background-color: black;"} cfg["last"] = { "ip": "False", "name": "False", "uid": "True", "reason": "", "duration": "0", "expanded": "False", "height": "", "alternate": "False", "ban on doubleclick": "False" } templates = {} whitelist = ["127.0.0.1"] def __init__(self): loadCfg(self.ini, self.cfg) url = self.cfg.get("general", "template") if url: self.nwmc_template = QNetworkAccessManager() self.nwmc_template.connect("finished(QNetworkReply*)", self.loadTemplates) self.nwmc_template.get(QNetworkRequest(QUrl(url))) url = self.cfg.get("general", "whitelist") if url: self.nwmc_whitelist = QNetworkAccessManager() self.nwmc_whitelist.connect("finished(QNetworkReply*)", self.loadWhitelist) self.nwmc_whitelist.get(QNetworkRequest(QUrl(url))) 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): saveCfg(self.ini, self.cfg) def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT or menuItemID != 0: return (err, uid) = ts3lib.getClientVariable(schid, selectedItemID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER) if err != ts3defines.ERROR_ok: uid = "" (err, name) = ts3lib.getClientVariable(schid, selectedItemID, ts3defines.ClientProperties.CLIENT_NICKNAME) if err != ts3defines.ERROR_ok: name = "" (err, ip) = ts3lib.getConnectionVariable(schid, selectedItemID, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) self.clid = selectedItemID if err or not ip: ip = "";ts3lib.requestConnectionInfo(schid, selectedItemID); print("requested for", selectedItemID, "on", schid) #TODO: Check if not self.dlg: self.dlg = BanDialog(self, schid, selectedItemID, uid, name, ip) else: self.dlg.setup(self, schid, selectedItemID, uid, name, ip) self.dlg.show() self.dlg.raise_() self.dlg.activateWindow() def onConnectionInfoEvent(self, schid, clid): print(self.name,"> onConnectionInfoEvent", schid, clid) if not hasattr(self, "clid") or clid != self.clid: return (err, ip) = ts3lib.getConnectionVariable(schid, clid, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) if ip and self.dlg: self.dlg.txt_ip.setText(ip) del self.clid def loadTemplates(self, reply): try: data = reply.readAll().data().decode('utf-8') self.templates = loads(data, object_pairs_hook=OrderedDict) if PluginHost.cfg.getboolean("general", "verbose"): print(self.name, "> Downloaded ban templates:", self.templates) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def loadWhitelist(self, reply): try: data = reply.readAll().data().decode('utf-8') self.whitelist = [] for line in data.splitlines(): ip = QHostAddress(line.strip()) if ip.isNull(): print(self.name,">",line,"is not a valid IP! Not adding to whitelist.") else: self.whitelist.append(line.strip()) if PluginHost.cfg.getboolean("general", "verbose"): print(self.name, "> Downloaded ip whitelist:", self.whitelist) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
class customBadges(ts3plugin): __path__ = getScriptPath(__name__) name = "Custom Badges" try: apiVersion = getCurrentApiVersion() except: apiVersion = 21 requestAutoload = True version = "0.9.5.1" author = "Bluscream" description = "Automatically sets some badges for you :)" offersConfigure = True commandKeyword = "" infoTitle = "[b]Badges[/b]" menuItems = [ (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Change " + name, "") # , # (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 1, "Generate Badge UIDs", "") ] hotkeys = [] ini = path.join(__path__, "settings.ini") txt = path.join(__path__, "notice") ui = path.join(__path__, "badges.ui") icons = path.join(ts3lib.getConfigPath(), "cache", "badges") # icons_ext = path.join(icons, "external") badges_ext_remote = "https://raw.githubusercontent.com/R4P3-NET/CustomBadges/master/badges.json" badges_remote = "https://badges-content.teamspeak.com/list" cfg = ConfigParser() dlg = None cfg["general"] = { "cfgversion": "1", "debug": "False", "enabled": "True", "badges": "", "overwolf": "False" } badges = {} extbadges = {} notice = QTimer() notice_nwmc = QNetworkAccessManager() mode = HookMode.NONE def __init__(self): if getAddonStatus("tspatch", "TS Patch").value > AddonStatus.INSTALLED.value: self.mode = HookMode.TSPATCH elif getAddonStatus("TS3Hook", "TS3Hook").value > AddonStatus.INSTALLED.value: self.mode = HookMode.TS3HOOK loadCfg(self.ini, self.cfg) self.requestBadges() self.requestBadgesExt() self.notice.timeout.connect(self.checkNotice) self.notice.start(30 * 1000) 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 infoData(self, schid, id, atype): if atype != ts3defines.PluginItemType.PLUGIN_CLIENT: return None (err, ownID) = ts3lib.getClientID(schid) if ownID != id: return None # overwolf = self.cfg.getboolean('general', 'overwolf') # badges = self.cfg.get('general', 'badges').split(',') (err, badges) = ts3lib.getClientVariable( schid, id, ts3defines.ClientPropertiesRare.CLIENT_BADGES) (overwolf, badges) = parseBadges(badges) _return = [ "Overwolf: {0}".format("[color=green]Yes[/color]" if overwolf else "[color=red]No[/color]") ] # i = [] # for badge in badges: # if badge for badge in badges: lst = self.badges if badge in self.extbadges: lst = self.extbadges _return.append("{} {}".format( # "[img]data://image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACp0lEQVR42qXSW0jTURwH8O/5/93mLm460alFXrKLqQ8aNUzRB6NWhOYG9ZDYlYiSHgoCs4d6qIwIiuipIOmtqClYUZEIhlDgbTIvealR7T6bm3Nz2///P/2bEURlRQd+L79zzuf8+HII/nOR5TYnduw+zjGMuuSJue2fgcltdRfT9BvO0kgY9pEPl8pedLb+NTCztb5cWZo3oM0GGI8PDi+B2xXauOl55+AfAZuhQQZ58pCudl0RlSiBJCmY0QFYJ4LjvEDK9M86ossDVQZjanXxI0VBOiSHWxI97vp5eF9bMOXjTTXdXebfAk5Dg4pZqZtPXasAL0+DvPlcoh+5eRns2zFMeHmE4kJKZcf90C8Be239Xc2eqgPEOQOiy4f82JlEP3ThFBjLMGJqHd5Me9sNfd0HfwKc2435is3F76TZFLHeV2BzC6Fsu5PYCx4yguvtgUq3Av2TPszMLhQ00dD7HwBX9c6+lNq8Lfz4EDi7ExJ9DVRX25eA5n3gerohS88BNx/H4yl7b+OCv+Y74JRkmGT1+oeyXBacKwAhMAd21Rqk3HqQAAL7d0KwWEEVadDwBFbHHPpn/aYjkaA5AXhyi9zKE9WZ/MgYaJIMiAsQnB+B1JzEC9zoINisQtAonyg1R2C22YN75/0a4ma0JxWnG26A84EGwqACheD1gl29Hqpr90Aog8BRE4RhCyDXgC7yUHHAp0AEXS53C/FXVMakxlIJb50Wvx0B5UXAaUdSeSVUbbe/ZdAkZvBSnCgDNMwDUQ5agcVTlwfkc0UVTW4qA52yAQJA4xwYsQSHGGRdI4hKjciVViRn5YFGqHhZABFLGiPocjiWQvQWl1CqlYVonAf3dQLxXDy6iLjNJpo8hMwcUFaGOMeD5wRxSgHu8KJql99DvgBZsjDj7AAlKgAAAABJRU5ErkJggg==[/img]", # "[img]file:///C:/Users/blusc/AppData/Roaming/TS3Client/styles/dark/apply.svg[/img]", "[img]https://badges-content.teamspeak.com/{}/{}.svg[/img]". format(badge, lst[badge]["filename"] if badge in lst else "unknown"), self.badgeNameByUID(badge, lst) if badge in lst else badge)) return _return def saveBadges(self, external): db = ts3client.Config() query = QSqlQuery(db) (timestamp, internal, array) = loadBadges() delimiter = array.mid(0, 12) delimiter1 = 0 delimiter2 = 0 delimiter3 = 0 delimiter4 = 0 guid_len = 0 guid = "" name_len = 0 name = "" url_len = 0 url = "" desc_len = 0 desc = "" for i in range(0, array.size()): if i == 12: #guid_len guid_len = int(array.at(i)) guid = str(array.mid(i + 1, guid_len)) elif i == (12 + 1 + guid_len + 1): delimiter1 = array.mid(i - 1, i - 1) name_len = int(array.at(i)) name = str(array.mid(i + 1, name_len)) elif i == (12 + 1 + guid_len + 1 + name_len + 2): delimiter2 = array.mid(i - 1, i - 1) url_len = int(array.at(i)) url = str(array.mid(i + 1, url_len)) elif i == (12 + 1 + guid_len + 1 + name_len + 2 + url_len + 2): delimiter3 = array.mid(i - 3, i - 3) delimiter4 = array.mid(i + desc_len, i + desc_len) desc_len = int(array.at(i)) desc = str(array.mid(i + 1, desc_len)) break print("delimiter:", delimiter.toHex()) print("delimiter1:", delimiter1.toHex()) print("delimiter2:", delimiter2.toHex()) print("delimiter3:", delimiter3.toHex()) print("delimiter4:", delimiter4.toHex()) print("array:", array.toHex()) # query.prepare( "UPDATE Badges (BadgesListData) VALUES (:byteArray)" ); # query.bindValue( ":imageData", array); def badgeNameByUID(self, uid, lst=badges): for badge in lst: if badge == uid: return lst[badge]["name"] def requestBadges(self): self.nwmc_badges = QNetworkAccessManager() self.nwmc_badges.connect("finished(QNetworkReply*)", self.loadBadges) self.nwmc_badges.get(QNetworkRequest(QUrl(self.badges_remote))) def loadBadges(self, reply): try: data = reply.readAll().data() # .decode('utf-8') self.badges = parseBadgesBlob(QByteArray(data))[0] except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) (tstamp, self.badges, array) = loadBadges() del self.nwmc_badges def requestBadgesExt(self): self.nwmc_ext = QNetworkAccessManager() self.nwmc_ext.connect("finished(QNetworkReply*)", self.loadBadgesExt) self.nwmc_ext.get(QNetworkRequest(QUrl(self.badges_ext_remote))) def loadBadgesExt(self, reply): try: data = reply.readAll().data().decode('utf-8') self.extbadges = loads(data) self.nwmc_exti = {} self.tmpfile = {} for badge in self.extbadges: _name = self.extbadges[badge]["filename"] _path = path.join(self.icons, _name) if path.exists(_path) and path.getsize(_path) > 0: continue self.requestExtIcon(_name) self.requestExtIcon("{}_details".format(_name)) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) del self.nwmc_exti def requestExtIcon(self, filename): self.nwmc_exti[filename] = QNetworkAccessManager() self.nwmc_exti[filename].connect("finished(QNetworkReply*)", self.loadExtIcon) self.tmpfile[filename] = QFile() self.tmpfile[filename].setFileName(path.join(self.icons, filename)) self.tmpfile[filename].open(QIODevice.WriteOnly) url = "https://raw.githubusercontent.com/R4P3-NET/CustomBadges/master/img/{}".format( filename) self.nwmc_exti[filename].get(QNetworkRequest(QUrl(url))) def loadExtIcon(self, reply): try: if reply.error() != QNetworkReply.NoError: ts3lib.logMessage( "Requesting \"{}\" failed:\n{}".format( reply.url().toString(), reply.errorString()), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) return name = reply.url().fileName() self.tmpfile[name].write(reply.readAll()) if self.tmpfile[name].isOpen(): self.tmpfile[name].close() self.tmpfile[name].deleteLater() except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def checkNotice(self): self.notice_nwmc.connect("finished(QNetworkReply*)", self.loadNotice) self.notice_nwmc.get( QNetworkRequest( QUrl( "https://raw.githubusercontent.com/R4P3-NET/CustomBadges/master/notice" ))) def loadNotice(self, reply): data = reply.readAll().data().decode('utf-8') if not path.isfile(self.txt): with open(self.txt, 'w'): pass data_local = "" with open(self.txt, 'r') as myfile: data_local = myfile.read() myfile.close() data = data.strip() # print("data:", data) # print("data_local:", data_local) if data == "" or data == data_local.strip(): return # self.cfg.get('general', 'lastnotice') with open(self.txt, "w") as text_file: text_file.write(data) text_file.close() # self.cfg.set('general', 'lastnotice', data) title = "{} Notice!".format(self.name) msgBox(data, 0, title) ts3lib.printMessageToCurrentTab("{}\n\n{}".format(title, data)) def stop(self): saveCfg(self.ini, self.cfg) self.notice.stop() def configure(self, qParentWidget): self.openDialog() def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL: return if menuItemID == 0: self.openDialog() elif menuItemID == 1: self.saveBadges(self.extbadges) for i in range(0, 3): # 0c4u2snt-ao1m-7b5a-d0gq-e3s3shceript uid = [ random_string(8, string.ascii_lowercase + string.digits) ] for _i in range(0, 3): uid.append( random_string(4, string.ascii_lowercase + string.digits)) uid.append( random_string(12, string.ascii_lowercase + string.digits)) ts3lib.printMessageToCurrentTab( "[color=red]Random UID #{}: [b]{}".format( i, '-'.join(uid))) def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber): if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED: self.setCustomBadges() def setCustomBadges(self): # try: if self.mode == HookMode.NONE: return overwolf = self.cfg.getboolean('general', 'overwolf') badges = self.cfg.get('general', 'badges').split(",") # if len(badges) > 0: badges += ['0c4u2snt-ao1m-7b5a-d0gq-e3s3shceript'] (err, schids) = ts3lib.getServerConnectionHandlerList() reg = compile('3(?:\.\d+)* \[Build: \d+\]') for schid in schids: _badges = badges err, ver = ts3lib.getServerVariable( schid, ts3defines.VirtualServerProperties.VIRTUALSERVER_VERSION) err, platform = ts3lib.getServerVariable( schid, ts3defines.VirtualServerProperties.VIRTUALSERVER_PLATFORM) if getServerType(schid, reg) in [ ServerInstanceType.TEASPEAK, ServerInstanceType.UNKNOWN ]: _badges = [x for x in badges if not x in self.extbadges][:3] _badges = buildBadges(_badges, overwolf) sendCommand(name=self.name, cmd=_badges, schid=schid, mode=self.mode) # except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def openDialog(self): if not self.dlg: self.dlg = BadgesDialog(self) self.dlg.show() self.dlg.raise_() self.dlg.activateWindow()
class RepositoryDialog(QDialog, pytson.Translatable): master_url = QUrl("https://raw.githubusercontent.com/pathmann/pyTSon_repository/master/repositorymaster.json") 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 onClosed(self): with open(pytson.getConfigPath("repositorymaster.json"), "w") as f: json.dump(list(self.replist.values()), f) def updatePendingButtons(self): if self.pending == 0: self.reloadButton.setEnabled(True) self.updateButton.setEnabled(True) self.loadingLabel.hide() self.masterloadingLabel.hide() else: self.reloadButton.setEnabled(False) self.updateButton.setEnabled(False) self.loadingLabel.show() self.masterloadingLabel.show() def updateRepositories(self): self.addons = {} self.pluginsList.clear() self.pending += sum(x["active"] for x in self.replist.values()) for rep in self.replist.values(): if all(x in rep for x in ['name', 'url', 'origin', 'active']): if rep["active"]: self.nwm.get(QNetworkRequest(QUrl(rep["url"]))) else: self.pending -= 1 ts3print(self._tr("Invalid repository in list, ignoring"), ts3defines.LogLevel.LogLevel_WARNING, "pyTSon.RepositoryDialog.updateRepositories", 0) self.updatePendingButtons() def updateMaster(self): self.pending += 1 self.masterloadingLabel.show() self.updateButton.setEnabled(False) self.nwm.get(QNetworkRequest(self.master_url)) self.updatePendingButtons() def handleMasterReply(self, reply): if reply.error() == QNetworkReply.NoError: try: repos = json.loads(reply.readAll().data().decode('utf-8')) for r in repos: if all(x in r for x in ["name", "url", "active", "origin"]): self.addRepository(r) else: ts3print(self._tr("Invalid entry in repositorymaster"), ts3defines.LogLevel.LogLevel_WARNING, "pyTSon.RepositoryManager.onNetworkReply", 0) except: ts3print(self._tr("Error reading repositorymaster: {trace}"). format(trace=traceback.format_exc()), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon.RepositoryManager.onNetworkReply", 0) self.updateMasterlist() def updateAddons(self, repo, addons): for a in addons: if all(x in a for x in ["name", "author", "version", "apiVersion", "description", "url"]): a["repository"] = repo["name"] if not a["name"] in self.addons: self.addons[a["name"]] = a else: ts3print(self._tr("Invalid entry in repository {name}: " "{repo}").format(name=repo["name"], repo=str(a)), ts3defines.LogLevel.LogLevel_WARNING, "pyTSon.RepositoryDialog.onNetworkReply", 0) break def handleRepositoryReply(self, reply): repo = None for r in self.replist.values(): if reply.url().url() == r["url"]: repo = r break if not repo: ts3print(self._tr("Error matching answer from {url} to a " "repository").format(url=reply.url().url()), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon.RepositoryDialog.onNetworkReply", 0) elif reply.error() == QNetworkReply.NoError: try: self.updateAddons(repo, json.loads(reply.readAll().data() .decode('utf-8'))) except ValueError as e: ts3print(self._tr("Error parsing repository {name}: " "{exception}").format(name=repo["name"], exception=str(e)), ts3defines.LogLevel.LogLevel_WARNING, "pyTSon.RepositoryDialog.onNetworkReply", 0) else: ts3print(self._tr("Network error updating repository {name}: " "{error}").format(name=repo["name"], error=reply.error()), ts3defines.LogLevel.LogLevel_WARNING, "pyTSon.RepositoryDialog.onNetworkReply", 0) if self.pending == 0: self.updateAddonlist() def onNetworkReply(self, reply): self.pending -= 1 if reply.url() == self.master_url: self.handleMasterReply(reply) else: self.handleRepositoryReply(reply) reply.deleteLater() self.updatePendingButtons() def addRepository(self, r): name = r["name"] if name in self.replist: if self.replist[name]["origin"] == "online": if self.replist[name]["url"] != r["url"]: self.replist[name]["url"] = r["url"] ts3print(self._tr("Url for repository {name} updated"). format(name=name), ts3defines.LogLevel.LogLevel_INFO, "pyTSon.RepositoryManager.addRepository", 0) else: ts3print(self._tr("Ignoring online repository {name}, got a " "local one with that name"). format(name=name), ts3defines.LogLevel.LogLevel_INFO, "pyTSon.RepositoryManager.addRepository", 0) else: self.replist[name] = r def updateMasterlist(self): self.repositoryList.clear() for name, r in self.replist.items(): item = QListWidgetItem(name) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setCheckState(Qt.Checked if r["active"] else Qt.Unchecked) item.setData(Qt.UserRole, name) self.repositoryList.addItem(item) def updateAddonlist(self): if self.pluginsList.currentItem(): cur = self.pluginsList.currentItem().text() else: cur = None self.pluginsList.clear() for a in self.addons.values(): if (self.replist[a["repository"]]["active"] and ("platforms" not in a or pytson.platformstr() in a["platforms"])): item = QListWidgetItem(a["name"], self.pluginsList) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(Qt.UserRole, a["name"]) if a["name"] in self.host.plugins: if a["version"] > self.host.plugins[a["name"]].version: item.setForeground(Qt.red) item.setToolTip(self._tr("Update available")) elif a["version"] == self.host.plugins[a["name"]].version: item.setForeground(Qt.green) item.setToolTip(self._tr("You have this plugin " "installed, no update " "available")) elif a["version"] < self.host.plugins[a["name"]].version: item.setForeground(Qt.gray) item.setToolTip(self._tr("Your local version has a " "greater version number")) if cur and a["name"] == cur: self.pluginsList.setCurrentItem(item) self.pluginsList.sortItems() def on_updateButton_clicked(self): self.updateMaster() def on_addButton_clicked(self): (res, name, url) = MultiInputDialog.getTexts(self._tr("Add repository"), self._tr("Name:"), self._tr("URL:"), "", "", self) if res: qurl = QUrl(url) if qurl.isValid() and not qurl.isLocalFile(): rep = dict() rep["name"] = name rep["url"] = url rep["origin"] = "local" rep["active"] = True self.replist[name] = rep item = QListWidgetItem(name) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setCheckState(Qt.Checked) item.setData(Qt.UserRole, name) self.repositoryList.addItem(item) else: QMessageBox.critical(self._tr("Error"), self._tr("The URL {url} is not valid"). format(url=url)) def on_deleteButton_clicked(self): cur = self.repositoryList.currentItem() if cur: name = cur.data(Qt.UserRole) if name not in self.replist: QMessageBox.critical(self._tr("Internal error"), self._tr("Can't find repository {name} " "in list").format(name=name)) return del self.replist[name] cur.delete() def on_repositoryList_doubleClicked(self, item): name = item.data(Qt.UserRole) try: rep = self.replist[name] except: QMessageBox.critical(self, self._tr("Internal error"), self._tr("Can't find repository {name} in " "list").format(name=name)) return ok = BoolResult() newurl = QInputDialog.getText(self, self._tr("Change url of repository " "{name}").format(name=name), self._tr("Url:"), QLineEdit.Normal, rep["url"], ok) if ok: rep["url"] = newurl rep["origin"] = "local" def on_repositoryList_currentItemChanged(self, cur, prev): if cur: name = cur.data(Qt.UserRole) if name not in self.replist: self.deleteButton.setEnabled(False) QMessageBox.critical(self, self._tr("Internal error"), self._tr("Can't find repository {name} " "in list").format(name=name)) return self.deleteButton.setEnabled(True) else: self.deleteButton.setEnabled(False) def on_repositoryList_itemChanged(self, item): if not item: return name = item.data(Qt.UserRole) if name not in self.replist: QMessageBox.critical(self, self._tr("Internal error"), self._tr("Can't find repository {name} in " "list").format(name=name)) return if self.replist[name]["active"] != (item.checkState() == Qt.Checked): self.replist[name]["active"] = (item.checkState() == Qt.Checked) self.updateAddonlist() def on_pluginsList_currentItemChanged(self, cur, prev): if cur: name = cur.data(Qt.UserRole) if name not in self.addons: QMessageBox.critical(self, self._tr("Internal error"), self._tr("Can't find addon {name} in " "list").format(name=name)) return p = self.addons[name] self.nameEdit.setText(p["name"]) self.authorEdit.setText(p["author"]) self.versionEdit.setText(p["version"]) self.descriptionEdit.setPlainText(p["description"]) self.apiEdit.setText(p["apiVersion"]) self.repositoryEdit.setText(p["repository"]) if name in self.host.plugins: if p["version"] > self.host.plugins[name].version: self.installButton.setEnabled(True) self.installButton.setText(self._tr("Update")) else: self.installButton.setEnabled(False) self.installButton.setText(self._tr("Install")) else: self.installButton.setEnabled(True) self.installButton.setText(self._tr("Install")) else: self.nameEdit.clear() self.authorEdit.clear() self.versionEdit.clear() self.descriptionEdit.clear() self.apiEdit.clear() self.repositoryEdit.clear() def on_reloadButton_clicked(self): self.updateRepositories() def on_installButton_clicked(self): item = self.pluginsList.currentItem() if not item: return name = item.data(Qt.UserRole) if name not in self.addons: QMessageBox.critical(self, self._tr("Internal error"), self._tr("Can't find addon {name} in list"). format(name=name)) return p = self.addons[name] # update?, so remove the local one first if name in self.host.plugins: if p["version"] > self.host.plugins[name].version: devtools.PluginInstaller.removePlugin(name) else: # should not happen (ui restricted) QMessageBox.critical(self, self._tr("Internal error"), self._tr("This plugin is already " "installed")) return self.installer = InstallDialog(self.host, self) self.installer.show() self.installer.install(p)
class Linkinfo(ts3plugin): name = "Linkinfo" requestAutoload = False version = "1.0.1" apiVersion = 22 author = "Luemmel" description = "Prints a Linkinfolink to the chat." offersConfigure = True commandKeyword = "" infoTitle = None hotkeys = [] menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Linkinfo settings", "")] directory = path.join(ts3.getPluginPath(), "pyTSon", "scripts", "linkinfo") protocols = [] domains = [] status = True mode = False wotapikey = "7132a9b89377c75f81f2ef87aa10896da7c28544" # def __init__(self): self.db = QSqlDatabase.addDatabase("QSQLITE", "pyTSon_linkinfo") self.db.setDatabaseName(path.join(self.directory, "linkinfo.db")) if not self.db.isValid(): raise Exception("Database invalid") if not self.db.open(): raise Exception("Could not open database.") d = self.db.exec_("SELECT * FROM domains ORDER BY domain ASC") while d.next(): self.domains.append(str(d.value("domain"))) p = self.db.exec_("SELECT * FROM protocols ORDER BY protocol ASC") while p.next(): self.protocols.append(str(p.value("protocol"))) s = self.db.exec_("SELECT * FROM settings") if s.next(): self.status = bool(s.value("status")) self.mode = bool(s.value("mode")) self.dlg = None def stop(self): self.db.close() self.db.delete() QSqlDatabase.removeDatabase("pyTSon_linkinfo") def configure(self, qParentWidget): self.open_dlg() def onMenuItemEvent(self, sch_id, a_type, menu_item_id, selected_item_id): if a_type == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL: if menu_item_id == 0: self.open_dlg() def open_dlg(self): if not self.dlg: self.dlg = SettingsDialog(self) self.dlg.show() self.dlg.raise_() self.dlg.activateWindow() return True def onTextMessageEvent(self, schid, targetMode, toID, fromID, fromName, fromUniqueIdentifier, message, ffIgnored): if self.status: (error, myid) = ts3.getClientID(schid) message = message.lower() if not myid == fromID and ("[url]" in message or "[url=" in message): domain_whitelisted = False for protocol in self.protocols: if protocol + "://" in message: domain_whitelisted = True for domain in self.domains: if "[url]http://" + domain in message or "[url]https://" + domain in message: domain_whitelisted = True if "[url=http://" + domain in message or "[url=https://" + domain in message: domain_whitelisted = True if "[url]http://www." + domain in message or "[url]https://www." + domain in message: domain_whitelisted = True if "[url=http://www." + domain in message or "[url=https://www." + domain in message: domain_whitelisted = True if "[url]www." + domain in message or "[url=www." + domain in message: domain_whitelisted = True if not domain_whitelisted: start = message.find("[url]") if not start == -1: end = message.find("[/url]") message = message[start + 5:end] else: start = message.find("[url=") end = message.find("]") message = message[start + 5:end] self.schid = schid self.myid = myid self.target = targetMode self.fromID = fromID self.getLinkInfo([message]) return message = "[[url=http://www.getlinkinfo.com/info?link=" + message + "]Linkinfo[/url]] " + message def getLinkInfo(self, urls): # https://www.mywot.com/wiki/API links = "/".join(urls) ts3lib.printMessageToCurrentTab("%s" % links) url = "http://api.mywot.com/0.4/public_link_json2?hosts=%s&key=%s" % ( links, self.wotapikey) ts3.logMessage('Requesting %s' % url, ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Linkinfo Script", 0) self.nwm = QNetworkAccessManager() self.nwm.connect("finished(QNetworkReply*)", self.onNetworkReply) self.nwm.get(QNetworkRequest(QUrl(url))) def onNetworkReply(self, reply): if reply.error() == QNetworkReply.NoError: try: message = str( json.loads(reply.readAll().data().decode('utf-8'))) if self.mode: if self.target == 1: ts3.requestSendPrivateTextMsg(self.schid, message, self.fromID) if self.target == 2: (error, mych) = ts3.getChannelOfClient(self.schid, self.myid) ts3.requestSendChannelTextMsg(self.schid, message, mych) else: ts3.printMessageToCurrentTab(str(message)) except: ts3.printMessageToCurrentTab(format_exc())
class dynamicAvatar(ts3plugin): shortname = "AC" name = "Dynamic Avatar Changer" requestAutoload = False version = "1.0" apiVersion = 22 author = "Bluscream" description = "Changes your avatar for you." offersConfigure = True commandKeyword = "" infoTitle = None menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Refresh avatar", path.join(ts3lib.getPluginPath(), "pyTSon", "scripts", "dynamicAvatar", "gfx", "manual.png")), (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 1, "Toggle Timer", '')] hotkeys = [] ini = path.join(getPluginPath(), "scripts", "dynamicAvatar", "settings.ini") config = ConfigParser() timer = QTimer() int = 0 def timestamp(self): return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now()) def __init__(self): if path.isfile(self.ini): self.config.read(self.ini) else: self.config['GENERAL'] = { "debug": "False", "imgurl": "", "imgpath": "", "mode": "url", "refresh": "60" } with open(self.ini, 'w') as configfile: self.config.write(configfile) self.timer.timeout.connect(self.tick) if self.config.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 tick(self, schid=0): schid = ts3lib.getCurrentServerConnectionHandlerID() self.int += 1 ts3lib.printMessageToCurrentTab('Tick %s' % self.int) if self.config.get('GENERAL', 'mode') == 'url': self.urlAvatar(schid) else: self.pathAvatar(schid) def configure(self, qParentWidget): try: self.dlg = SettingsDialog(self) self.dlg.show() except: from traceback import format_exc try: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon::" + self.name, 0) except: print("Error in " + self.name + ".configure: " + format_exc()) def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): try: if atype == ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL: if menuItemID == 0: if self.config.get('GENERAL', 'mode') == "url": self.urlAvatar(schid) elif self.config.get('GENERAL', 'mode') == "path": self.pathAvatar(schid) elif menuItemID == 1: if self.timer.isActive(): self.timer.stop() ts3lib.printMessageToCurrentTab('Timer stopped!') else: self.timer.start( int(self.config.get('GENERAL', 'refresh')) * 1000) ts3lib.printMessageToCurrentTab('Timer started!') except: try: from traceback import format_exc ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Script", 0) except: try: from traceback import format_exc print(format_exc()) except: print("Unknown Error") def urlAvatar(self, schid): try: self.nwm = QNetworkAccessManager() self.nwm.connect("finished(QNetworkReply*)", self.onNetworkReply) self.schid = schid print("%s" % self.config.get('GENERAL', 'imgurl')) self.nwm.get( QNetworkRequest(QUrl(self.config.get('GENERAL', 'imgurl')))) except: from traceback import format_exc try: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Script", 0) except: print(format_exc()) def onNetworkReply( self, reply ): #http://stackoverflow.com/questions/41712636/qnetworkrequest-for-generated-images try: print("Error: %s (%s)" % (reply.error(), reply.errorString())) print("Content-Type: %s" % reply.header(QNetworkRequest.ContentTypeHeader)) try: print("Content: %s" % reply.readAll()) except: pass #if reply.header(QNetworkRequest.ContentTypeHeader) == "image/jpeg": imgraw = reply.readAll() #.data()#.decode('utf-8') temp_dir = gettempdir() filename = self.generateAvatarFileName(self.schid) tmp = path.join(temp_dir, filename) fn = QFile(tmp) fn.open(QIODevice.WriteOnly) fn.write(imgraw) fn.close #with open(tmp, 'wb') as f: f.write(imgraw) ts3lib.logMessage("Uploading %s as new avatar." % tmp, ts3defines.LogLevel.LogLevel_INFO, "PyTSon Script", 0) self.uploadAvatar(self.schid, tmp, filename) except: from traceback import format_exc try: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Script", 0) except: print(format_exc()) reply.deleteLater() def pathAvatar(self, schid): try: _path = self.config.get('GENERAL', 'imgpath') img = path.join( _path, random.choice([ x for x in listdir(_path) if path.isfile(path.join(_path, x)) ])) if not self.getFileExtension(img) in [ 'bmp', 'gif', 'jpeg', 'jpg', 'pbm', 'pgm', 'png', 'ppm', 'xbm', 'xpm', None ]: self.pathAvatar(schid) return temp_dir = gettempdir() filename = self.generateAvatarFileName(schid) tmp = path.join(temp_dir, filename) copy2(img, tmp) ts3lib.logMessage("Uploading %s as new avatar." % img, ts3defines.LogLevel.LogLevel_INFO, "PyTSon Script", 0) self.uploadAvatar(schid, tmp, filename) except: from traceback import format_exc try: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Script", 0) except: print(format_exc()) def uploadAvatar(self, schid, img, filename=""): try: img = path.abspath(img) self.tmp = img if filename == "": filename = self.generateAvatarFileName(schid) imgdir = path.dirname(img) + path.sep self.retcode = ts3lib.createReturnCode() (error, ftid) = ts3lib.sendFile(schid, 0, "", "/avatar/" + filename, True, False, imgdir, self.retcode) except: try: from traceback import format_exc ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Script", 0) except: try: from traceback import format_exc print(format_exc()) except: print("Unknown Error") def setAvatar(self, schid, img): ts3lib.setClientSelfVariableAsString( schid, ts3defines.ClientPropertiesRare.CLIENT_FLAG_AVATAR, self.getMd5FromFile(img)) ts3lib.flushClientSelfUpdates(schid) def generateAvatarFileName(self, schid): (error, ownID) = ts3lib.getClientID(schid) (error, ownUID) = ts3lib.getClientVariableAsString( schid, ownID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER) ownUID = ownUID.encode('ascii') return "avatar_" + b64encode(ownUID).decode("ascii").split('=')[0] def getMd5FromFile(self, file): hash_md5 = md5() with open(file, "rb") as f: #f = iopen(file, 'rb') for chunk in iter(lambda: f.read(4096), b""): hash_md5.update(chunk) #f.close() return hash_md5.hexdigest() def getFileExtension(self, filename): basename = path.basename(filename) # os independent ext = '.'.join(basename.split('.')[1:]) return ext if ext else None def onServerErrorEvent(self, schid, errorMessage, error, returnCode, extraMessage): if hasattr(self, "retcode") and self.retcode == returnCode: self.retcode = None self.setAvatar(schid, self.tmp) try: remove(self.tmp) self.tmp = None except: QTimer.singleShot(500, self.deltmp) def deltmp(self): try: f = iopen(self.tmp) f.close() except: pass try: remove(self.tmp) self.tmp = None except: QTimer.singleShot(1000, self.tmp) # def onFileTransferStatusEvent(self, ftid, status, statusMessage, remotefileSize, schid): # Doesn't work in pyTSon # try: # print("test") # print(str("#"+ftid+": "+status)) # except: # try: from traceback import format_exc;ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "PyTSon Script", 0) # except: # try: from traceback import format_exc;print(format_exc()) # except: print("Unknown Error") def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber): if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED: if ts3lib.getServerVariableAsString( schid, ts3defines.VirtualServerProperties. VIRTUALSERVER_UNIQUE_IDENTIFIER ) == "QTRtPmYiSKpMS8Oyd4hyztcvLqU=": return # if not self.timer.isActive(): self.timer.start(int(self.config.get('GENERAL', 'refresh'))*1000); elif newStatus == ts3defines.ConnectStatus.STATUS_DISCONNECTED: if self.timer.isActive(): self.timer.stop()
class customBan(ts3plugin): path = getScriptPath(__name__) name = "Custom Ban" try: apiVersion = pytson.getCurrentApiVersion() except: apiVersion = 22 requestAutoload = False version = "1.0" author = "Bluscream" description = "Requested by @mrcraigtunstall (217.61.6.128)\nExtended for @SossenSystems (ts3public.de)" offersConfigure = False commandKeyword = "" infoTitle = None menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT, 0, "Ban Client", "scripts/%s/ban_client.svg" % __name__)] hotkeys = [] ini = "%s/config.ini" % path dlg = None cfg = ConfigParser() cfg["general"] = { "template": "", "whitelist": "", "ipapi": "http://ip-api.com/json/{ip}", "stylesheet": "alternate-background-color: white;background-color: black;" } cfg["last"] = { "ip": "False", "name": "False", "uid": "True", "mytsid": "True", "hwid": "True", "reason": "", "duration": "0", "expanded": "False", "height": "", "alternate": "False", "ban on doubleclick": "False" } templates = {} whitelist = ["127.0.0.1"] waiting_for = (0, 0) mytsids = {} regex_time = re.compile( r'^((?P<years>\d+?)y)?((?P<months>\d+?)M)?((?P<days>\d+?)d)?((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?$' ) suffix = "" prefix = "" times = 0 retcodes = [] clid = 0 def __init__(self): loadCfg(self.ini, self.cfg) url = self.cfg.get("general", "template") if url: self.nwmc_template = QNetworkAccessManager() self.nwmc_template.connect("finished(QNetworkReply*)", self.loadTemplates) self.nwmc_template.get(QNetworkRequest(QUrl(url))) url = self.cfg.get("general", "whitelist") if url: self.nwmc_whitelist = QNetworkAccessManager() self.nwmc_whitelist.connect("finished(QNetworkReply*)", self.loadWhitelist) self.nwmc_whitelist.get(QNetworkRequest(QUrl(url))) 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): saveCfg(self.ini, self.cfg) def onIncomingClientQueryEvent(self, schid, command): cmd = parseCommand(command) if cmd[0] == "notifycliententerview": if not cmd[1]["client_myteamspeak_id"]: return if not schid in self.mytsids: self.mytsids[schid] = {} self.mytsids[schid][cmd[1] ["clid"]] = cmd[1]["client_myteamspeak_id"] elif cmd[0] == "notifyclientleftview": if not schid in self.mytsids: return if not cmd[1]["clid"] in self.mytsids[schid]: return del self.mytsids[schid][cmd[1]["clid"]] def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_CLIENT or menuItemID != 0: return self.waiting_for = (schid, selectedItemID) ts3lib.requestClientVariables(schid, selectedItemID) def checkVars(self, schid, clid): (err, ownID) = ts3lib.getClientID(schid) (err, uid) = ts3lib.getClientVariable( schid, clid, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER) if ownID == clid: (err, uid) = ts3lib.getClientSelfVariable( schid, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER) if err != ts3defines.ERROR_ok or not uid: uid = False (err, mytsid) = ts3lib.getClientVariable(schid, clid, 61) if ownID == clid: (err, mytsid) = ts3lib.getClientSelfVariableAsString(schid, 61) if err != ts3defines.ERROR_ok or not mytsid: mytsid = False (err, ip) = ts3lib.getConnectionVariable( schid, clid, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) if err != ts3defines.ERROR_ok or not ip: ip = False return uid, mytsid, ip def onUpdateClientEvent(self, schid, clid, invokerID, invokerName, invokerUID): if schid != self.waiting_for[0]: return if clid != self.waiting_for[1]: return self.waiting_for = (0, 0) (err, uid) = ts3lib.getClientVariable( schid, clid, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER) if err != ts3defines.ERROR_ok: uid = "" (err, mytsid) = ts3lib.getClientVariable(schid, clid, 61) if err != ts3defines.ERROR_ok or not mytsid: if schid in self.mytsids and clid in self.mytsids[schid]: mytsid = self.mytsids[schid][clid] else: mytsid = "" (err, name) = ts3lib.getClientVariable( schid, clid, ts3defines.ClientProperties.CLIENT_NICKNAME) if err != ts3defines.ERROR_ok: name = "" self.clid = clid type = getServerType(schid) (err, ip) = ts3lib.getConnectionVariable( schid, clid, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) if (err != ts3defines.ERROR_ok or not ip) or (ip and ip == "None"): retcode = ts3lib.createReturnCode() self.retcodes.append(retcode) ts3lib.requestConnectionInfo(schid, clid, retcode) (err, ip) = ts3lib.getConnectionVariable( schid, clid, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) if not self.dlg: self.dlg = BanDialog(self, schid, clid, uid, name, ip, mytsid, "", type) else: self.dlg.setup(self, schid, clid, uid, name, ip, mytsid, ip, type) self.dlg.show() self.dlg.raise_() self.dlg.activateWindow() def onConnectionInfoEvent(self, schid, clid): if PluginHost.cfg.getboolean("general", "verbose"): print(self.name, "> onConnectionInfoEvent", schid, clid) if not hasattr(self, "clid") or clid != self.clid: return (err, ip) = ts3lib.getConnectionVariable( schid, clid, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) if ip: (err, ownid) = ts3lib.getClientID(schid) if ip == "None" and clid != ownid: retCode = ts3lib.createReturnCode() self.retcodes.append(retCode) ts3lib.requestConnectionInfo(schid, clid, retCode) return elif self.dlg: self.dlg.txt_ip.setText(ip) del self.clid def onServerErrorEvent(self, schid, errorMessage, error, returnCode, extraMessage): if not returnCode in self.retcodes: return self.retcodes.remove(returnCode) (err, ip) = ts3lib.getConnectionVariable( schid, self.clid, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) (err, ownid) = ts3lib.getClientID(schid) if ip and ip != "None" and self.clid != ownid: retCode = ts3lib.createReturnCode() self.retcodes.append(retCode) ts3lib.requestConnectionInfo(schid, self.clid, retCode) def checkIP(self): pass def parse_time(self, time_str): parts = self.regex_time.match(time_str) if not parts: return False parts = parts.groupdict() time_params = {} for (_name, param) in parts.items(): if not param: continue name = _name.lower() param = int(param) if name in ["years", "year", "y"]: name = "days" param = param * 365 elif name in ["months", "month"] or _name == "M": name = "days" param = param * 30.417 time_params[name] = int(param) return timedelta(**time_params) def loadTemplates(self, reply): try: data = reply.readAll().data().decode('utf-8') # if PluginHost.cfg.getboolean("general", "verbose"): json_data = loads(data, object_pairs_hook=OrderedDict) if "prefix" in json_data: self.prefix = json_data["prefix"] if "suffix" in json_data: self.suffix = json_data["suffix"] templates = json_data["templates"] for reason, duration in templates.items(): try: if isinstance(duration, int): continue if duration.isdigit(): templates[reason] = int(duration) elif isinstance(duration, str): if duration.lower() in [ "max", "perm", "permanent", "infinite" ]: templates[reason] = 0 continue delta = self.parse_time(duration) if not delta: print("Can't load", reason, duration) continue templates[reason] = int(delta.total_seconds()) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) self.templates = templates if PluginHost.cfg.getboolean("general", "verbose"): print(self.name, "> Downloaded ban templates:", self.templates) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def loadWhitelist(self, reply): try: data = reply.readAll().data().decode('utf-8') self.whitelist = [] for line in data.splitlines(): ip = QHostAddress(line.strip()) if ip.isNull(): print(self.name, ">", line, "is not a valid IP! Not adding to whitelist.") else: self.whitelist.append(line.strip()) if PluginHost.cfg.getboolean("general", "verbose"): print(self.name, "> Downloaded ip whitelist:", self.whitelist) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0)
class customBadges(ts3plugin): name = "Custom Badges" try: apiVersion = getCurrentApiVersion() except: apiVersion = 21 requestAutoload = False version = "0.9.3.1" author = "Bluscream" description = "Automatically sets some badges for you :)" offersConfigure = True commandKeyword = "" infoTitle = "[b]Badges[/b]" menuItems = [ (ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Change " + name, "")#, #(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 1, "Generate Badge UIDs", "") ] hotkeys = [] icons = path.join(ts3lib.getConfigPath(), "cache", "badges") ini = path.join(getPluginPath(), "scripts", "customBadges", "settings.ini") ui = path.join(getPluginPath(), "scripts", "customBadges", "badges.ui") badges_ext = path.join(getPluginPath(), "include", "badges_ext.json") badges_ext_remote = "https://raw.githubusercontent.com/R4P3-NET/CustomBadges/master/badges.json" cfg = ConfigParser() dlg = None cfg["general"] = { "cfgversion": "1", "debug": "False", "enabled": "True", "badges": "", "overwolf": "False", "lastnotice": "" } badges = {} extbadges = {} notice = QTimer() notice_nwmc = QNetworkAccessManager() def __init__(self): try: loadCfg(self.ini, self.cfg) (tstamp, self.badges, array) = loadBadges() self.requestBadgesExt() self.notice.timeout.connect(self.checkNotice) self.notice.start(30*1000) # 180 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)) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def infoData(self, schid, id, atype): if atype != ts3defines.PluginItemType.PLUGIN_CLIENT: return None (err, ownID) = ts3lib.getClientID(schid) if ownID != id: return None # overwolf = self.cfg.getboolean('general', 'overwolf') # badges = self.cfg.get('general', 'badges').split(',') (err, badges) = ts3lib.getClientVariable(schid, id, ts3defines.ClientPropertiesRare.CLIENT_BADGES) (overwolf, badges) = parseBadges(badges) _return = ["Overwolf: {0}".format("[color=green]Yes[/color]" if overwolf else "[color=red]No[/color]")] # i = [] # for badge in badges: # if badge for badge in badges: lst = self.badges if badge in self.extbadges: lst = self.extbadges _return.append("{} {}".format( "[img]https://badges-content.teamspeak.com/{}/{}.svg[/img]".format(badge, lst[badge]["filename"] if badge in lst else "unknown"), self.badgeNameByUID(badge, lst) if badge in lst else badge )) return _return def saveBadges(self, external): db = ts3client.Config() query = QSqlQuery(db) (timestamp, internal, array) = loadBadges() delimiter = array.mid(0, 12) delimiter1 = 0;delimiter2 = 0;delimiter3 = 0;delimiter4 = 0 guid_len = 0;guid = "" name_len = 0;name = "" url_len = 0;url = "" desc_len = 0;desc = "" for i in range(0, array.size()): if i == 12: #guid_len guid_len = int(array.at(i)) guid = str(array.mid(i+1, guid_len)) elif i == (12 + 1 + guid_len + 1): delimiter1 = array.mid(i - 1,i - 1) name_len = int(array.at(i)) name = str(array.mid(i+1, name_len)) elif i == (12 + 1 + guid_len + 1 + name_len + 2): delimiter2 = array.mid(i - 1,i - 1) url_len = int(array.at(i)) url = str(array.mid(i+1, url_len)) elif i == (12 + 1 + guid_len + 1 + name_len + 2 + url_len + 2): delimiter3 = array.mid(i - 3,i - 3) delimiter4 = array.mid(i+desc_len,i+desc_len) desc_len = int(array.at(i)) desc = str(array.mid(i+1, desc_len)) break print("delimiter:", delimiter.toHex()) print("delimiter1:", delimiter1.toHex()) print("delimiter2:", delimiter2.toHex()) print("delimiter3:", delimiter3.toHex()) print("delimiter4:", delimiter4.toHex()) print("array:", array.toHex()) # query.prepare( "UPDATE Badges (BadgesListData) VALUES (:byteArray)" ); # query.bindValue( ":imageData", array); def badgeNameByUID(self, uid, lst=badges): for badge in lst: if badge == uid: return lst[badge]["name"] def requestBadgesExt(self): try: with open(self.badges_ext, encoding='utf-8-sig') as json_file: self.extbadges = load(json_file) except: self.nwmc_ext = QNetworkAccessManager() self.nwmc_ext.connect("finished(QNetworkReply*)", self.loadBadgesExt) self.nwmc_ext.get(QNetworkRequest(QUrl(self.badges_ext_remote))) def loadBadgesExt(self, reply): try: data = reply.readAll().data().decode('utf-8') self.extbadges = loads(data) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def checkNotice(self): self.notice_nwmc.connect("finished(QNetworkReply*)", self.loadNotice) self.notice_nwmc.get(QNetworkRequest(QUrl("https://raw.githubusercontent.com/R4P3-NET/CustomBadges/master/notice"))) def loadNotice(self, reply): data = reply.readAll().data().decode('utf-8') if data.strip() == "" or data == self.cfg.get('general', 'lastnotice'): return msgBox(data, 0, "{} Notice!".format(self.name)) self.cfg.set('general', 'lastnotice', data) def stop(self): saveCfg(self.ini, self.cfg) self.notice.stop() def configure(self, qParentWidget): self.openDialog() def onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if atype != ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL: return if menuItemID == 0: self.openDialog() elif menuItemID == 1: self.saveBadges(self.extbadges) for i in range(0,3): # 0c4u2snt-ao1m-7b5a-d0gq-e3s3shceript uid = [random_string(size=8, chars=string.ascii_lowercase + string.digits)] for _i in range(0,3): uid.append(random_string(size=4, chars=string.ascii_lowercase + string.digits)) uid.append(random_string(size=12, chars=string.ascii_lowercase + string.digits)) ts3lib.printMessageToCurrentTab("[color=red]Random UID #{}: [b]{}".format(i, '-'.join(uid))) def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber): if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED: self.setCustomBadges() def setCustomBadges(self): try: overwolf = self.cfg.getboolean('general', 'overwolf') badges = self.cfg.get('general', 'badges').split(",") # if len(badges) > 0: badges += ['0c4u2snt-ao1m-7b5a-d0gq-e3s3shceript'] (err, schids) = ts3lib.getServerConnectionHandlerList() for schid in schids: sendCommand(self.name, buildBadges(badges, overwolf), schid) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def openDialog(self): if not self.dlg: self.dlg = BadgesDialog(self) self.dlg.show() self.dlg.raise_() self.dlg.activateWindow()
class BanDialog(QDialog): moveBeforeBan = False clid = 0 countries = None icon_warning = None def __init__(self, script, schid, clid, uid, name, ip, mytsid, hwid, servertype, parent=None): try: super(QDialog, self).__init__(parent) setupUi(self, "%s/ban.ui" % script.path) try: icons = IconPack.current() icons.open() self.icon_warning = QIcon(icons.icon("WARNING")) except: pass self.setAttribute(Qt.WA_DeleteOnClose) self.cfg = script.cfg self.ini = script.ini self.schid = schid self.templates = script.templates self.whitelist = script.whitelist self.prefix = script.prefix self.suffix = script.suffix self.name = script.name if script.cfg.getboolean("last", "expanded"): self.disableReasons(True) height = script.cfg.get("last", "height") if height: self.resize(self.width, int(height)) else: self.disableReasons() alt = script.cfg.getboolean("last", "alternate") if alt: self.chk_alternate.setChecked(True) dblclick = script.cfg.getboolean("last", "ban on doubleclick") if dblclick: self.chk_doubleclick.setChecked(True) for reason in script.templates: self.lst_reasons.addItem(reason) self.box_reason.addItem(reason) self.box_reason.setEditText(script.cfg.get( "last", "reason")) # setItemText(0, ) """ ipREX = QRegExp("[\w+\/]{27}=") ipREX.setCaseSensitivity(Qt.CaseInsensitive) ipREX.setPatternSyntax(QRegExp.RegExp) regValidator = QRegExpValidator(ipREX,0) self.txt_ip.setValidator(regValidator) """ # self.txt_ip.setInputMask( "000.000.000.000" ) self.setup(script, schid, clid, uid, name, ip, mytsid, hwid, servertype) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def setup(self, script, schid, clid, uid, name, ip, mytsid, hwid, servertype): self.setWindowTitle("Ban \"{}\" ({})".format(name, clid)) self.clid = clid if not ip: (err, ip) = ts3lib.getConnectionVariable( schid, clid, ts3defines.ConnectionProperties.CONNECTION_CLIENT_IP) url = script.cfg.get("general", "ipapi") if url: self.nwmc_ip = QNetworkAccessManager() self.nwmc_ip.connect("finished(QNetworkReply*)", self.checkIP) self.countries = CountryFlags() self.countries.open() self.disableISP() self.grp_ip.setChecked(script.cfg.getboolean("last", "ip")) if ip != "None": self.txt_ip.setText(ip) self.on_txt_ip_textChanged(ip) self.grp_name.setChecked(script.cfg.getboolean("last", "name")) self.txt_name.setText(name) self.on_txt_name_textChanged(name) self.grp_uid.setChecked(script.cfg.getboolean("last", "uid")) self.txt_uid.setText(uid) self.on_txt_uid_textChanged(uid) self.grp_mytsid.setChecked(script.cfg.getboolean("last", "mytsid")) self.txt_mytsid.setText(mytsid) self.on_txt_mytsid_textChanged(mytsid) if servertype == ServerInstanceType.TEASPEAK: self.grp_hwid.setChecked(script.cfg.getboolean("last", "hwid")) self.txt_hwid.setText(hwid) self.on_txt_hwid_textChanged(hwid) else: self.grp_hwid.setVisible(False) self.setDuration(script.cfg.getint("last", "duration")) def disableReasons(self, enable=False): for item in [ self.lst_reasons, self.line, self.chk_alternate, self.chk_doubleclick, self.chk_keep ]: item.setVisible(enable) if enable: self.btn_reasons.setText("Reasons <") self.setFixedWidth(675) # self.resize(675, self.height) else: self.btn_reasons.setText("Reasons >") self.setFixedWidth(320) # self.resize(320, self.height) def disableISP(self, enable=False): # if not enable and self.txt_loc.isVisible(): return # elif enable and not self.txt_loc.isVisible(): return for item in [self.lbl_isp, self.txt_isp, self.lbl_flag, self.txt_loc]: item.setVisible(enable) def disableAlt(self, enable=False): self.lst_reasons.setAlternatingRowColors(enable) self.lst_reasons.setStyleSheet( self.cfg.get("general", "stylesheet") if enable else "") def checkIP(self, reply): try: data = reply.readAll().data().decode('utf-8') # if PluginHost.cfg.getboolean("general", "verbose"): print(self.name,"> checkIP() data:",data) if PluginHost.cfg.getboolean("general", "verbose"): print(self.name, "> Resolved IP ", self.txt_ip.text, ":", data) data = loads(data) if data["status"] != "success": self.disableISP() return self.txt_isp.setText(data["isp"]) self.txt_loc.setText("{}, {}, {}".format(data["city"], data["regionName"], data["country"])) code = data["countryCode"] self.lbl_flag.setToolTip(code) self.lbl_flag.setPixmap(self.countries.flag(code)) if not self.txt_isp.isVisible(): self.disableISP(True) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_txt_ip_textChanged(self, text): try: if not hasattr(self, "nwmc_ip"): self.disableISP() return if not text: self.disableISP() return if len(text) < 7: self.disableISP() return ip = QHostAddress(text) if ip.isNull() or ip.isLoopback() or ip.isMulticast(): self.disableISP() return if text.strip() in ["127.0.0.1", "0.0.0.0", "255.255.255"]: self.disableISP() return self.nwmc_ip.get( QNetworkRequest( QUrl(self.cfg.get("general", "ipapi").format(ip=text)))) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_txt_name_textChanged(self, text): self.validate(self.txt_name, '^.{3,32}$', text) def on_txt_uid_textChanged(self, text): self.validate(self.txt_uid, '^[\w+\/]{27}=$', text) # '^music#[\w]{15}$' def on_txt_mytsid_textChanged(self, text): self.validate(self.txt_mytsid, '^[\w+\/]{44}$', text) def on_txt_hwid_textChanged(self, text): self.validate(self.txt_hwid, '^[a-z0-9]{32},[a-z0-9]{32}$', text) def validate(self, elem, pattern, text, reason=None): try: actions = elem.actions() if not text: elem.setToolTip("") if self.icon_warning: if len(actions): elem.removeAction(actions[0]) else: elem.setStyleSheet("") valid = re.match(pattern, text) if not valid: if reason: elem.setToolTip(reason) else: elem.setToolTip("This {name} seems to be invalid!".format( name=elem.parentWidget().title)) if self.icon_warning: if not len(actions): elem.addAction(self.icon_warning, QLineEdit.LeadingPosition) else: elem.setStyleSheet("background-color:#5C4601") else: elem.setToolTip("") if self.icon_warning: if len(actions): elem.removeAction(actions[0]) else: elem.setStyleSheet("") except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_box_reason_currentTextChanged(self, text): if not text in self.templates: return self.setDuration(self.templates[text]) self.validate(self.txt_reason, '^[\w+\/]{{,80}}$', text, "This {name} is too long! (max 80 chars)") def on_lst_reasons_itemClicked(self, item): try: self.box_reason.setEditText(item.text()) except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_lst_reasons_itemDoubleClicked(self, item): if not self.chk_doubleclick.isChecked(): return self.box_reason.setEditText(item.text()) self.on_btn_ban_clicked() def on_chk_alternate_toggled(self, enabled): self.disableAlt(enabled) def setDuration(self, bantime): seconds = int(bantime) # delta = timedelta(seconds=bantime) # days, seconds = delta.days, delta.seconds days = seconds // 86400 hours = seconds % 86400 // 3600 minutes = (seconds % 3600) // 60 seconds = (seconds % 60) self.int_duration_s.setValue(seconds) self.int_duration_m.setValue(minutes) self.int_duration_h.setValue(hours) self.int_duration_d.setValue(days) """ def on_grp_hwid_toggled(self, enabled:bool): if enabled: self.grp_ip.setChecked(True) self.grp_uid.setChecked(True) self.grp_mytsid.setChecked(True) self.grp_name.setEnabled(False) else: self.grp_name.setEnabled(True) """ def on_btn_regex_clicked(self): regex = "" name = self.txt_name.text.strip() self.txt_name.setText(name) name = re.escape(name) for char in name: if char.isalpha(): regex += "[%s%s]" % (char.upper(), char.lower()) else: regex += char self.txt_name.setText(".*%s.*" % regex) def on_btn_ban_clicked(self): try: ip = self.txt_ip.text if self.grp_ip.isChecked() else "" name = self.txt_name.text if self.grp_name.isChecked() else "" uid = self.txt_uid.text if self.grp_uid.isChecked() else "" mytsid = self.txt_mytsid.text if self.grp_mytsid.isChecked( ) else "" hwid = self.txt_hwid.text if self.grp_hwid.isVisible( ) and self.grp_hwid.isChecked() else "" _reason = self.box_reason.currentText delta = timedelta(seconds=self.int_duration_s.value, minutes=self.int_duration_m.value, hours=self.int_duration_h.value, days=self.int_duration_d.value) # duration = self.templates[_reason] err, ownnick = ts3lib.getClientSelfVariable( self.schid, ts3defines.ClientProperties.CLIENT_NICKNAME) reason = "{}{}{}".format(self.prefix, _reason, self.suffix) # delta = timedelta(seconds=duration) print(delta) reason = reason.replace("%ownnick%", ownnick).replace("%duration%", str(delta)) # if reason[0].isdigit(): reason = "" + reason duration = int(delta.total_seconds()) if self.moveBeforeBan: ts3lib.requestClientMove(self.schid, self.clid, 26, "") # if uid: if ip: check = True if len(self.whitelist) < 1: check = confirm( "Empty IP Whitelist!", "The IP whitelist is empty! Are you sure you want to ban \"{}\"?\n\nMake sure your whitelist URL\n{}\nis working!" .format(ip, self.cfg.get("general", "whitelist"))) if ip in self.whitelist: ts3lib.printMessageToCurrentTab( "{}: [color=red]Not banning whitelisted IP [b]{}". format(self.name, ip)) elif check: ts3lib.banadd(self.schid, ip, "", "", duration, reason) if name: ts3lib.banadd(self.schid, "", name, "", duration, reason) if uid: ts3lib.banadd(self.schid, "", "", uid, duration, reason) if mytsid: ts3lib.requestSendClientQueryCommand( self.schid, "banadd mytsid={id} banreason={reason} time={duration}". format(id=mytsid, reason=escapeStr(reason), duration=duration)) if hwid: ts3lib.requestSendClientQueryCommand( self.schid, "banadd hwid={id} banreason={reason} time={duration}". format(id=hwid, reason=escapeStr(reason), duration=duration)) # msgBox("schid: %s\nip: %s\nname: %s\nuid: %s\nduration: %s\nreason: %s"%(self.schid, ip, name, uid, duration, reason)) self.cfg["last"] = { "ip": str(self.grp_ip.isChecked()), "name": str(self.grp_name.isChecked()), "uid": str(self.grp_uid.isChecked()), "mytsid": str(self.grp_mytsid.isChecked()), "hwid": str(self.grp_hwid.isChecked()), "reason": _reason, "duration": str(duration), "expanded": str(self.lst_reasons.isVisible()), "height": str(self.height), "alternate": str(self.chk_alternate.isChecked()), "ban on doubleclick": str(self.chk_doubleclick.isChecked()), } if not self.chk_keep.isChecked(): self.close() except: ts3lib.logMessage(format_exc(), ts3defines.LogLevel.LogLevel_ERROR, "pyTSon", 0) def on_btn_cancel_clicked(self): self.cfg.set("last", "expanded", str(self.lst_reasons.isVisible())) self.cfg.set("last", "height", str(self.height)) self.cfg.set("last", "alternate", str(self.chk_alternate.isChecked())) self.cfg.set("last", "ban on doubleclick", str(self.chk_doubleclick.isChecked())) self.close() def on_btn_reasons_clicked(self): if self.lst_reasons.isVisible(): self.disableReasons() else: self.disableReasons(True)
def getFile(url): nwmc = QNetworkAccessManager() nwmc.connect("finished(QNetworkReply*)", getFile) nwmc.get(QNetworkRequest(QUrl(url)))
class notify(ts3plugin): name = "Notifier" apiVersion = 22 requestAutoload = False version = "1.0" author = "Bluscream" description = "Automatically notifies other clients about:\n\n○ Outdated Clients\n○ Unread Offline Messages.\n\nCheck out https://r4p3.net/forums/plugins.68/ for more plugins." offersConfigure = False commandKeyword = "" infoTitle = None menuItems = [(ts3defines.PluginMenuType.PLUGIN_MENU_TYPE_GLOBAL, 0, "Toggle " + name, "")] hotkeys = [] debug = False toggle = True requested = False checkOutdatedVersion = True checkUnreadMessages = True blacklist = ["QTRtPmYiSKpMS8Oyd4hyztcvLqU="] versions = { "clientver": "3.1.6", "clientrev": 1502873983, "serverver": "3.0.13.8", "serverrev": 1500452811 } _sent = [] @staticmethod def timestamp(): return '[{:%Y-%m-%d %H:%M:%S}] '.format(datetime.now()) def __init__(self): self.nwmc = QNetworkAccessManager() self.requestVersions() 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 onMenuItemEvent(self, schid, atype, menuItemID, selectedItemID): if menuItemID != 0: return self.toggle = not self.toggle ts3.printMessageToCurrentTab( '{} Set {} to [color=yellow]{}[/color]'.format( self.timestamp(), self.name, self.toggle)) def onClientMoveEvent(self, schid, clientID, oldChannelID, newChannelID, visibility, moveMessage): if not self.toggle: return (error, _clid) = ts3.getClientID(schid) if clientID != _clid and oldChannelID == 0: self.requested = True ts3.requestClientVariables(schid, clientID) def onConnectStatusChangeEvent(self, schid, newStatus, errorNumber): if newStatus == ts3defines.ConnectStatus.STATUS_CONNECTION_ESTABLISHED: error, targetVer = ts3.getServerVariable( schid, ts3defines.VirtualServerProperties.VIRTUALSERVER_VERSION) if self.debug: ts3.printMessageToCurrentTab( "schid: {} error: {} targetVer: {} targetRev: {} serverRev: {}" .format(schid, error, targetVer, self.parseVersion(targetVer), self.versions["serverrev"])) if error == ts3defines.ERROR_ok and self.parseVersion( targetVer)["rev"] < self.versions["serverrev"]: ts3.printMessageToCurrentTab( "[color=red]This server is using a outdated version ({}). It might be vulnerable!" .format(targetVer)) def onUpdateClientEvent(self, schid, clientID, invokerID, invokerName, invokerUniqueIdentifier): if not self.requested or not self.toggle: return error, _uid = ts3.getServerVariable( schid, ts3defines.VirtualServerProperties.VIRTUALSERVER_UNIQUE_IDENTIFIER) if _uid in self.blacklist: return self.requested = False (error, _uid) = ts3.getClientVariable( schid, clientID, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER) if _uid in self._sent: return _done = False (error, country) = ts3.getClientVariable( schid, clientID, ts3defines.ClientPropertiesRare.CLIENT_COUNTRY) if self.debug: ts3.printMessageToCurrentTab( "clid: {} error: {} country: {}".format( clientID, error, country)) if self.checkOutdatedVersion: (error, platform) = ts3.getClientVariable( schid, clientID, ts3defines.ClientProperties.CLIENT_PLATFORM) if self.debug: ts3.printMessageToCurrentTab( "clid: {} error: {} platform: {}".format( clientID, error, platform)) if not platform in ["Windows", "OSX", "Linux"]: return (error, targetVer) = ts3.getClientVariable( schid, clientID, ts3defines.ClientProperties.CLIENT_VERSION) if self.debug: ts3.printMessageToCurrentTab( "clid: {} error: {} targetVer: {}".format( clientID, error, targetVer)) if error == ts3defines.ERROR_ok: current = self.parseVersion(targetVer) if current["rev"] < self.versions["clientrev"]: if country in ["DE", "CH", "AT"]: msg = """[b][color=red]Hinweis[/color][/b] Du nutzt eine veraltete Version von Teamspeak ([color=red]{current}[/color]). Bitte aktualisiere deinen Client auf Version [color=blue]{latest}[/color] um mögliche Sicherheitsrisiken auszuschliessen. Um zu updaten gehe einfach auf "Hilfe" => "Nach Aktualisierung suchen" Falls du nicht aktualisierst setzt du dich unter Umständen einigen Gefahren aus. Hier mal ein paar Beispiele: https://r4p3.net/resources/exploit-overview.84/ """ else: msg = """[b][color=red]Attention[/color][/b] You are using a outdated version of Teamspeak ([color=red]{current}[/color]). Your version is very likely vulnerable to several exploits. Please update your Client to Version [color=blue]{latest}[/color] To update click on "Help" => "Check for Update" If you don't update you might risk your computer being hacked. Some examples: https://r4p3.net/resources/exploit-overview.84/ """ ts3.requestSendPrivateTextMsg( schid, msg.format(current=current["ver"], latest=self.versions["clientver"]), clientID) _done = True if self.checkUnreadMessages: (error, platform) = ts3.getClientVariable( schid, clientID, ts3defines.ClientProperties.CLIENT_PLATFORM) if self.debug: ts3.printMessageToCurrentTab( "clid: {} error: {} platform: {}".format( clientID, error, platform)) if platform in ["Android", "iOS"]: return (error, messages) = ts3.getClientVariableAsInt( schid, clientID, ts3defines.ClientPropertiesRare.CLIENT_UNREAD_MESSAGES) if self.debug: ts3.printMessageToCurrentTab( "clid: {} error: {} messages: {}".format( clientID, error, messages)) if messages > 0: if country in ["DE", "CH", "AT"]: msg = """[b][color=orange]Hinweis[/color][/b] Du hast [color=blue]%s[/color] ungelesene Offline Nachrichte(n). Du kannst sie nachlesen indem du auf \"Extras\" => \"Offline Nachrichten\" klickst oder einfach [STRG]+[O] auf deiner Tastatur drückst. """ else: msg = """[b][color=orange]Reminder[/color][/b] You have [color=blue]%s[/color] unread offline message(s). You can read them by clicking on \"Tools\" => \"Offline Messages\" or pressing [CTRL]+[O] on your keyboard. """ ts3.requestSendPrivateTextMsg(schid, msg % messages, clientID) _done = True if _done: self._sent.extend([_uid]) (err, _ownuid) = ts3.getClientSelfVariable( schid, ts3defines.ClientProperties.CLIENT_UNIQUE_IDENTIFIER) close = ts3.clientChatClosed(schid, _ownuid, clientID) if self.debug: ts3.printMessageToCurrentTab( "\nSCHID: {}\nownUID: {}\nclientID: {}\nclientUID: {}\nclosed: {}\nerrorid: {}" .format(schid, _ownuid, clientID, _uid, close == ts3defines.ERROR_ok, close)) @staticmethod def parseVersion(ver): ver = ver.split(" ") return {"ver": ver[0], "rev": int(ver[2].split("]")[0])} def requestVersions(self): self.nwmc.connect("finished(QNetworkReply*)", self.onVersionReply) self.nwmc.get( QNetworkRequest( QUrl("https://api.planetteamspeak.com/updatecheck/"))) def onVersionReply(self, reply): self.versions = json.loads( reply.readAll().data().decode('utf-8'))["result"]