From 40cfb7800b5629b61c5924714861d9586728aa8a Mon Sep 17 00:00:00 2001 From: Fulgen301 Date: Wed, 15 Feb 2017 20:10:52 +0100 Subject: Add capabilities (WIP) --- pycrctrl.py | 145 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 36 deletions(-) (limited to 'pycrctrl.py') diff --git a/pycrctrl.py b/pycrctrl.py index 1d2248d..e53a722 100644 --- a/pycrctrl.py +++ b/pycrctrl.py @@ -97,6 +97,12 @@ class CmdResult(IntEnum): RightsFail = 2 RuntimeError = 3 +class Capability(IntEnum): + Unknown = -1 + User = 0 + Admin = 1 + Moderator = 2 + class PyCRCtrl(object): """Server control""" @@ -121,6 +127,7 @@ class PyCRCtrl(object): league = True __state = "Lobby" + __ingamechat = "aktiviert" #RegExps = { # "lobbyStartExp" : "((?:Los geht's!|Action go!)\s*)", @@ -130,13 +137,17 @@ class PyCRCtrl(object): # "shutdownExp" : r"^Internetspiel ausgewertet(.*)" # } + capabilities = {} + _capa_old = {} + def __init__(self, irc=None, path=None, config="pycrctrl.conf"): if sys.platform == "win32": - raise NotImplementedError("{} wird nicht unterstützt!".format(sys.platform)) + raise NotImplementedError("{} wird nicht unterstützt!".format(sys.platform)) self.irc = irc self.path = path self.loadConfigFile(config) + self.loadCapabilities() self.loadScenarioList() self.codec = codec = QTextCodec.codecForName(self.config.get("encoding")) self.queue = queue.Queue(5) @@ -152,7 +163,18 @@ class PyCRCtrl(object): def state(self, text): if text in ["Lobby", "Lädt", "Läuft"]: self.__state = text - self.setTopic("Aktuelles Szenario: {} | {}".format(self.scenario, self.state)) + topic = "Aktuelles Szenario: {} | {}{} | Ingamechat ist {}.".format(self.scenario, self.state, (" | Liga" if self.scenario in self.league_scenlist else ""), self.ingamechat) + self.setTopic(topic) + + @property + def ingamechat(self): + return self.__ingamechat + + @ingamechat.setter + def ingamechat(self, text): + if text in ["aktiviert", "deaktiviert"]: + self.__ingamechat = text + self.state = self.state def loadScenarioList(self) -> bool: if self.path == None: @@ -166,7 +188,15 @@ class PyCRCtrl(object): return True - def loadConfigFile(self, config): + def loadCapabilities(self) -> bool: + if self.path == None: + return False + + _capa_old = json.load(open(os.path.join(self.path, "capabilities.conf"), "r")) + return True + + + def loadConfigFile(self, config) -> bool: if self.path == None: return False @@ -187,7 +217,7 @@ class PyCRCtrl(object): return True - def host(self, scenario=None) -> str: + def host(self, scenario=None, user=None) -> str: if scenario == None: return (CmdResult.SyntaxFail, "Bitte gib einen Szenarionamen an!") if type(scenario) in [bytes, QByteArray]: @@ -211,7 +241,7 @@ class PyCRCtrl(object): if self.queue.full() == False: self.queue.put(scenario) - return (CmdResult.Success, 'Szenario "{}" wurde der Warteschlange hinzugefügt.'.format(scenario)) + return (CmdResult.Success, 'Szenario "{}" wurde der Warteschlange hinzugefügt.'.format(scenario)) else: return (CmdResult.RuntimeError, "Die Warteschlange ist voll!") @@ -223,6 +253,8 @@ class PyCRCtrl(object): self.scenario = self.queue.get() else: self.scenario = random.choice(self.scenlist) + + self.capabilities = self._capa_old self.clonk = subprocess.Popen( './{} {} "{}"'.format(self.config.get("engine"), self.config.get("commandline") + (" --" if type(self).__name__ == "PyOCCtrl" else " /") + ("league" if self.scenario in self.league_scenlist() else "noleague"),self.scenario), 0, @@ -267,22 +299,24 @@ class PyCRCtrl(object): if output[0] == ">": output = output[1:] - if output.find(self.config.get("prefix")) != -1 and output.find("<{}>".format(self.irc.nick)) == -1: - part = output[output.find(self.config.get("prefix"))+len(self.config.get("prefix")):].split(" ",1) + + part = re.match("<(.*)> ({})(.*)".format(self.config.get("prefix")), output) + if part and part.group(0) != self.irc.nick: + cmd = part.group(3).split(" ", 1) found = False x = None - if len(part) > 0: + if len(cmd) > 0: for key in self.commands.keys(): - if key == part[0].splitlines()[0]: + if key == cmd[0].splitlines()[0]: found = True try: - x = self.commands[key](part[1]) + x = self.commands[key](cmd[1].split(" "), user=part.group(1)) except IndexError: - x = self.commands[key]() + x = self.commands[key](user=part.group(1)) break if not found: - self.writeToServer('Unbekannter Befehl: "' + part[0] + '"!') + self.writeToServer('Unbekannter Befehl: "' + part.group(2) + '"!') if x: if type(x) == tuple and x[1] != "": self.writeToServer(x[1]) @@ -297,14 +331,12 @@ class PyCRCtrl(object): except (UnicodeDecodeError, UnicodeEncodeError): pass - if self.irc: + if self.irc and self.ingamechat == "aktiviert": if output.find("<" + self.irc.nick + ">") == -1: - if bool(re.match(r"^<.*>", output) and output.find("[IRC]") == -1) and \ - bool(output.find(self.config.get("prefix")) == -1): + if re.match(r"^<.*>", output) and output.find("[IRC]") == -1 and output.find(self.config.get("prefix")) == -1: self.irc.reply("[Clonk]{}".format(output), to=self.config.get("channels")["ingame"]) - elif bool(re.match(self.decodeRegExp(self.config.get("RegExps")["joinExp"]), output)) or \ - bool(re.match(self.decodeRegExp(self.config.get("RegExps")["leaveExp"]), output)): + elif re.match(self.decodeRegExp(self.config.get("RegExps")["joinExp"]), output) or re.match(self.decodeRegExp(self.config.get("RegExps")["leaveExp"]), output): self.irc.reply(output, to=self.config.get("channels")["ingame"]) @@ -331,7 +363,7 @@ class PyCRCtrl(object): return (CmdResult.Success, "") def doPrivmsg(self, msg): - if not self.irc: + if not (self.irc and self.ingamechat == "aktiviert"): return for channel in msg.args[0].split(","): if channel == self.config.get("channels")["ingame"] and msg.nick != self.irc.nick: @@ -369,11 +401,39 @@ class PyCRCtrl(object): self.topic = text return bool(self.irc.sendMsg(ircmsgs.topic(self.config.get("channels")["ingame"], text))) - def start(self, time=None): + def admin(self, prm=None, user=""): + """Setzt den Rundenadmin.""" + try: + if not prm: + raise IndexError + prm = " ".join(prm) + + if (self.capabilities[prm], self.capabilities[user]) > (Capability.Admin, Capability.Admin): + return (CmdResult.RuntimeError, "Du hast bereits mehr Rechte als ein Rundenadmin!") + + + except KeyError: + pass + + except IndexError: + return (CmdResult.SyntaxFail, "Nicht genügend Argumente!") + + for u, c in self.capabilities.items(): + if c == Capability.Admin: + return (CmdResult.RuntimeError, "{} ist bereits Rundenadmin!".format(u)) + + + self.capabilities[prm] = self.capabilities[user] = Capability.Admin + return (CmdResult.Success, "{} (Spielername: {}) wurde als Rundenadmin eingetragen!".format(user, prm)) + + + def start(self, time=None, user=""): + """Startet das Spiel.""" + if not self.checkCapability(Capability.Admin, user): return (CmdResult.RightsFail, "Du hast nicht die nötige Berechtigung.".encode("utf-8")) self.stopped = False if time: try: - time = int(time.split(" ")[0]) + time = int(time[0]) except: time = 5 self.writeToServer("/start {}".format(time)) @@ -383,7 +443,9 @@ class PyCRCtrl(object): return (CmdResult.Success, "") - def stop(self, prm=None): + def stop(self, prm=None, user=""): + """Stoppt den Countdown.""" + if not self.checkCapability(Capability.Admin, user): return (CmdResult.RightsFail, "Du hast nicht die nötige Berechtigung.".encode("utf-8")) def stopping(self): while self.clonk and self.stopped: self.writeToServer("/start 60000") @@ -398,15 +460,17 @@ class PyCRCtrl(object): return (CmdResult.Success, "") - def help(self, prm=None): - self.writeToServer("Verfügbare Befehle:") + def help(self, prm=None, user=""): + """Gibt die Hilfe aus.""" + self.writeToServer("Verfügbare Befehle:".encode("utf-8")) for text, function in self.commands.items(): - self.writeToServer(text) + self.writeToServer("{} -- {}".format(text, function.__doc__)) return (CmdResult.Success, "") - def displayQueue(self, prm=None): + def displayQueue(self, prm=None, user=""): + """Gibt die Warteschlange aus.""" self.writeToServer(b"Warteschlange:") for i,scen in enumerate(self.queue.queue): @@ -415,17 +479,26 @@ class PyCRCtrl(object): return (CmdResult.Success, "") - def list(self, prm=None): + def list(self, prm=None, user=""): + """Zeigt die Szenarioliste an.""" self.writeToServer(b"List:\n-------------") for scen in self.scenlist: self.writeToServer(scen) return (CmdResult.Success, "") - def ircCommands(self, prm=None): + def ircCommands(self, prm=None, user=""): + """Enthält Befehle zur Steuerung der IRC-Funktionen.""" + if not self.checkCapability(Capability.Admin, user): return (CmdResult.RightsFail, "Du hast nicht die nötige Berechtigung.".encode("utf-8")) if not prm: return (CmdResult.SyntaxFail, "") + if prm[0] == "ingamechat": + if prm[1] == "off": + self.ingamechat = "deaktiviert" + elif prm[1] == "on": + self.ingamechat = "aktiviert" + return (CmdResult.Success, "") def IsRunning(self) -> bool: @@ -456,17 +529,17 @@ class PyCRCtrl(object): self.scenlist().append(name) Pickler(open(os.path.join(self.path, "scenlist"), "wb")).dump(self.scenlist()) return self + + def checkCapability(self, capability, user=""): + if not user: + return False + try: + return (True if self.capabilities[user] >= capability else False) + + except KeyError: + return False - -class PyOCCtrl(PyCRCtrl): - - - - engine = "openclonk-server" - codec = QTextCodec.codecForName("UTF-8") - commandline = "--fullscreen --lobby=300 --faircrew --record --config=config.txt" - # # # -- cgit v1.2.3-54-g00ecf