Remove keyword system, implement ZNC notifications to relay, remove exact from cast fields and fix security bug in relay

This commit is contained in:
Mark Veidemanis 2019-08-05 22:51:16 +01:00
parent 0637f762ea
commit 68c6aa969d
8 changed files with 97 additions and 348 deletions

View File

@ -1,155 +0,0 @@
import main
import modules.keyword as keyword
class Key:
def __init__(self, *args):
self.key(*args)
def key(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length):
if authed:
if data.startswith("key add"):
if not data in ["key add ", "key add"] and data[3] == " ":
keywordsToAdd = data[8:]
keywords = keywordsToAdd.split(",")
for i in keywords:
rtrn = keyword.addKeyword(i)
if rtrn == "EXISTS":
failure("Keyword already exists: %s" % i)
elif rtrn == "ISIN":
failure("Keyword already matched: %s" % i)
elif rtrn == True:
success("Keyword added: %s" % i)
return
else:
incUsage("key")
return
elif data.startswith("key del"):
if not data in ["key del ", "key del"] and data[3] == " ":
keywordsToDel = data[8:]
keywords = keywordsToDel.split(",")
for i in keywords:
rtrn = keyword.delKeyword(i)
if rtrn == "NOKEY":
failure("Keyword does not exist: %s" % i)
elif rtrn == True:
success("Keyword deleted: %s" % i)
return
else:
incUsage("key")
return
if length == 4:
if spl[1] == "except":
if not spl[2] in main.keyconf["Keywords"]:
failure("No such keyword: %s" % spl[2])
return
if spl[2] in main.keyconf["KeywordsExcept"].keys():
if spl[3] in main.keyconf["KeywordsExcept"][spl[2]]:
failure("Exception exists: %s" % spl[3])
return
else:
if not spl[2] in spl[3]:
failure("Keyword %s not in exception %s. This won't work." % (spl[2], spl[3]))
return
main.keyconf["KeywordsExcept"][spl[2]] = []
main.keyconf["KeywordsExcept"][spl[2]].append(spl[3])
main.saveConf("keyconf")
success("Successfully added exception %s for keyword %s" % (spl[3], spl[2]))
return
elif spl[1] == "master":
if not spl[2] in main.pool.keys():
failure("Name does not exist: %s" % spl[2])
return
if spl[2] in main.IRCPool.keys():
if not spl[3] in main.IRCPool[spl[2]].channels:
info("Bot not on channel: %s" % spl[3])
main.config["Master"] = [spl[2], spl[3]]
main.saveConf("config")
success("Master set to %s on %s" % (spl[3], spl[2]))
return
elif spl[1] == "unexcept":
if not spl[2] in main.keyconf["KeywordsExcept"].keys():
failure("No such exception: %s" % spl[2])
return
if not spl[3] in main.keyconf["KeywordsExcept"][spl[2]]:
failure("Exception %s has no attribute %s" % (spl[2], spl[3]))
return
main.keyconf["KeywordsExcept"][spl[2]].remove(spl[3])
if main.keyconf["KeywordsExcept"][spl[2]] == []:
del main.keyconf["KeywordsExcept"][spl[2]]
main.saveConf("keyconf")
success("Successfully removed exception %s for keyword %s" % (spl[3], spl[2]))
return
else:
incUsage("key")
return
elif length == 3:
if spl[1] == "unexcept":
if not spl[2] in main.keyconf["KeywordsExcept"].keys():
failure("No such exception: %s" % spl[2])
return
del main.keyconf["KeywordsExcept"][spl[2]]
main.saveConf("keyconf")
success("Successfully removed exception list of %s" % spl[2])
return
elif spl[1] == "monitor":
if spl[2] == "on":
if not obj.addr in main.MonitorPool:
main.MonitorPool.append(obj.addr)
success("Keyword monitoring enabled")
if len(main.masterbuf) == 0:
return
rtrn = []
for i in range(len(main.masterbuf)):
rtrn.append(main.masterbuf.pop(0))
main.saveConf("masterbuf")
info("\n".join(rtrn))
return
else:
failure("Keyword monitoring is already enabled")
return
elif spl[2] == "off":
if obj.addr in main.MonitorPool:
main.MonitorPool.remove(obj.addr)
success("Keyword monitoring disabled")
return
else:
failure("Keyword monitoring is already disabled")
return
else:
incUsage("key")
return
else:
incUsage("key")
return
elif length == 2:
if spl[1] == "list":
info(",".join(main.keyconf["Keywords"]))
return
elif spl[1] == "listexcept":
exceptMap = []
for i in main.keyconf["KeywordsExcept"].keys():
exceptMap.append("Key: %s" % i)
exceptMap.append("%s: %s" % (i, ",".join(main.keyconf["KeywordsExcept"][i])))
exceptMap.append("\n")
info("\n".join(exceptMap))
return
elif spl[1] == "master":
info(" - ".join([str(i) for i in main.config["Master"]]))
return
elif spl[1] == "monitor":
if obj.addr in main.MonitorPool:
info("Keyword monitoring is enabled on this connection")
return
else:
info("Keyword monitoring is disabled on this connection")
return
else:
incUsage("key")
return
else:
incUsage("key")
return
else:
incUsage(None)

View File

@ -24,7 +24,6 @@ class Mon:
self.parser.add_argument("--type", nargs="*", metavar="type", dest="specType", help="Specify type of spec matching. Available types: join, part, quit, msg, topic, mode, nick, kick, notice, action, who")
self.parser.add_argument("--free", nargs="*", metavar="query", dest="free", help="Use freeform matching")
self.parser.add_argument("--exact", nargs="*", metavar="query", dest="exact", help="Use exact matching")
self.parser.add_argument("--nick", nargs="*", metavar="nickname", dest="nick", help="Use nickname matching")
self.parser.add_argument("--ident", nargs="*", metavar="ident", dest="ident", help="Use ident matching")
self.parser.add_argument("--host", nargs="*", metavar="host", dest="host", help="Use host matching")
@ -208,8 +207,6 @@ class Mon:
cast["status"] = obj.status
if not obj.free == None:
cast["free"] = obj.free
if not obj.exact == None:
cast["exact"] = obj.exact
if not obj.nick == None:
cast["nick"] = obj.nick
if not obj.ident == None:

View File

@ -1,6 +0,0 @@
{
"Keywords": [
"example"
],
"KeywordsExcept": {}
}

View File

@ -7,10 +7,11 @@ from twisted.internet import reactor
from string import digits
from random import randint
import modules.keyword as keyword
import modules.userinfo as userinfo
import modules.counters as count
import modules.monitor as monitor
from modules import userinfo
from modules import counters as count
from modules import monitor
from core.relay import sendRelayNotification
import main
from utils.logging.log import *
@ -73,7 +74,7 @@ class IRCRelay(IRCClient):
self.connected = True
log("signed on as a relay: %s" % self.relay)
if main.config["Notifications"]["Connection"]:
keyword.sendMaster("SIGNON: %s" % self.relay)
sendRelayNotification("Relay", {"type": "conn", "status": "connected"})
for i in self.relayCommands.keys():
for x in self.relayCommands[i]:
self.msg(main.config["Tweaks"]["ZNC"]["Prefix"]+i, x)
@ -134,27 +135,27 @@ class IRCBot(IRCClient):
def privmsg(self, user, channel, msg):
nick, ident, host = self.parsen(user)
# ZNC adds messages when no users are in the channel, messing up tracking
#userinfo.editUser(self.net, channel, nick, user)
count.event(self.net, "privmsg")
keyword.actKeyword(user, channel, msg, self.nickname, "MSG", self.name)
monitor.event(self.net, channel, {"type": "msg", "exact": user, "nick": nick, "ident": ident, "host": host, "message": msg})
count.event(self.net, "msg")
#event = None
#if self.nickname.lower() in msg.lower():
# event = "highlight"
monitor.event(self.net, {"type": "msg", "nick": nick, "ident": ident, "host": host, "target": channel, "message": msg})
def noticed(self, user, channel, msg):
nick, ident, host = self.parsen(user)
#userinfo.editUser(self.net, channel, nick, user)
count.event(self.net, "notice")
keyword.actKeyword(user, channel, msg, self.nickname, "NOTICE", self.name)
monitor.event(self.net, channel, {"type": "notice", "exact": user, "nick": nick, "ident": ident, "host": host, "message": msg})
monitor.event(self.net, {"type": "notice", "nick": nick, "ident": ident, "host": host, "target": channel, "message": msg})
def action(self, user, channel, msg):
nick, ident, host = self.parsen(user)
#userinfo.editUser(self.net, channel, nick, user)
count.event(self.net, "action")
keyword.actKeyword(user, channel, msg, self.nickname, "ACTION", self.name)
monitor.event(self.net, channel, {"type": "action", "exact": user, "nick": nick, "ident": ident, "host": host, "message": msg})
monitor.event(self.net, {"type": "action", "nick": nick, "ident": ident, "host": host, "target": channel, "message": msg})
def get(self, var):
try:
@ -207,7 +208,7 @@ class IRCBot(IRCClient):
n = self._who[channel][1]
n.append([nick, user, host, server, status, realname])
count.event(self.net, "whoreply")
monitor.event(self.net, channel, {"type": "who", "exact": nick+"!"+user+"@"+host, "nick": nick, "ident": user, "host": host, "realname": realname, "server": server, "status": status})
monitor.event(self.net, {"type": "who", "nick": nick, "ident": user, "host": host, "realname": realname, "target": channel, "server": server, "status": status})
def irc_RPL_ENDOFWHO(self, prefix, params):
channel = params[1]
@ -287,7 +288,7 @@ class IRCBot(IRCClient):
else:
message = None
if nick == self.nickname:
self.left(channel, message)
self.left(prefix, channel, message)
else:
self.userLeft(prefix, channel, message)
@ -295,8 +296,11 @@ class IRCBot(IRCClient):
"""
Called when a user has quit.
"""
#nick = prefix.split('!')[0]
self.userQuit(prefix, params[0])
nick = prefix.split('!')[0]
if nick == self.nickname:
self.botQuit(prefix, params[0])
else:
self.userQuit(prefix, params[0])
def irc_NICK(self, prefix, params):
"""
@ -336,7 +340,7 @@ class IRCBot(IRCClient):
self.connected = True
log("signed on: %s" % self.name)
if main.config["Notifications"]["Connection"]:
keyword.sendMaster("SIGNON: %s" % self.name)
sendRelayNotification(self.name, {"type": "conn", "status": "connected"})
count.event(self.net, "signedon")
def joined(self, channel):
@ -365,41 +369,48 @@ class IRCBot(IRCClient):
del self._getWho[channel]
userinfo.delChannel(self.net, channel)
def left(self, channel, message):
keyword.actKeyword(self.nickname, channel, message, self.nickname, "SELFPART", self.name)
def left(self, user, channel, message):
nick, ident, host = self.parsen(user)
count.event(self.net, "selfpart")
monitor.event(self.net, channel, {"type": "part", "message": message})
monitor.event(self.net, {"type": "part", "target": channel, "message": message})
monitor.event(self.net, {"type": "part", "self": True, "target": channel, "message": message})
self.botLeft(channel)
def kickedFrom(self, channel, kicker, message):
nick, ident, host = self.parsen(kicker)
if channel in self.channels:
self.channels.remove(channel)
keyword.sendMaster("KICK %s: (%s/%s) %s" % (self.name, kicker, channel, message))
count.event(self.net, "selfkick")
monitor.event(self.net, channel, {"type": "kick", "exact": kicker, "nick": nick, "ident": ident, "host": host, "message": message})
monitor.event(self.net, {"type": "kick", "nick": nick, "ident": ident, "host": host, "target": channel, "message": message})
monitor.event(self.net, {"type": "kick", "self": True, "nick": nick, "ident": ident, "host": host, "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)
count.event(self.net, "join")
monitor.event(self.net, channel, {"type": "join", "exact": user, "nick": nick, "ident": ident, "host": host})
monitor.event(self.net, {"type": "join", "nick": nick, "ident": ident, "host": host, "target": channel})
def userLeft(self, user, channel, message):
nick, ident, host = self.parsen(user)
userinfo.delUser(self.net, channel, nick, user)
keyword.actKeyword(user, channel, message, self.nickname, "PART", self.name)
count.event(self.net, "part")
monitor.event(self.net, channel, {"type": "part", "exact": user, "nick": nick, "ident": ident, "host": host, "message": message})
monitor.event(self.net, {"type": "part", "nick": nick, "ident": ident, "host": host, "target": channel, "message": message})
def userQuit(self, user, quitMessage):
nick, ident, host = self.parsen(user)
userinfo.delUserByNetwork(self.net, nick, user)
count.event(self.net, "quit")
keyword.actKeyword(user, None, quitMessage, self.nickname, "QUIT", self.name)
monitor.event(self.net, None, {"type": "quit", "exact": user, "nick": nick, "ident": ident, "host": host, "message": quitMessage})
monitor.event(self.net, {"type": "quit", "nick": nick, "ident": ident, "host": host, "message": quitMessage})
def botQuit(self, user, quitMessage):
nick, ident, host = self.parsen(user)
userinfo.delUserByNetwork(self.net, nick, user)
count.event(self.net, "selfquit")
monitor.event(self.net, {"type": "quit", "nick": nick, "ident": ident, "host": host, "message": quitMessage})
monitor.event(self.net, {"type": "quit", "self": True, "nick": nick, "ident": ident, "host": host, "message": quitMessage})
def userKicked(self, kickee, channel, kicker, message):
nick, ident, host = self.parsen(kicker)
@ -407,22 +418,20 @@ class IRCBot(IRCClient):
userinfo.delUserByNick(self.net, channel, kickee)
count.event(self.net, "kick")
keyword.actKeyword(kicker, channel, message, self.nickname, "KICK", self.name)
monitor.event(self.net, channel, {"type": "kick", "exact": kicker, "nick": nick, "ident": ident, "host": host, "message": message, "user": kickee})
monitor.event(self.net, {"type": "kick", "nick": nick, "ident": ident, "host": host, "target": channel, "message": message, "user": kickee})
def userRenamed(self, oldname, newname):
nick, ident, host = self.parsen(oldname)
userinfo.renameUser(self.net, nick, oldname, newname, newname+"!"+ident+"@"+host)
count.event(self.net, "nick")
monitor.event(self.net, None, {"type": "nick", "exact": oldname, "nick": nick, "ident": ident, "host": host, "user": newname})
monitor.event(self.net, {"type": "nick", "nick": nick, "ident": ident, "host": host, "user": newname})
def topicUpdated(self, user, channel, newTopic):
nick, ident, host = self.parsen(user)
userinfo.editUser(self.net, channel, nick, user)
count.event(self.net, "topic")
keyword.actKeyword(user, channel, newTopic, self.nickname, "TOPIC", self.name)
monitor.event(self.net, channel, {"type": "topic", "exact": user, "nick": nick, "ident": ident, "host": host, "message": newTopic})
monitor.event(self.net, {"type": "topic", "nick": nick, "ident": ident, "host": host, "target": channel, "message": newTopic})
def modeChanged(self, user, channel, toset, modes, args):
nick, ident, host = self.parsen(user)
@ -431,7 +440,7 @@ class IRCBot(IRCClient):
argList = list(args)
modeList = [i for i in modes]
for a, m in zip(argList, modeList):
monitor.event(self.net, channel, {"type": "mode", "exact": user, "nick": nick, "ident": ident, "host": host, "modes": m, "modeargs": a})
monitor.event(self.net, {"type": "mode", "nick": nick, "ident": ident, "host": host, "target": channel, "modes": m, "modeargs": a})
class IRCBotFactory(ReconnectingClientFactory):
def __init__(self, name, relay=None, relayCommands=None, user=None, stage2=None):
@ -449,7 +458,6 @@ class IRCBotFactory(ReconnectingClientFactory):
self.relay, self.relayCommands, self.user, self.stage2 = relay, relayCommands, user, stage2
def buildProtocol(self, addr):
if self.relay == None:
entry = IRCBot(self.name)
main.IRCPool[self.name] = entry
@ -470,7 +478,7 @@ class IRCBotFactory(ReconnectingClientFactory):
if not self.relay:
sendAll("%s: connection lost: %s" % (self.name, error))
if main.config["Notifications"]["Connection"]:
keyword.sendMaster("CONNLOST %s: %s" % (self.name, error))
sendRelayNotification(self.name, {"type": "conn", "status": "lost", "reason": error})
if not self.relay:
self.retry(connector)
#ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
@ -481,9 +489,10 @@ class IRCBotFactory(ReconnectingClientFactory):
self.client.channels = []
error = reason.getErrorMessage()
log("%s: connection failed: %s" % (self.name, error))
sendAll("%s: connection failed: %s" % (self.name, error))
if not self.relay:
sendAll("%s: connection failed: %s" % (self.name, error))
if main.config["Notifications"]["Connection"]:
keyword.sendMaster("CONNFAIL %s: %s" % (self.name, error))
sendRelayNotification(self.name, {"type": "conn", "status": "failed", "reason": error})
if not self.relay:
self.retry(connector)
#ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

View File

@ -1,8 +1,15 @@
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 *
validTypes = ["msg", "notice", "action", "who", "part", "join", "kick", "quit", "nick", "topic", "mode", "conn", "znc", "query", "self", "highlight", "monitor", "err"]
selfTypes = ["query", "self", "highlight"]
class Relay(Protocol):
def __init__(self, addr):
self.addr = addr
@ -40,11 +47,19 @@ class Relay(Protocol):
return
elif parsed["type"] == "control":
if "subscribe" in parsed.keys():
self.handleSubscribe(parsed["subscribe"])
return
if self.authed:
self.handleSubscribe(parsed["subscribe"])
return
else:
self.sendErr("DENIED")
return
elif "unsubscribe" in parsed.keys():
self.handleUnsubscribe(parsed["unsubscribe"])
return
if self.authed:
self.handleUnsubscribe(parsed["unsubscribe"])
return
else:
self.sendErr("DENIED")
return
else:
self.sendErr("UNCLEAR")
return
@ -57,7 +72,7 @@ class Relay(Protocol):
self.sendErr("NOTLIST")
return
for i in lst:
if not i in ["msg", "notice", "action", "who", "part", "join", "kick", "quit", "nick", "topic", "mode"]:
if not i in validTypes:
self.sendErr("NONEXISTANT")
return
if i in self.subscriptions:
@ -72,7 +87,7 @@ class Relay(Protocol):
self.sendErr("NOTLIST")
return
for i in lst:
if not i in ["msg", "notice", "action", "who", "part", "join", "kick", "quit", "nick", "topic", "mode"]:
if not i in validTypes:
self.sendErr("NONEXISTANT")
return
if not i in self.subscriptions:
@ -118,3 +133,12 @@ class RelayFactory(Factory):
connection.send(data)
else:
return
def sendRelayNotification(name, cast):
for i in main.relayConnections.keys():
if main.relayConnections[i].authed:
if cast["type"] in main.relayConnections[i].subscriptions or set(main.relayConnections[i].subscriptions).issubset(cast):
newCast = deepcopy(cast)
newCast["name"] = name
newCast["time"] = datetime.now()
main.relayConnections[i].send(dumps(newCast))

View File

@ -8,7 +8,6 @@ certPath = "cert/"
filemap = {
"config": ["config.json", "configuration"],
"keyconf": ["keyword.json", "keyword lists"],
"pool": ["pool.json", "network, alias and relay mappings"],
"help": ["help.json", "command help"],
"counters": ["counters.json", "counters file"],

View File

@ -1,121 +0,0 @@
import main
from utils.logging.log import *
import modules.counters as count
def sendMaster(data):
if not len(main.MonitorPool) == 0:
hasMonitors = True
else:
hasMonitors = False
if main.config["Master"] == [None, None]:
if hasMonitors:
for i in main.MonitorPool:
main.connections[i].send(data)
return
else:
main.masterbuf.append(data)
main.saveConf("masterbuf")
return
if main.config["Master"][0] in main.IRCPool.keys():
if main.config["Master"][1] in main.IRCPool[main.config["Master"][0]].channels:
main.IRCPool[main.config["Master"][0]].msg(main.config["Master"][1], data)
else:
if not hasMonitors:
main.masterbuf.append(data)
main.saveConf("masterbuf")
else:
if not hasMonitors:
main.masterbuf.append(data)
main.saveConf("masterbuf")
for i in main.MonitorPool:
main.connections[i].send(data)
def isKeyword(msg):
if msg == None:
return
message = msg.lower()
messageDuplicate = message
toUndo = False
uniqueNum = 0
totalNum = 0
for i in main.keyconf["Keywords"]:
if i in message:
if i in main.keyconf["KeywordsExcept"].keys():
for x in main.keyconf["KeywordsExcept"][i]:
if x in message:
toUndo = True
messageDuplicate = messageDuplicate.replace(x, "\0\r\n\n\0")
for y in main.keyconf["Keywords"]:
if i in messageDuplicate:
totalNum += messageDuplicate.count(i)
message = messageDuplicate.replace(i, "{"+i+"}")
message = message.replace("\0\r\n\n\0", x)
uniqueNum += 1
if toUndo == False:
totalNum += message.count(i)
message = message.replace(i, "{"+i+"}")
uniqueNum += 1
toUndo = False
if totalNum == 0:
return False
else:
return [message, uniqueNum, totalNum]
def actKeyword(user, channel, message, nickname, actType, name):
if message == None:
return
toSend = isKeyword(message)
if name == main.config["Master"][0] and channel == main.config["Master"][1]:
pass
else:
msgLower = message.lower()
nickLower = nickname.lower()
if nickLower in msgLower: # Someone has said the bot's nickname
msgLower = msgLower.replace(nickLower, "{"+nickLower+"}")
count.event(name, "nickhighlight")
if main.config["Notifications"]["Highlight"]:
sendMaster("NICK %s %s (T:%s): (%s/%s) %s" % (actType, name, msgLower.count(nickLower), user, channel, msgLower))
if not channel == None:
chanLower = channel.lower()
if nickLower == chanLower: # I received a message directed only at me
ZNCAlreadySent = False
if main.config["Notifications"]["Query"]:
if user == main.config["Tweaks"]["ZNC"]["Prefix"] + "status!znc@znc.in":
if main.config["Compat"]["ZNC"]:
sendMaster("ZNC %s %s: %s" % (actType, name, msgLower))
ZNCAlreadySent = True
else:
sendMaster("QUERY %s %s: (%s) %s" % (actType, name, user, msgLower))
else:
sendMaster("QUERY %s %s: (%s) %s" % (actType, name, user, msgLower))
if not ZNCAlreadySent == True:
if main.config["Compat"]["ZNC"]:
if user == main.config["Tweaks"]["ZNC"]["Prefix"] + "status!znc@znc.in":
sendMaster("ZNC %s %s: %s" % (actType, name, msgLower))
if toSend:
sendMaster("MATCH %s %s (U:%s T:%s): (%s/%s) %s" % (actType, name, toSend[1], toSend[2], user, channel, toSend[0]))
count.event(name, "keymatch")
def addKeyword(keyword):
if keyword in main.keyconf["Keywords"]:
return "EXISTS"
else:
for i in main.keyconf["Keywords"]:
if i in keyword or keyword in i:
return "ISIN"
main.keyconf["Keywords"].append(keyword)
main.saveConf("keyconf")
return True
def delKeyword(keyword):
if not keyword in main.keyconf["Keywords"]:
return "NOKEY"
main.keyconf["Keywords"].remove(keyword)
main.saveConf("keyconf")
return True

View File

@ -1,8 +1,9 @@
import main
import modules.keyword as keyword
from copy import deepcopy
from json import dumps
import main
from core.relay import sendRelayNotification
def testNetTarget(name, target):
called = False
for i in main.monitor.keys():
@ -49,32 +50,33 @@ 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, target, cast):
for i in main.relayConnections.keys():
if main.relayConnections[i].authed and cast["type"] in main.relayConnections[i].subscriptions:
newCast = deepcopy(cast)
if not target == None:
newCast["target"] = target
if "exact" in newCast.keys():
del newCast["exact"]
newCast["name"] = name
main.relayConnections[i].send(dumps(newCast))
def event(name, cast, event=None):
if "target" in cast.keys():
target = cast["target"]
else:
target = None
if set(["nick", "ident", "host", "message"]).issubset(set(cast)):
if main.config["Compat"]["ZNC"] and "message" in cast.keys():
if cast["nick"][0] == main.config["Tweaks"]["ZNC"]["Prefix"] and cast["ident"] == "znc" and cast["host"] == "znc.in":
sendRelayNotification(name, {"type": "znc", "message": cast["message"]})
return
sendRelayNotification(name, cast)
monitorGroups = testNetTarget(name, target)
if monitorGroups == False:
return
for monitorGroup in monitorGroups:
matcher = magicFunction(deepcopy(cast), deepcopy(main.monitor[monitorGroup]))
if matcher == True:
cast["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):
keyword.sendMaster("ERRDELIV MONITOR [%s] (%s/%s) %s " % (monitorGroup, name, target, cast))
sendRelayNotification(name, {"type": "err", "name": name, "target": target, "message": cast, "reason": "errdeliv"})
continue
if not i in main.pool.keys():
keyword.sendMaster("ERROR on monitor %s: No such name: %s" % (monitorGroup, i))
sendRelayNotification(name, {"type": "err", "name": name, "target": target, "message": cast, "reason": "noname"})
if not i in main.IRCPool.keys():
keyword.sendMaster("ERROR on monitor %s: No such instance: %s" % (monitorGroup, i))
sendRelayNotification(name, {"type": "err", "name": name, "target": target, "message": cast, "reason": "noinstance"})
for x in main.monitor[monitorGroup]["send"][i]:
main.IRCPool[i].msg(x, "MONITOR [%s] (%s/%s) %s" % (monitorGroup, name, target, cast))
else:
keyword.sendMaster("MONITOR [%s] (%s/%s) %s " % (monitorGroup, name, target, cast))
main.IRCPool[i].msg(x, "monitor [%s] (%s) %s" % (monitorGroup, name, cast))