From 1ec0e1f7e608bf71e82c08660f807e978184eed1 Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Mon, 12 Aug 2019 21:03:47 +0100 Subject: [PATCH] Remove provisioning restrictions, move all user tracking code to monitoring module, fix proper network name not being passed to the relay --- commands/provision.py | 36 +++++++++++++-------------- core/bot.py | 57 ++++++++++++++++--------------------------- core/relay.py | 3 +-- modules/monitor.py | 48 ++++++++++++++++++++++++++---------- modules/provision.py | 30 +++++++++++------------ 5 files changed, 90 insertions(+), 84 deletions(-) diff --git a/commands/provision.py b/commands/provision.py index 3453171..7803b6f 100644 --- a/commands/provision.py +++ b/commands/provision.py @@ -19,22 +19,22 @@ class Provision: failure("No such network: %s" % spl[3]) return - if "users" in main.relay[spl[1]]: - if not spl[2] in main.relay[spl[1]]["users"]: - failure("Relay %s not provisioned for alias %s" % (spl[1], spl[2])) - return - else: - failure("Relay %s not provisioned for alias %s" % (spl[1], spl[2])) - return + #if "users" in main.relay[spl[1]]: + # if not spl[2] in main.relay[spl[1]]["users"]: + # failure("Relay %s not provisioned for alias %s" % (spl[1], spl[2])) + # return + #else: + # failure("Relay %s not provisioned for alias %s" % (spl[1], spl[2])) + # return rtrn = provision.provisionRelayForNetwork(spl[1], spl[2], spl[3]) - if rtrn == "PROVISIONED": - failure("Relay %s already provisioned for alias %s on network %s" % (spl[1], spl[2], spl[3])) - return - elif rtrn == "DUPLICATE": - failure("Instance with relay %s and alias %s already exists for network %s" % (spl[1], spl[2], spl[3])) - return - elif rtrn: + #if rtrn == "PROVISIONED": + # failure("Relay %s already provisioned for alias %s on network %s" % (spl[1], spl[2], spl[3])) + # return + #elif rtrn == "DUPLICATE": + # failure("Instance with relay %s and alias %s already exists for network %s" % (spl[1], spl[2], spl[3])) + # return + if rtrn: success("Started provisioning network %s on relay %s for alias %s" % (spl[3], spl[1], spl[2])) info("Instance name is %s" % rtrn) return @@ -43,10 +43,10 @@ class Provision: return if length == 3: # provision for relay and alias only rtrn = provision.provisionRelayForAlias(spl[1], spl[2]) - if rtrn == "PROVISIONED": - failure("Relay %s already provisioned for alias %s" % (spl[1], spl[2])) - return - elif rtrn: + #if rtrn == "PROVISIONED": + # failure("Relay %s already provisioned for alias %s" % (spl[1], spl[2])) + # return + if rtrn: success("Started provisioning relay %s for alias %s" % (spl[1], spl[2])) return else: diff --git a/core/bot.py b/core/bot.py index ee5d8b7..ae4a0fe 100644 --- a/core/bot.py +++ b/core/bot.py @@ -139,7 +139,8 @@ class IRCBot(IRCClient): del cast[i] if "muser" in cast.keys(): cast["nick"], cast["ident"], cast["host"] = self.parsen(cast["muser"]) - del cast["muser"] + #if not cast["type"] in ["nick", "kick", "quit", "part", "join"]: + # del cast["muser"] if set(["nick", "ident", "host", "message"]).issubset(set(cast)): if "message" in cast.keys(): if cast["ident"] == "znc" and cast["host"] == "znc.in": @@ -181,12 +182,10 @@ class IRCBot(IRCClient): castDup["name"] = self.name self.event(**castDup) - if "name" not in cast.keys(): + if not "name" in cast.keys(): cast["name"] = self.net - if cast["type"] in ["msg", "notice", "action"]: - userinfo.editUser(self.net, cast["nick"]+"!"+cast["ident"]+"@"+cast["host"]) count.event(self.net, cast["type"]) - monitor.event(self.net, self.name, cast) + monitor.event(cast) def privmsg(self, user, channel, msg): self.event(type="msg", muser=user, target=channel, message=msg) @@ -214,10 +213,8 @@ class IRCBot(IRCClient): return newnick def nickChanged(self, olduser, newnick): - oldnick, ident, host = self.parsen(olduser) - userinfo.renameUser(self.net, oldnick, olduser, newnick, newnick+"!"+ident+"@"+host) self.nickname = newnick - self.event(type="self", mtype="nick", nick=oldnick, ident=ident, host=host, user=newnick) + self.event(type="self", mtype="nick", muser=olduser, user=newnick) def irc_ERR_NICKNAMEINUSE(self, prefix, params): self._attemptedNick = self.alterCollidedNick(self._attemptedNick) @@ -397,59 +394,47 @@ class IRCBot(IRCClient): lc = self._getWho[channel] lc.stop() del self._getWho[channel] - userinfo.delChannel(self.net, channel) - log("Can no longer cover %s, removing records" % channel) - - def left(self, user, channel, message): + userinfo.delChannel(self.net, channel) # < we do not need to deduplicate this + log("Can no longer cover %s, removing records" % channel) # as it will only be matched once -- + # other bots have different nicknames so + def left(self, user, channel, message): # even if they saw it, they wouldn't react self.event(type="part", muser=user, target=channel, message=message) self.botLeft(channel) def userJoined(self, user, channel): - nick, ident, host = self.parsen(user) - userinfo.addUser(self.net, channel, nick, user) - self.event(type="join", nick=nick, ident=ident, host=host, target=channel) + self.event(type="join", muser=user, target=channel) def userLeft(self, user, channel, message): - nick, ident, host = self.parsen(user) - userinfo.delUser(self.net, channel, nick, user) - self.event(type="part", nick=nick, ident=ident, host=host, target=channel, message=message) + self.event(type="part", muser=user, target=channel, message=message) def userQuit(self, user, quitMessage): - nick, ident, host = self.parsen(user) - self.chanlessEvent(type="quit", nick=nick, ident=ident, host=host, message=quitMessage) - userinfo.delUserByNetwork(self.net, nick, user) + self.chanlessEvent(type="quit", muser=user, message=quitMessage) def userKicked(self, kickee, channel, kicker, message): - nick, ident, host = self.parsen(kicker) - userinfo.editUser(self.net, kicker) - userinfo.delUserByNick(self.net, channel, kickee) - if kickee.lower == self.nickname.lower: + if kickee.lower() == self.nickname.lower(): self.botLeft(channel) - self.event(type="kick", nick=nick, ident=ident, host=host, target=channel, message=message, user=kickee) + self.event(type="kick", muser=kicker, target=channel, message=message, user=kickee) def chanlessEvent(self, **cast): chans = userinfo.getChansSingle(self.net, cast["nick"]) if chans == None: self.event(**cast) return + # getChansSingle returns all channels of the user, we only want to use + # ones we have common with them + realChans = set(chans).intersection(set(self.channels)) for i in chans: cast["target"] = i self.event(**cast) def userRenamed(self, oldname, newname): - nick, ident, host = self.parsen(oldname) - self.chanlessEvent(type="nick", nick=nick, ident=ident, host=host, user=newname) - userinfo.renameUser(self.net, nick, oldname, newname, newname+"!"+ident+"@"+host) + self.chanlessEvent(type="nick", muser=oldname, user=newname) def topicUpdated(self, user, channel, newTopic): - nick, ident, host = self.parsen(user) - userinfo.editUser(self.net, user) - - self.event(type="topic", nick=nick, ident=ident, host=host, target=channel, message= newTopic) + self.event(type="topic", muser=user, target=channel, message= newTopic) def modeChanged(self, user, channel, toset, modes, args): nick, ident, host = self.parsen(user) - userinfo.editUser(self.net, user) argList = list(args) modeList = [i for i in modes] for a, m in zip(argList, modeList): @@ -490,7 +475,7 @@ class IRCBotFactory(ReconnectingClientFactory): log("%s: connection lost: %s" % (self.name, error)) if not self.relay: sendAll("%s: connection lost: %s" % (self.name, error)) - sendRelayNotification(self.name, {"type": "conn", "status": "lost", "message": error}) + sendRelayNotification({"type": "conn", "name": self.name, "status": "lost", "message": error}) self.retry(connector) #ReconnectingClientFactory.clientConnectionLost(self, connector, reason) @@ -502,7 +487,7 @@ class IRCBotFactory(ReconnectingClientFactory): log("%s: connection failed: %s" % (self.name, error)) if not self.relay: sendAll("%s: connection failed: %s" % (self.name, error)) - sendRelayNotification(self.name, {"type": "conn", "status": "failed", "message": error}) + sendRelayNotification({"type": "conn", "name": self.name, "status": "failed", "message": error}) self.retry(connector) #ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) diff --git a/core/relay.py b/core/relay.py index 58ba3d5..4067ee0 100644 --- a/core/relay.py +++ b/core/relay.py @@ -132,11 +132,10 @@ class RelayFactory(Factory): else: return -def sendRelayNotification(name, cast): +def sendRelayNotification(cast): for i in main.relayConnections.keys(): if main.relayConnections[i].authed: if cast["type"] in main.relayConnections[i].subscriptions: newCast = deepcopy(cast) - newCast["name"] = name newCast["time"] = str(datetime.now().isoformat()) main.relayConnections[i].send(dumps(newCast)) diff --git a/modules/monitor.py b/modules/monitor.py index 08fae94..16b0bb4 100644 --- a/modules/monitor.py +++ b/modules/monitor.py @@ -3,6 +3,7 @@ from json import dumps import main from core.relay import sendRelayNotification +from modules import userinfo def testNetTarget(name, target): called = False @@ -50,28 +51,49 @@ def magicFunction(A, B): else: return all(A[k] in B[k] for k in set(A) & set(B)) and set(B) <= set(A) -def event(name, numberedName, cast, event=None): - if "target" in cast.keys(): - target = cast["target"] - else: - target = None +def event(c): # yes I'm using a short variable because otherwise it goes off the screen + if not "target" in c.keys(): + c["target"] = None - sendRelayNotification(name, cast) - monitorGroups = testNetTarget(name, target) + # metadata scraping + # need to check if this was received from a relay + # in which case, do not do this + if c["type"] in ["msg", "notice", "action", "topic", "mode"]: + userinfo.editUser(c["name"], c["muser"]) + elif c["type"] == "nick": + userinfo.renameUser(c["name"], c["nick"], c["muser"], c["user"], c["user"]+"!"+c["ident"]+"@"+c["host"]) + elif c["type"] == "kick": + userinfo.editUser(c["name"], c["muser"]) + userinfo.delUserByNick(c["name"], c["target"], c["user"]) + elif c["type"] == "quit": + userinfo.delUserByNetwork(c["name"], c["nick"], c["muser"]) + elif c["type"] == "join": + userinfo.addUser(c["name"], c["target"], c["nick"], c["user"]) + elif c["type"] == "part": + userinfo.delUser(c["name"], c["target"], c["nick"], c["user"]) + + if "mtype" in c.keys(): + if c["mtype"] == "nick": + userinfo.renameUser(c["name"], c["nick"], c["muser"], c["user"], c["user"]+"!"+c["ident"]+"@"+c["host"]) + + if "muser" in c.keys(): + del c["muser"] + sendRelayNotification(c) + monitorGroups = testNetTarget(c["name"], c["target"]) if monitorGroups == False: return for monitorGroup in monitorGroups: - matcher = magicFunction(deepcopy(cast), deepcopy(main.monitor[monitorGroup])) + matcher = magicFunction(deepcopy(c), deepcopy(main.monitor[monitorGroup])) if matcher == True: - cast["monitor"] = True + c["monitor"] = True if "send" in main.monitor[monitorGroup].keys(): for i in main.monitor[monitorGroup]["send"].keys(): if isinstance(main.monitor[monitorGroup]["send"][i], bool): - sendRelayNotification(name, {"type": "err", "name": name, "target": target, "message": cast, "reason": "errdeliv"}) + sendRelayNotification({"type": "err", "name": name, "target": target, "message": c, "reason": "errdeliv"}) continue if not i in main.pool.keys(): - sendRelayNotification(name, {"type": "err", "name": name, "target": target, "message": cast, "reason": "noname"}) + sendRelayNotification({"type": "err", "name": name, "target": target, "message": c, "reason": "noname"}) if not i in main.IRCPool.keys(): - sendRelayNotification(name, {"type": "err", "name": name, "target": target, "message": cast, "reason": "noinstance"}) + sendRelayNotification({"type": "err", "name": name, "target": target, "message": c, "reason": "noinstance"}) for x in main.monitor[monitorGroup]["send"][i]: - main.IRCPool[i].msg(x, "monitor [%s] (%s) %s" % (monitorGroup, name, cast)) + main.IRCPool[i].msg(x, "monitor [%s] (%s) %s" % (monitorGroup, c["name"], c)) diff --git a/modules/provision.py b/modules/provision.py index 0eb7464..f964cf3 100644 --- a/modules/provision.py +++ b/modules/provision.py @@ -48,40 +48,40 @@ def provisionNetworkData(relay, alias, network, host, port, security, auth, pass return def provisionRelayForAlias(relay, alias): - if "users" in main.relay[relay].keys(): - if alias in main.relay[relay]["users"]: - return "PROVISIONED" - else: - main.relay[relay]["users"] = [] - main.relay[relay]["users"].append(alias) + #if "users" in main.relay[relay].keys(): + # if alias in main.relay[relay]["users"]: + # return "PROVISIONED" + #else: + # main.relay[relay]["users"] = [] + #main.relay[relay]["users"].append(alias) provisionUserData(relay, alias, main.alias[alias]["nick"], main.alias[alias]["altnick"], main.alias[alias]["ident"], main.alias[alias]["realname"], main.relay[relay]["password"]) - main.saveConf("relay") + #main.saveConf("relay") return True def provisionRelayForNetwork(relay, alias, network): - if set(["users", "networks"]).issubset(main.relay[relay].keys()): - if network in main.relay[relay]["networks"] and alias in main.relay[relay]["users"]: - return "PROVISIONED" - else: - main.relay[relay]["networks"] = [] - main.relay[relay]["networks"].append(network) + #if set(["users", "networks"]).issubset(main.relay[relay].keys()): + # if network in main.relay[relay]["networks"] and alias in main.relay[relay]["users"]: + # return "PROVISIONED" + #else: + # main.relay[relay]["networks"] = [] + #main.relay[relay]["networks"].append(network) provisionNetworkData(relay, alias, network, main.network[network]["host"], main.network[network]["port"], main.network[network]["security"], main.network[network]["auth"], main.alias[alias]["password"]) - main.saveConf("relay") + #main.saveConf("relay") storedNetwork = False num = 1 while not storedNetwork: i = str(num) if num == 1000: - error("Too many iterations in while trying to choose name for r: %s a: %s n: %s" % (relay, alias, network)) + error("Iteration limit exceeded while trying to choose name for r: %s a: %s n: %s" % (relay, alias, network)) return False if network+i in main.pool.keys():