From 633a0235807d87cf921ce6d3b53127ad56c2ec63 Mon Sep 17 00:00:00 2001 From: Alexei Sorokin Date: Tue, 23 Aug 2016 20:23:53 +0300 Subject: [PATCH] Refactoring of command handling --- hptoad.py | 189 +++++++++++++++++++++++++++--------------------------- 1 file changed, 96 insertions(+), 93 deletions(-) diff --git a/hptoad.py b/hptoad.py index c2301c4..a3b2cdf 100755 --- a/hptoad.py +++ b/hptoad.py @@ -34,23 +34,23 @@ class Zhobe: self.jid = opts["jid"] self.connect = opts["connect"] self.muc = opts["muc"] - self.pure_nick = opts["nick"] - self.nick = self.pure_nick + self.pure_bot_nick = opts["nick"] + self.bot_nick = self.pure_bot_nick def register_handlers(self): self.client.add_event_handler("session_start", self.on_session_start) self.client.add_event_handler("message", self.on_message, threaded=True) self.client.add_event_handler("muc::%s::presence" % self.muc, - self.on_presence) + self.on_muc_presence) def join_muc(self): muc_plugin = self.client.plugin["xep_0045"] if self.muc in muc_plugin.getJoinedRooms(): - muc_plugin.leaveMUC(self.muc, self.nick, + muc_plugin.leaveMUC(self.muc, self.bot_nick, msg="Replaced by new connection") - muc_plugin.joinMUC(self.muc, self.nick, wait=True) + muc_plugin.joinMUC(self.muc, self.bot_nick, wait=True) @classmethod def log_exception(cls, ex): @@ -82,7 +82,7 @@ class Zhobe: # letter(ASCII or cyrillic), number, underscore only. _cmd_validator_regexp = re.compile("^!(\\w|\\p{Cyrillic})*$") - def parse_command(self, body, dir_path, nick, is_admin=False): + def prep_extern_cmd(self, body, nick, dir_path, is_admin=False): cmd = body.split(" ", 1) cmd[0] = cmd[0].strip() @@ -106,46 +106,99 @@ class Zhobe: return proc_args, None - def exec_command(self, body, dir_path, from_id, nick, is_admin=False): - cmd, err = self.parse_command(body, dir_path, nick, - is_admin=is_admin) - if err is not None: - logging.error("Command: %s" % err) - self.client.send_message(mto=self.muc, - mbody="%s: WAT" % nick, - mtype="groupchat") - if is_admin: - self.client.send_message(mto=from_id, - mbody=err, - mtype="chat") - return + def extern_cmd(self, body, nick, from_id, dir_path, is_admin=False): + reply = "" + err = None + + cmd, prep_err = self.prep_extern_cmd(body, nick, dir_path, + is_admin=is_admin) + + if prep_err: + reply = "%s: WAT" % nick + err = "Command: %s" % prep_err + return reply, err try: proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) - cmd_out, cmd_outerr = proc.communicate() - except subprocess.CalledProcessError as err: - logging.error("Execute: %s" % str(err)) - self.client.send_message(mto=self.muc, - mbody="%s: WAT" % nick, - mtype="groupchat") - if is_admin: - self.client.send_message(mto=from_id, - mbody=str(err), - mtype="chat") - return + cmd_reply, cmd_err = proc.communicate() + except subprocess.CalledProcessError as e: + reply = "%s: WAT" % nick + err = "Execute: %s" % str(e) + return reply, err - if cmd_outerr and len(cmd_outerr) > 0: - logging.error("Process: %s" % cmd_outerr.strip()) + if cmd_err and len(cmd_err.strip()) > 0: + err = "Process: %s" % cmd_err.strip() + if cmd_reply and len(cmd_reply.strip()) > 0: + reply = cmd_reply.strip() + return reply, err + + def handle_cmd(self, body, nick, from_id, is_admin=False): + muc_plugin = self.client.plugin["xep_0045"] + + reply = "" + err = None + + if body == "!megakick": # Incomplete megakick. + reply = "%s: WAT" % nick + + elif body.startswith("!megakick "): # Megakick. + victim = body.split("!megakick ", 1)[1] + + is_bot_admin = self.is_muc_admin(self.muc, self.bot_nick) + is_victim_admin = self.is_muc_admin(self.muc, victim) + + if is_admin and victim != self.bot_nick: + if is_bot_admin and not is_victim_admin and \ + victim in muc_plugin.rooms[self.muc]: + muc_plugin.setRole(self.muc, victim, "none") + else: + reply = "%s: Can't megakick %s." % (nick, victim) + else: + reply = "%s: GTFO" % nick + + elif body.startswith("!"): # Any external command. + reply, err = self.extern_cmd(body, nick, from_id, "./plugins", + is_admin=is_admin) + + return reply, err + + def handle_self_message(self, body, nick, from_id): + if body.startswith("!"): + msg, err = self.handle_cmd(body, nick, from_id, is_admin=True) + else: + msg = body.strip() + + if msg and len(msg) > 0: + self.client.send_message(mto=self.muc, mbody=msg, + mtype="groupchat") + + def handle_muc_message(self, body, nick, from_id): + is_admin = self.is_muc_admin(self.muc, nick) + + reply = "" + err = None + + # Has to be redone with the current bot nick. + call_regexp = re.compile("^%s[:,]" % self.bot_nick) + + if body.startswith("!"): # Any external command. + reply, err = self.handle_cmd(body, nick, from_id, + is_admin=is_admin) + + elif call_regexp.match(body): # Chat. + cmd_body = call_regexp.sub("!answer", body) + reply, err = self.extern_cmd(cmd_body, nick, from_id, "./chat", + is_admin=is_admin) + + if err: + logging.error(err) if is_admin: - self.client.send_message(mto=from_id, - mbody=cmd_outerr.strip(), - mtype="chat") - if cmd_out and len(cmd_out) > 0: - self.client.send_message(mto=self.muc, - mbody=cmd_out.strip(), + self.client.send_message(mto=from_id, mbody=err, mtype="chat") + if reply: + self.client.send_message(mto=self.muc, mbody=reply, mtype="groupchat") def on_session_start(self, event): @@ -154,56 +207,6 @@ class Zhobe: ppriority=12) self.join_muc() - def handle_self_message(self, body, nick, from_id): - if not body.startswith("!"): - self.client.send_message(mto=self.muc, mbody=body, - mtype="groupchat") - return - - self.exec_command(body, "./plugins", from_id, nick, is_admin=True) - - def handle_muc_message(self, body, nick, from_id): - muc_plugin = self.client.plugin["xep_0045"] - - is_admin = self.is_muc_admin(self.muc, nick) - - # Has to be redone with the current bot nick. - call_regexp = re.compile("^%s[:,]" % self.nick) - - if body == "!megakick": - self.client.send_message(mto=self.muc, - mbody="%s: WAT" % nick, - mtype="groupchat") - - elif body.startswith("!megakick "): - victim = body.split("!megakick ", 1)[1] - - is_bot_admin = self.is_muc_admin(self.muc, self.nick) - is_victim_admin = self.is_muc_admin(self.muc, victim) - - if is_admin and victim != self.nick: - if is_bot_admin and not is_victim_admin and \ - victim in muc_plugin.rooms[self.muc]: - muc_plugin.setRole(self.muc, victim, "none") - else: - self.client.send_message(mto=self.muc, - mbody="%s: Can't megakick %s." % - (nick, victim), - mtype="groupchat") - else: - self.client.send_message(mto=self.muc, - mbody="%s: GTFO" % nick, - mtype="groupchat") - - elif body.startswith("!"): # Any external command. - self.exec_command(body, "./plugins", from_id, nick, - is_admin=is_admin) - - elif call_regexp.match(body): # Chat. - cmd_body = call_regexp.sub("!answer", body) - self.exec_command(cmd_body, "./chat", from_id, nick, - is_admin=is_admin) - def on_message(self, event): try: if not event["type"] in ("chat", "normal", "groupchat"): @@ -225,7 +228,7 @@ class Zhobe: except Exception as e: self.log_exception(e) - def on_presence(self, event): + def on_muc_presence(self, event): muc_plugin = self.client.plugin["xep_0045"] try: typ = event["muc"]["type"] @@ -239,12 +242,12 @@ class Zhobe: if typ == "error": if event["error"]["code"] == "409": - self.nick = self.nick + "_" + self.bot_nick = self.bot_nick + "_" self.join_muc() elif typ == "unavailable": - if nick == self.nick: - self.nick = self.pure_nick + if nick == self.bot_nick: + self.bot_nick = self.pure_bot_nick time.sleep(0.5) self.join_muc() except Exception as e: @@ -252,7 +255,7 @@ class Zhobe: def run(self): # Reset the nick. - self.nick = self.pure_nick + self.bot_nick = self.pure_bot_nick if self.connect: connect = self.connect.split(":", 1)