Fix various bugs in the event system

Squash many bugs in the event notification system and simplify the
code.
This commit is contained in:
Mark Veidemanis 2020-06-02 21:34:15 +01:00
parent 290e0b5f87
commit 1640955e5c
4 changed files with 71 additions and 49 deletions

View File

@ -9,6 +9,7 @@ import sys
from string import digits
from random import randint
from copy import deepcopy
from datetime import datetime
from modules import userinfo
from modules import counters
@ -200,73 +201,95 @@ class IRCBot(IRCClient):
del main.TempChan[self.net]
def event(self, **cast):
if not "time" in cast.keys():
cast["time"] = str(datetime.now().isoformat())
# remove odd stuff
for i in list(cast.keys()): # Make a copy of the .keys() as Python 3 cannot handle iterating over
if cast[i] == "": # a dictionary that changes length with each iteration
del cast[i]
# remove server stuff
if "muser" in cast.keys():
if cast["muser"] == self.servername:
return
if "channel" in cast.keys():
if cast["channel"] == "*":
return
##
# expand out the hostmask
if not {"nick", "ident", "host"}.issubset(set(cast.keys())):
cast["nick"], cast["ident"], cast["host"] = parsen(cast["muser"])
# handle ZNC stuff
if {"nick", "ident", "host", "msg"}.issubset(set(cast)):
if "msg" in cast.keys():
if cast["ident"] == "znc" and cast["host"] == "znc.in":
cast["type"] = "znc"
cast["num"] = self.num
del cast["nick"]
del cast["ident"]
del cast["host"]
del cast["channel"]
if "Disconnected from IRC" in cast["msg"]:
log("ZNC disconnected on %s - %i" % (self.net, self.num))
self.isconnected = False
if "Connected!" in cast["msg"]:
log("ZNC connected on %s - %i" % (self.net, self.num))
self.isconnected = True
if not cast["type"] in ["query", "self", "highlight", "znc", "who"]:
if "channel" in cast.keys() and not cast["type"] == "mode": # don't handle modes here
if cast["channel"].lower() == self.nickname.lower(): # as they are channel == nickname
#castDup = deepcopy(cast) # however modes are not queries!
cast["mtype"] = cast["type"]
cast["type"] = "query"
cast["num"] = self.num
#self.event(**castDup)
# Don't call self.event for this one because queries are not events on a
# channel, but we still want to see them
if cast["ident"] == "znc" and cast["host"] == "znc.in":
cast["type"] = "znc"
cast["num"] = self.num
del cast["nick"]
del cast["ident"]
del cast["host"]
del cast["channel"]
if "Disconnected from IRC" in cast["msg"]:
log("ZNC disconnected on %s - %i" % (self.net, self.num))
self.isconnected = False
if "Connected!" in cast["msg"]:
log("ZNC connected on %s - %i" % (self.net, self.num))
self.isconnected = True
#
# don't reprocess the same message twice
# if the type is in that list, it's already been here, don't run it again
if not cast["type"] in {"query", "self", "highlight", "znc", "who"}:
cast["num"] = self.num
if "channel" in cast.keys():
if cast["type"] == "mode":
if self.nickname.lower() == cast["channel"].lower():
castDup = deepcopy(cast)
castDup["mtype"] = cast["type"]
castDup["type"] = "self"
self.event(**castDup)
if cast["modearg"]:
if self.nickname.lower() == cast["modearg"].lower():
castDup = deepcopy(cast)
castDup["mtype"] = cast["type"]
castDup["type"] = "self"
self.event(**castDup)
else:
if cast["channel"].lower() == self.nickname.lower():
cast["mtype"] = cast["type"]
cast["type"] = "query"
#self.event(**castDup)
# Don't call self.event for this one because queries are not events on a
# channel, but we still want to see them
# we have been kicked
if "user" in cast.keys():
if cast["user"].lower() == self.nickname.lower():
cast["num"] = self.num
castDup = deepcopy(cast)
castDup["mtype"] = cast["type"]
castDup["type"] = "self"
cast["num"] = self.num
self.event(**castDup)
# we sent a message/left/joined/kick someone/quit
if "nick" in cast.keys():
if cast["nick"].lower() == self.nickname.lower():
cast["num"] = self.num
castDup = deepcopy(cast)
castDup["mtype"] = cast["type"]
castDup["type"] = "self"
cast["num"] = self.num
if not cast["channel"].lower() == self.nickname.lower(): # modes has been set on us directly
self.event(**castDup) # don't tell anyone else
if "msg" in cast.keys() and not cast["type"] == "query": # Don't highlight queries
# we have been mentioned in a msg/notice/action/part/quit/topic message
if "msg" in cast.keys(): # Don't highlight queries
if not cast["msg"] == None:
if self.nickname.lower() in cast["msg"].lower():
cast["num"] = self.num
castDup = deepcopy(cast)
castDup["mtype"] = cast["type"]
castDup["type"] = "highlight"
cast["num"] = self.num
self.event(**castDup)
if not "net" in cast.keys():
cast["net"] = self.net
if not "num" in cast.keys():
print("no num", cast)
cast["num"] = self.num
counters.event(self.net, cast["type"])
monitor.event(self.net, cast)
@ -596,22 +619,22 @@ class IRCBot(IRCClient):
#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, channel=channel, message=message)
self.event(type="part", muser=user, channel=channel, msg=message)
self.botLeft(channel)
def userJoined(self, user, channel):
self.event(type="join", muser=user, channel=channel)
def userLeft(self, user, channel, message):
self.event(type="part", muser=user, channel=channel, message=message)
self.event(type="part", muser=user, channel=channel, msg=message)
def userQuit(self, user, quitMessage):
self.chanlessEvent({"type": "quit", "muser": user, "message": quitMessage})
self.chanlessEvent({"type": "quit", "muser": user, "msg": quitMessage})
def userKicked(self, kickee, channel, kicker, message):
if kickee.lower() == self.nickname.lower():
self.botLeft(channel)
self.event(type="kick", muser=kicker, channel=channel, message=message, user=kickee)
self.event(type="kick", muser=kicker, channel=channel, msg=message, user=kickee)
def chanlessEvent(self, cast):
cast["nick"], cast["ident"], cast["host"] = parsen(cast["muser"])
@ -635,13 +658,13 @@ class IRCBot(IRCClient):
self.chanlessEvent({"type": "nick", "muser": oldname, "user": newname})
def topicUpdated(self, user, channel, newTopic):
self.event(type="topic", muser=user, channel=channel, message= newTopic)
self.event(type="topic", muser=user, channel=channel, msg=newTopic)
def modeChanged(self, user, channel, toset, modes, args):
argList = list(args)
modeList = [i for i in modes]
for a, m in zip(argList, modeList):
self.event(type="mode", muser=user, channel=channel, modes=m, status=toset, modeargs=a)
self.event(type="mode", muser=user, channel=channel, mode=m, status=toset, modearg=a)
class IRCBotFactory(ReconnectingClientFactory):
def __init__(self, net, num=None, relayCommands=None, user=None, stage2=None):

View File

@ -1,7 +1,6 @@
from twisted.internet.protocol import Protocol, Factory, ClientFactory
from json import dumps, loads
from copy import deepcopy
from datetime import datetime
import main
from utils.logging.log import *
@ -136,6 +135,4 @@ 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["time"] = str(datetime.now().isoformat())
main.relayConnections[i].send(dumps(newCast))
main.relayConnections[i].send(dumps(cast))

View File

@ -1,6 +1,5 @@
from copy import deepcopy
from json import dumps
from datetime import datetime
import main
from core.relay import sendRelayNotification
@ -9,8 +8,8 @@ from modules import regproc
from utils.dedup import dedup
order = ["type", "net", "num", "channel", "msg", "nick",
"ident", "host", "mtype", "user", "modes", "modeargs"
"realname", "server", "status"]
"ident", "host", "mtype", "user", "mode", "modearg",
"realname", "server", "status", "time"]
def testNetTarget(name, target):
called = False
@ -88,6 +87,7 @@ def event(numName, c): # yes I'm using a short variable because otherwise it goe
if "muser" in c.keys():
del c["muser"]
sendRelayNotification({k: c[k] for k in order if k in c}) # Sort dict keys according to order
# only monitors below

View File

@ -1,11 +1,13 @@
from datetime import datetime
from csiphash import siphash24
from copy import deepcopy
from json import dumps
import main
from utils.logging.debug import debug
def dedup(numName, c):
# deduplication
def dedup(numName, b):
c = deepcopy(b)
del c["time"]
c["approxtime"] = str(datetime.utcnow().timestamp())[:main.config["Tweaks"]["DedupPrecision"]]
castHash = siphash24(main.hashKey, dumps(c, sort_keys=True).encode("utf-8"))
del c["approxtime"]