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

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

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))