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

View File

@ -1,8 +1,15 @@
from twisted.internet.protocol import Protocol, Factory, ClientFactory from twisted.internet.protocol import Protocol, Factory, ClientFactory
from json import dumps, loads from json import dumps, loads
from copy import deepcopy
from datetime import datetime
import main import main
from utils.logging.log import * 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): class Relay(Protocol):
def __init__(self, addr): def __init__(self, addr):
self.addr = addr self.addr = addr
@ -40,11 +47,19 @@ class Relay(Protocol):
return return
elif parsed["type"] == "control": elif parsed["type"] == "control":
if "subscribe" in parsed.keys(): if "subscribe" in parsed.keys():
self.handleSubscribe(parsed["subscribe"]) if self.authed:
return self.handleSubscribe(parsed["subscribe"])
return
else:
self.sendErr("DENIED")
return
elif "unsubscribe" in parsed.keys(): elif "unsubscribe" in parsed.keys():
self.handleUnsubscribe(parsed["unsubscribe"]) if self.authed:
return self.handleUnsubscribe(parsed["unsubscribe"])
return
else:
self.sendErr("DENIED")
return
else: else:
self.sendErr("UNCLEAR") self.sendErr("UNCLEAR")
return return
@ -57,7 +72,7 @@ class Relay(Protocol):
self.sendErr("NOTLIST") self.sendErr("NOTLIST")
return return
for i in lst: 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") self.sendErr("NONEXISTANT")
return return
if i in self.subscriptions: if i in self.subscriptions:
@ -72,7 +87,7 @@ class Relay(Protocol):
self.sendErr("NOTLIST") self.sendErr("NOTLIST")
return return
for i in lst: 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") self.sendErr("NONEXISTANT")
return return
if not i in self.subscriptions: if not i in self.subscriptions:
@ -118,3 +133,12 @@ class RelayFactory(Factory):
connection.send(data) connection.send(data)
else: else:
return 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 = { filemap = {
"config": ["config.json", "configuration"], "config": ["config.json", "configuration"],
"keyconf": ["keyword.json", "keyword lists"],
"pool": ["pool.json", "network, alias and relay mappings"], "pool": ["pool.json", "network, alias and relay mappings"],
"help": ["help.json", "command help"], "help": ["help.json", "command help"],
"counters": ["counters.json", "counters file"], "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 copy import deepcopy
from json import dumps from json import dumps
import main
from core.relay import sendRelayNotification
def testNetTarget(name, target): def testNetTarget(name, target):
called = False called = False
for i in main.monitor.keys(): for i in main.monitor.keys():
@ -49,32 +50,33 @@ def magicFunction(A, B):
else: else:
return all(A[k] in B[k] for k in set(A) & set(B)) and set(B) <= set(A) return all(A[k] in B[k] for k in set(A) & set(B)) and set(B) <= set(A)
def event(name, target, cast): def event(name, cast, event=None):
for i in main.relayConnections.keys(): if "target" in cast.keys():
if main.relayConnections[i].authed and cast["type"] in main.relayConnections[i].subscriptions: target = cast["target"]
newCast = deepcopy(cast) else:
if not target == None: target = None
newCast["target"] = target if set(["nick", "ident", "host", "message"]).issubset(set(cast)):
if "exact" in newCast.keys(): if main.config["Compat"]["ZNC"] and "message" in cast.keys():
del newCast["exact"] if cast["nick"][0] == main.config["Tweaks"]["ZNC"]["Prefix"] and cast["ident"] == "znc" and cast["host"] == "znc.in":
newCast["name"] = name sendRelayNotification(name, {"type": "znc", "message": cast["message"]})
main.relayConnections[i].send(dumps(newCast)) return
sendRelayNotification(name, cast)
monitorGroups = testNetTarget(name, target) monitorGroups = testNetTarget(name, target)
if monitorGroups == False: if monitorGroups == False:
return return
for monitorGroup in monitorGroups: for monitorGroup in monitorGroups:
matcher = magicFunction(deepcopy(cast), deepcopy(main.monitor[monitorGroup])) matcher = magicFunction(deepcopy(cast), deepcopy(main.monitor[monitorGroup]))
if matcher == True: if matcher == True:
cast["monitor"] = True
if "send" in main.monitor[monitorGroup].keys(): if "send" in main.monitor[monitorGroup].keys():
for i in main.monitor[monitorGroup]["send"].keys(): for i in main.monitor[monitorGroup]["send"].keys():
if isinstance(main.monitor[monitorGroup]["send"][i], bool): 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 continue
if not i in main.pool.keys(): 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(): 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]: for x in main.monitor[monitorGroup]["send"][i]:
main.IRCPool[i].msg(x, "MONITOR [%s] (%s/%s) %s" % (monitorGroup, name, target, cast)) main.IRCPool[i].msg(x, "monitor [%s] (%s) %s" % (monitorGroup, name, cast))
else:
keyword.sendMaster("MONITOR [%s] (%s/%s) %s " % (monitorGroup, name, target, cast))