2017-11-19 14:46:42 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
from twisted.internet import reactor
|
2017-11-24 19:16:08 +00:00
|
|
|
from twisted.internet.defer import Deferred
|
2017-11-19 14:46:42 +00:00
|
|
|
from twisted.internet.ssl import DefaultOpenSSLContextFactory
|
|
|
|
from twisted.internet.protocol import Protocol, Factory
|
2017-11-23 20:37:00 +00:00
|
|
|
from twisted.internet.endpoints import SSL4ClientEndpoint, TCP4ClientEndpoint, connectProtocol
|
|
|
|
from twisted.words.protocols.irc import IRCClient
|
|
|
|
|
2017-12-24 21:04:48 +00:00
|
|
|
#from twisted.python import log
|
|
|
|
#from sys import stdout
|
|
|
|
#log.startLogging(stdout)
|
|
|
|
|
2017-11-21 20:16:14 +00:00
|
|
|
from json import load, dump, loads
|
2017-11-19 14:46:42 +00:00
|
|
|
from sys import exit
|
2017-12-03 18:34:56 +00:00
|
|
|
from subprocess import run, PIPE
|
2017-11-19 14:46:42 +00:00
|
|
|
|
2017-12-24 21:04:48 +00:00
|
|
|
numbers = "0123456789"
|
|
|
|
|
2017-11-19 14:46:42 +00:00
|
|
|
listener = None
|
|
|
|
connections = {}
|
2017-11-23 20:37:00 +00:00
|
|
|
IRCPool = {}
|
2017-11-19 14:46:42 +00:00
|
|
|
|
2017-12-24 21:04:48 +00:00
|
|
|
MonitorPool = []
|
|
|
|
|
|
|
|
wholist = {}
|
|
|
|
|
2017-11-19 14:46:42 +00:00
|
|
|
def log(data):
|
|
|
|
print("[LOG]", data)
|
|
|
|
|
|
|
|
def debug(data):
|
|
|
|
print("[DEBUG]", data)
|
|
|
|
|
2017-11-20 19:15:58 +00:00
|
|
|
def warn(data):
|
|
|
|
print("[WARNING]", data)
|
|
|
|
|
|
|
|
def error(data):
|
|
|
|
print("[ERROR]", data)
|
|
|
|
exit(1)
|
|
|
|
|
2017-11-20 21:40:04 +00:00
|
|
|
def sendData(addr, data):
|
|
|
|
connections[addr].send(data)
|
|
|
|
|
|
|
|
def sendSuccess(addr, data):
|
|
|
|
sendData(addr, "[y] " + data)
|
|
|
|
|
|
|
|
def sendFailure(addr, data):
|
|
|
|
sendData(addr, "[n] " + data)
|
|
|
|
|
|
|
|
def sendInfo(addr, data):
|
|
|
|
sendData(addr, "[i] " + data)
|
|
|
|
|
2017-11-23 20:37:00 +00:00
|
|
|
class IRCBot(IRCClient):
|
|
|
|
def __init__(self, name):
|
2017-11-24 19:16:08 +00:00
|
|
|
self.connected = False
|
|
|
|
self.channels = []
|
|
|
|
|
2017-11-23 20:37:00 +00:00
|
|
|
self.name = name
|
|
|
|
instance = pool[name]
|
|
|
|
|
|
|
|
self.nickname = instance["nickname"]
|
|
|
|
self.realname = instance["realname"]
|
|
|
|
self.username = instance["username"]
|
|
|
|
self.userinfo = instance["userinfo"]
|
|
|
|
self.fingerReply = instance["finger"]
|
|
|
|
self.versionName = instance["version"]
|
|
|
|
self.versionNum = None
|
|
|
|
self.versionEnv = None
|
|
|
|
self.sourceURL = instance["source"]
|
2017-11-25 19:48:20 +00:00
|
|
|
self.autojoin = instance["autojoin"]
|
2017-11-23 20:37:00 +00:00
|
|
|
|
|
|
|
self._who = {}
|
|
|
|
self._getWho = {}
|
|
|
|
|
|
|
|
self.authtype = instance["authtype"]
|
|
|
|
if self.authtype == "ns":
|
|
|
|
self.authpass = instance["password"]
|
|
|
|
self.authentity = instance["authentity"]
|
|
|
|
else:
|
|
|
|
self.password = instance["password"]
|
|
|
|
|
|
|
|
def refresh(self):
|
2017-11-24 19:16:08 +00:00
|
|
|
instance = pool[self.name]
|
2017-11-23 20:37:00 +00:00
|
|
|
if not instance["nickname"] == self.nickname:
|
|
|
|
self.nickname = instance["nickname"]
|
|
|
|
self.setNick(self.nickname)
|
|
|
|
|
|
|
|
self.userinfo = instance["userinfo"]
|
|
|
|
self.fingerReply = instance["finger"]
|
|
|
|
self.versionName = instance["version"]
|
|
|
|
self.versionNum = None
|
|
|
|
self.versionEnv = None
|
|
|
|
self.sourceURL = instance["source"]
|
|
|
|
|
2017-12-25 22:09:38 +00:00
|
|
|
def parsen(self, user):
|
|
|
|
step = user.split("!")
|
|
|
|
nick = step[0]
|
|
|
|
if len(step) == 2:
|
|
|
|
step2 = step[1].split("@")
|
|
|
|
ident, host = step2
|
2017-11-30 18:54:08 +00:00
|
|
|
else:
|
2017-12-25 22:09:38 +00:00
|
|
|
ident = nick
|
|
|
|
host = nick
|
|
|
|
|
|
|
|
return [nick, ident, host]
|
|
|
|
|
|
|
|
def privmsg(self, user, channel, msg):
|
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
|
|
|
helper.actKeyword(user, channel, msg, self.nickname, "PRV", self.name)
|
2017-11-25 19:02:13 +00:00
|
|
|
|
|
|
|
def noticed(self, user, channel, msg):
|
2017-12-25 22:09:38 +00:00
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
|
|
|
helper.actKeyword(user, channel, msg, self.nickname, "NOT", self.name)
|
2017-11-25 19:02:13 +00:00
|
|
|
|
|
|
|
def action(self, user, channel, msg):
|
2017-12-25 22:09:38 +00:00
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
|
|
|
helper.actKeyword(user, channel, msg, self.nickname, "ACT", self.name)
|
2017-11-25 19:02:13 +00:00
|
|
|
|
2017-11-24 19:16:08 +00:00
|
|
|
def get(self, var):
|
|
|
|
try:
|
|
|
|
result = getattr(self, var)
|
|
|
|
except AttributeError:
|
|
|
|
result = None
|
|
|
|
return result
|
|
|
|
|
2017-11-23 20:37:00 +00:00
|
|
|
def setNick(self, nickname):
|
|
|
|
self._attemptedNick = nickname
|
|
|
|
self.sendLine("NICK %s" % nickname)
|
|
|
|
self.nickname = nickname
|
|
|
|
|
|
|
|
def alterCollidedNick(self, nickname):
|
|
|
|
newnick = nickname + "_"
|
|
|
|
return newnick
|
|
|
|
|
|
|
|
def irc_ERR_NICKNAMEINUSE(self, prefix, params):
|
|
|
|
self._attemptedNick = self.alterCollidedNick(self._attemptedNick)
|
|
|
|
self.setNick(self._attemptedNick)
|
|
|
|
|
|
|
|
def irc_ERR_PASSWDMISMATCH(self, prefix, params):
|
2017-11-24 19:16:08 +00:00
|
|
|
log("%s: password mismatch" % self.name)
|
|
|
|
helper.sendAll("%s: password mismatch" % self.name)
|
2017-11-23 20:37:00 +00:00
|
|
|
|
|
|
|
def who(self, channel):
|
|
|
|
channel = channel
|
2017-11-24 19:16:08 +00:00
|
|
|
d = Deferred()
|
2017-11-23 20:37:00 +00:00
|
|
|
if channel not in self._who:
|
|
|
|
self._who[channel] = ([], {})
|
|
|
|
self._who[channel][0].append(d)
|
|
|
|
self.sendLine("WHO %s" % channel)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def irc_RPL_WHOREPLY(self, prefix, params):
|
|
|
|
channel = params[1]
|
|
|
|
user = params[2]
|
|
|
|
host = params[3]
|
|
|
|
server = params[4]
|
|
|
|
nick = params[5]
|
|
|
|
status = params[6]
|
|
|
|
realname = params[7]
|
|
|
|
if channel not in self._who:
|
|
|
|
return
|
|
|
|
n = self._who[channel][1]
|
|
|
|
n[nick] = [nick, user, host, server, status, realname]
|
|
|
|
|
|
|
|
def irc_RPL_ENDOFWHO(self, prefix, params):
|
|
|
|
channel = params[1]
|
|
|
|
if channel not in self._who:
|
|
|
|
return
|
|
|
|
callbacks, info = self._who[channel]
|
|
|
|
for cb in callbacks:
|
|
|
|
cb.callback((channel, info))
|
|
|
|
del self._who[channel]
|
|
|
|
|
|
|
|
def got_who(self, whoinfo):
|
2017-12-24 21:04:48 +00:00
|
|
|
global wholist
|
|
|
|
helper.setWho(self.name, whoinfo[1])
|
2017-11-23 20:37:00 +00:00
|
|
|
|
|
|
|
def signedOn(self):
|
2017-11-24 19:16:08 +00:00
|
|
|
self.connected = True
|
2017-12-25 19:02:17 +00:00
|
|
|
log("signed on: %s" % self.name)
|
2017-11-23 20:37:00 +00:00
|
|
|
if self.authtype == "ns":
|
|
|
|
self.msg(self.authentity, "IDENTIFY %s" % self.nspass)
|
2017-11-25 19:48:20 +00:00
|
|
|
for i in self.autojoin:
|
|
|
|
self.join(i)
|
2017-11-23 20:37:00 +00:00
|
|
|
|
|
|
|
def joined(self, channel):
|
2017-11-24 19:16:08 +00:00
|
|
|
if not channel in self.channels:
|
|
|
|
self.channels.append(channel)
|
2017-11-23 20:37:00 +00:00
|
|
|
self.who(channel).addCallback(self.got_who)
|
|
|
|
|
2017-11-24 19:16:08 +00:00
|
|
|
def left(self, channel):
|
|
|
|
if channel in self.channels:
|
|
|
|
self.channels.remove(channel)
|
|
|
|
|
|
|
|
def kickedFrom(self, channel, kicker, message):
|
|
|
|
if channel in self.channels:
|
|
|
|
self.channels.remove(channel)
|
2017-11-28 19:31:02 +00:00
|
|
|
helper.sendMaster("KICK %s: (%s/%s) %s" % (self.name, kicker, channel, message))
|
2017-11-24 19:16:08 +00:00
|
|
|
|
2017-12-25 22:09:38 +00:00
|
|
|
def userJoined(self, user, channel):
|
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
|
|
|
def userLeft(self, user, channel):
|
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
|
|
|
def userQuit(self, user, quitMessage):
|
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
|
|
|
helper.actKeyword(user, None, quitMessage, self.nickname, "QUT", self.name)
|
|
|
|
|
|
|
|
def userKicked(self, kickee, channel, kicker, message):
|
|
|
|
helper.actKeyword(kicker, channel, message, self.nickname, "KCK", self.name)
|
|
|
|
|
|
|
|
def topicUpdated(self, user, channel, newTopic):
|
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
|
|
|
helper.actKeyword(user, channel, newTopic, self.nickname, "TOP", self.name)
|
|
|
|
|
|
|
|
def modeChanged(self, user, channel, toset, modes, args):
|
|
|
|
nick, ident, host = self.parsen(user)
|
|
|
|
helper.setWhoSingle(self.name, nick, ident, host)
|
|
|
|
|
2017-11-24 19:16:08 +00:00
|
|
|
def connectionLost(self, reason):
|
|
|
|
self.connected = False
|
|
|
|
self.channels = []
|
|
|
|
error = reason.getErrorMessage()
|
|
|
|
log("%s: connection lost: %s" % (self.name, error))
|
|
|
|
helper.sendAll("%s: connection lost: %s" % (self.name, error))
|
|
|
|
|
|
|
|
def connectionFailed(self, reason):
|
|
|
|
self.connected = False
|
|
|
|
self.channels = []
|
|
|
|
error = reason.getErrorMessage()
|
|
|
|
log("%s: connection failed: %s" % (self.name, error))
|
|
|
|
helper.sendAll("%s: connection failed: %s" % (self.name, error))
|
|
|
|
|
2017-11-19 14:46:42 +00:00
|
|
|
class Base(Protocol):
|
|
|
|
def __init__(self, addr):
|
|
|
|
self.addr = addr
|
|
|
|
self.authed = False
|
2017-11-23 18:32:30 +00:00
|
|
|
if config["UsePassword"] == False:
|
|
|
|
self.authed = True
|
2017-11-19 14:46:42 +00:00
|
|
|
|
|
|
|
def send(self, data):
|
|
|
|
data += "\r\n"
|
|
|
|
data = data.encode("utf-8", "replace")
|
|
|
|
self.transport.write(data)
|
|
|
|
|
|
|
|
def dataReceived(self, data):
|
2017-11-20 21:40:04 +00:00
|
|
|
data = data.decode("utf-8", "replace")
|
2017-11-27 19:54:35 +00:00
|
|
|
#log("Data received from %s:%s -- %s" % (self.addr.host, self.addr.port, repr(data)))
|
2017-12-03 13:10:51 +00:00
|
|
|
if "\n" in data:
|
|
|
|
splitData = [x for x in data.split("\n") if x]
|
|
|
|
if "\n" in data:
|
|
|
|
for i in splitData:
|
|
|
|
helper.parseCommand(self.addr, self.authed, i)
|
|
|
|
return
|
2017-11-20 21:40:04 +00:00
|
|
|
helper.parseCommand(self.addr, self.authed, data)
|
2017-11-19 14:46:42 +00:00
|
|
|
|
|
|
|
def connectionMade(self):
|
|
|
|
log("Connection from %s:%s" % (self.addr.host, self.addr.port))
|
|
|
|
self.send("Hello.")
|
|
|
|
|
|
|
|
def connectionLost(self, reason):
|
2017-12-24 21:04:48 +00:00
|
|
|
global connections, MonitorPool
|
2017-11-21 20:16:14 +00:00
|
|
|
self.authed = False
|
2017-11-20 21:40:04 +00:00
|
|
|
log("Connection lost from %s:%s -- %s" % (self.addr.host, self.addr.port, reason.getErrorMessage()))
|
2017-11-19 14:46:42 +00:00
|
|
|
if not listener == None:
|
|
|
|
if self.addr in connections.keys():
|
|
|
|
del connections[self.addr]
|
|
|
|
else:
|
2017-11-20 19:15:58 +00:00
|
|
|
warn("Tried to remove a non-existant connection.")
|
2017-11-19 14:46:42 +00:00
|
|
|
else:
|
2017-11-20 19:15:58 +00:00
|
|
|
warn("Tried to remove a connection from a listener that wasn't running.")
|
2017-12-24 21:04:48 +00:00
|
|
|
if self.addr in MonitorPool:
|
|
|
|
MonitorPool.remove(self.addr)
|
2017-11-19 14:46:42 +00:00
|
|
|
|
|
|
|
class BaseFactory(Factory):
|
|
|
|
def buildProtocol(self, addr):
|
|
|
|
global connections
|
|
|
|
entry = Base(addr)
|
|
|
|
connections[addr] = entry
|
|
|
|
return entry
|
|
|
|
|
|
|
|
def send(self, addr, data):
|
|
|
|
global connections
|
|
|
|
if addr in connections.keys():
|
|
|
|
connection = connections[addr]
|
|
|
|
connection.send(data)
|
|
|
|
else:
|
|
|
|
return
|
|
|
|
|
2017-11-20 19:53:25 +00:00
|
|
|
class Helper(object):
|
|
|
|
def getConfig(self):
|
|
|
|
with open("config.json", "r") as f:
|
|
|
|
config = load(f)
|
2017-11-23 18:32:30 +00:00
|
|
|
if set(["Port", "BindAddress", "UseSSL", "UsePassword"]).issubset(set(config.keys())):
|
|
|
|
if config["UseSSL"] == True:
|
|
|
|
if not set(["ListenerKey", "ListenerCertificate"]).issubset(set(config.keys())):
|
2017-11-20 19:53:25 +00:00
|
|
|
error("SSL is on but certificate or key is not defined")
|
2017-11-23 18:32:30 +00:00
|
|
|
if config["UsePassword"] == True:
|
|
|
|
if not "Password" in config.keys():
|
2017-11-20 21:40:04 +00:00
|
|
|
error("Password authentication is on but password is not defined")
|
2017-11-20 19:53:25 +00:00
|
|
|
return config
|
|
|
|
else:
|
|
|
|
error("Mandatory values missing from config")
|
2017-11-19 14:46:42 +00:00
|
|
|
|
2017-12-24 21:04:48 +00:00
|
|
|
def setWho(self, network, newObjects):
|
|
|
|
global wholist
|
|
|
|
network = "".join([x for x in network if not x in numbers])
|
|
|
|
if not network in wholist.keys():
|
|
|
|
wholist[network] = {}
|
|
|
|
for i in newObjects.keys():
|
|
|
|
wholist[network][i] = newObjects[i]
|
2017-12-25 22:27:09 +00:00
|
|
|
|
2017-12-24 21:04:48 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
def setWhoSingle(self, network, nick, ident, host):
|
|
|
|
global wholist
|
|
|
|
network = "".join([x for x in network if not x in numbers])
|
|
|
|
|
|
|
|
if network in wholist.keys():
|
|
|
|
if nick in wholist[network].keys():
|
|
|
|
wholist[network][nick][1] = ident
|
|
|
|
wholist[network][nick][2] = host
|
2017-12-25 19:02:17 +00:00
|
|
|
else:
|
|
|
|
wholist[network][nick] = [nick, ident, host, None, None, None]
|
|
|
|
|
|
|
|
def getWho(self, nick):
|
|
|
|
result = {}
|
|
|
|
for i in wholist.keys():
|
|
|
|
for x in wholist[i].keys():
|
|
|
|
if nick.lower() == x.lower():
|
|
|
|
if not i in result.keys():
|
|
|
|
result[i] = []
|
|
|
|
result[i].append(wholist[i][x])
|
|
|
|
return result
|
2017-12-03 13:10:51 +00:00
|
|
|
|
|
|
|
def getKeywordConfig(self):
|
|
|
|
with open("keyword.json", "r") as f:
|
2017-12-25 22:27:09 +00:00
|
|
|
return load(f)
|
2017-12-03 13:10:51 +00:00
|
|
|
|
2017-12-25 22:27:09 +00:00
|
|
|
def getWholist(self):
|
|
|
|
with open("wholist.json", "r") as f:
|
|
|
|
return load(f)
|
2017-12-03 13:10:51 +00:00
|
|
|
|
2017-11-21 20:16:14 +00:00
|
|
|
def getPool(self):
|
|
|
|
with open("pool.json", "r") as f:
|
|
|
|
data = f.read()
|
|
|
|
if not data == "":
|
|
|
|
pool = loads(data.strip())
|
|
|
|
return pool
|
|
|
|
else:
|
|
|
|
return {}
|
|
|
|
|
2017-12-25 22:27:09 +00:00
|
|
|
def saveConfig(self):
|
|
|
|
global config
|
|
|
|
with open("config.json", "w") as f:
|
|
|
|
dump(config, f, indent=4)
|
|
|
|
return
|
|
|
|
|
|
|
|
def saveKeywordConfig(self):
|
|
|
|
global keyconf
|
|
|
|
with open("keyword.json", "w") as f:
|
|
|
|
dump(keyconf, f, indent=4)
|
|
|
|
return
|
|
|
|
|
|
|
|
def saveWholist(self):
|
|
|
|
global wholist
|
|
|
|
with open("wholist.json", "w") as f:
|
|
|
|
dump(wholist, f, indent=4)
|
|
|
|
return
|
|
|
|
|
2017-11-21 20:16:14 +00:00
|
|
|
def savePool(self):
|
|
|
|
global pool
|
|
|
|
with open("pool.json", "w") as f:
|
|
|
|
dump(pool, f, indent=4)
|
|
|
|
return
|
|
|
|
|
|
|
|
def getHelp(self):
|
|
|
|
with open("help.json", "r") as f:
|
|
|
|
help = load(f)
|
|
|
|
return help
|
|
|
|
|
|
|
|
def incorrectUsage(self, addr, mode):
|
|
|
|
if mode == None:
|
|
|
|
sendFailure(addr, "Incorrect usage")
|
|
|
|
return
|
|
|
|
if mode in help.keys():
|
|
|
|
sendFailure(addr, "Usage: " + help[mode])
|
|
|
|
return
|
|
|
|
|
2017-11-24 19:16:08 +00:00
|
|
|
def sendAll(self, data):
|
|
|
|
global connections
|
|
|
|
for i in connections:
|
|
|
|
connections[i].send(data)
|
|
|
|
return
|
|
|
|
|
2017-11-25 18:42:32 +00:00
|
|
|
def sendMaster(self, data):
|
|
|
|
if config["Master"][0] in IRCPool.keys():
|
|
|
|
IRCPool[config["Master"][0]].msg(config["Master"][1], data)
|
2017-12-24 21:09:18 +00:00
|
|
|
else:
|
|
|
|
warning("Master with no IRC instance defined")
|
2017-12-24 21:04:48 +00:00
|
|
|
for i in MonitorPool:
|
|
|
|
connections[i].send(data)
|
2017-11-25 18:42:32 +00:00
|
|
|
|
|
|
|
def isKeyword(self, msg):
|
|
|
|
message = msg.lower()
|
2017-11-28 19:19:27 +00:00
|
|
|
messageDuplicate = message
|
2017-11-27 19:54:35 +00:00
|
|
|
toUndo = False
|
2017-11-25 18:42:32 +00:00
|
|
|
uniqueNum = 0
|
|
|
|
totalNum = 0
|
2017-12-03 13:10:51 +00:00
|
|
|
for i in keyconf["Keywords"]:
|
2017-11-25 18:42:32 +00:00
|
|
|
if i in message:
|
2017-12-03 13:10:51 +00:00
|
|
|
if i in keyconf["KeywordsExcept"].keys():
|
|
|
|
for x in keyconf["KeywordsExcept"][i]:
|
2017-11-27 19:54:35 +00:00
|
|
|
if x in message:
|
|
|
|
toUndo = True
|
2017-11-28 19:19:27 +00:00
|
|
|
messageDuplicate = messageDuplicate.replace(x, "\0\r\n\n\0")
|
2017-12-03 13:10:51 +00:00
|
|
|
for y in keyconf["Keywords"]:
|
2017-11-28 19:19:27 +00:00
|
|
|
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
|
2017-11-27 19:54:35 +00:00
|
|
|
|
|
|
|
toUndo = False
|
|
|
|
|
2017-11-25 19:50:57 +00:00
|
|
|
if totalNum == 0:
|
2017-11-25 18:42:32 +00:00
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return [message, uniqueNum, totalNum]
|
|
|
|
|
2017-12-25 22:09:38 +00:00
|
|
|
def actKeyword(self, user, channel, message, nickname, actType, name):
|
|
|
|
toSend = self.isKeyword(message)
|
|
|
|
if name == config["Master"][0] and channel == config["Master"][1]:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
if config["HighlightNotifications"]:
|
|
|
|
msgLower = message.lower()
|
|
|
|
nickLower = nickname.lower()
|
|
|
|
if nickLower in msgLower:
|
|
|
|
msgLower = msgLower.replace(nickLower, "{"+nickLower+"}")
|
|
|
|
self.sendMaster("NICK %s %s (T:%s): (%s/%s) %s" % (actType, name, msgLower.count(nickLower), user, channel, msgLower))
|
|
|
|
if toSend:
|
|
|
|
helper.sendMaster("MATCH %s %s (U:%s T:%s): (%s/%s) %s" % (actType, name, toSend[1], toSend[2], user, channel, toSend[0]))
|
|
|
|
|
2017-11-23 20:37:00 +00:00
|
|
|
def addBot(self, name):
|
|
|
|
global IRCPool
|
|
|
|
instance = pool[name]
|
2017-11-24 19:16:08 +00:00
|
|
|
log("Started bot %s to %s:%s protocol %s nickname %s" % (name, instance["host"], instance["port"], instance["protocol"], instance["nickname"]))
|
2017-11-23 20:37:00 +00:00
|
|
|
if instance["protocol"] == "plain":
|
|
|
|
if instance["bind"] == None:
|
|
|
|
point = TCP4ClientEndpoint(reactor, instance["host"], int(instance["port"]), timeout=int(instance["timeout"]))
|
|
|
|
bot = IRCBot(name)
|
|
|
|
IRCPool[name] = bot
|
|
|
|
d = connectProtocol(point, bot)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
point = TCP4ClientEndpoint(reactor, instance["host"], int(instance["port"]), timeout=int(instance["timeout"]), bindAddress=instance["bind"])
|
|
|
|
bot = IRCBot(name)
|
|
|
|
IRCPool[name] = bot
|
|
|
|
d = connectProtocol(point, bot)
|
|
|
|
return
|
|
|
|
elif instance["protocol"] == "ssl":
|
|
|
|
contextFactory = DefaultOpenSSLContextFactory(instance["key"].encode("utf-8", "replace"), instance["certificate"].encode("utf-8", "replace"))
|
|
|
|
if instance["bind"] == None:
|
|
|
|
point = SSL4ClientEndpoint(reactor, instance["host"], int(instance["port"]), contextFactory, timeout=int(instance["timeout"]))
|
|
|
|
bot = IRCBot(name)
|
|
|
|
IRCPool[name] = bot
|
|
|
|
d = connectProtocol(point, bot)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
point = SSL4ClientEndpoint(reactor, instance["host"], int(instance["port"]), contextFactory, timeout=int(instance["timeout"]), bindAddress=instance["bind"])
|
|
|
|
bot = IRCBot(name)
|
|
|
|
IRCPool[name] = bot
|
|
|
|
d = connectProtocol(point, bot)
|
|
|
|
return
|
|
|
|
|
2017-11-25 00:38:06 +00:00
|
|
|
def addKeyword(self, keyword):
|
2017-12-03 13:10:51 +00:00
|
|
|
if keyword in keyconf["Keywords"]:
|
2017-11-25 00:38:06 +00:00
|
|
|
return "EXISTS"
|
|
|
|
else:
|
2017-12-03 13:10:51 +00:00
|
|
|
for i in keyconf["Keywords"]:
|
2017-11-25 00:38:06 +00:00
|
|
|
if i in keyword or keyword in i:
|
|
|
|
return "ISIN"
|
2017-12-03 13:10:51 +00:00
|
|
|
keyconf["Keywords"].append(keyword)
|
|
|
|
helper.saveKeywordConfig()
|
2017-11-25 00:38:06 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
def delKeyword(self, keyword):
|
2017-12-03 13:10:51 +00:00
|
|
|
if not keyword in keyconf["Keywords"]:
|
2017-11-25 00:38:06 +00:00
|
|
|
return "NOKEY"
|
2017-12-03 13:10:51 +00:00
|
|
|
keyconf["Keywords"].remove(keyword)
|
|
|
|
helper.saveKeywordConfig()
|
2017-11-25 00:38:06 +00:00
|
|
|
return True
|
|
|
|
|
2017-11-20 21:40:04 +00:00
|
|
|
def parseCommand(self, addr, authed, data):
|
2017-12-25 22:09:38 +00:00
|
|
|
global pool, MonitorPool, wholist
|
2017-11-20 21:40:04 +00:00
|
|
|
spl = data.split()
|
2017-12-03 13:10:51 +00:00
|
|
|
if addr in connections.keys():
|
|
|
|
obj = connections[addr]
|
|
|
|
else:
|
|
|
|
warning("Got connection object with no instance in the address pool")
|
|
|
|
return
|
2017-11-20 21:40:04 +00:00
|
|
|
|
|
|
|
success = lambda data: sendSuccess(addr, data)
|
|
|
|
failure = lambda data: sendFailure(addr, data)
|
|
|
|
info = lambda data: sendInfo(addr, data)
|
|
|
|
|
2017-11-21 20:16:14 +00:00
|
|
|
incUsage = lambda mode: self.incorrectUsage(addr, mode)
|
2017-11-20 21:40:04 +00:00
|
|
|
length = len(spl)
|
|
|
|
if len(spl) > 0:
|
|
|
|
cmd = spl[0]
|
|
|
|
else:
|
2017-11-21 18:41:18 +00:00
|
|
|
failure("No text was sent")
|
2017-11-20 21:40:04 +00:00
|
|
|
return
|
2017-11-21 20:16:14 +00:00
|
|
|
|
2017-11-20 21:40:04 +00:00
|
|
|
if authed == True:
|
2017-11-21 20:16:14 +00:00
|
|
|
if cmd == "help":
|
|
|
|
helpMap = []
|
|
|
|
for i in help.keys():
|
|
|
|
helpMap.append("%s: %s" % (i, help[i]))
|
|
|
|
info("\n".join(helpMap))
|
|
|
|
return
|
|
|
|
|
2017-11-23 18:39:08 +00:00
|
|
|
elif cmd == "rehash":
|
|
|
|
global config
|
|
|
|
config = helper.getConfig()
|
2017-12-03 13:10:51 +00:00
|
|
|
log("Configuration rehashed")
|
2017-11-23 18:39:08 +00:00
|
|
|
success("Configuration rehashed successfully")
|
|
|
|
|
2017-12-03 13:10:51 +00:00
|
|
|
elif cmd == "rekey":
|
|
|
|
global keyconf
|
|
|
|
keyconf = helper.getKeywordConfig()
|
|
|
|
log("Keyword configuration rehashed")
|
|
|
|
success("Keyword configuration rehashed successfully")
|
|
|
|
|
2017-12-25 22:27:09 +00:00
|
|
|
elif cmd == "savewho":
|
|
|
|
self.saveWholist()
|
|
|
|
success("Saved WHO info to file")
|
|
|
|
return
|
|
|
|
|
2017-12-03 18:34:56 +00:00
|
|
|
elif cmd == "dist":
|
|
|
|
if config["DistEnabled"]:
|
|
|
|
rtrn = run(["./dist.sh"], shell=True, stdout=PIPE)
|
2017-12-03 19:23:29 +00:00
|
|
|
if config["SendDistOutput"]:
|
|
|
|
info("Exit code: %s -- Stdout: %s" % (rtrn.returncode, rtrn.stdout))
|
|
|
|
else:
|
|
|
|
info("Exit code: %s" % rtrn.returncode)
|
2017-12-03 18:34:56 +00:00
|
|
|
else:
|
|
|
|
failure("The dist command is not enabled")
|
|
|
|
return
|
|
|
|
|
2017-11-21 20:16:14 +00:00
|
|
|
elif cmd == "pass":
|
2017-11-20 21:40:04 +00:00
|
|
|
info("You are already authenticated")
|
|
|
|
return
|
2017-11-21 20:16:14 +00:00
|
|
|
|
2017-11-20 21:40:04 +00:00
|
|
|
elif cmd == "logout":
|
|
|
|
obj.authed = False
|
|
|
|
success("Logged out")
|
|
|
|
return
|
2017-11-21 20:16:14 +00:00
|
|
|
|
|
|
|
elif cmd == "list":
|
|
|
|
poolMap = []
|
|
|
|
for i in pool.keys():
|
2017-11-23 19:11:29 +00:00
|
|
|
poolMap.append("Server: %s" % i)
|
|
|
|
for x in pool[i].keys():
|
|
|
|
poolMap.append("%s: %s" % (x, pool[i][x]))
|
|
|
|
poolMap.append("\n")
|
2017-11-21 20:16:14 +00:00
|
|
|
info("\n".join(poolMap))
|
2017-11-20 21:40:04 +00:00
|
|
|
return
|
2017-11-21 20:16:14 +00:00
|
|
|
|
2017-12-25 22:09:38 +00:00
|
|
|
elif cmd == "stats":
|
|
|
|
if length == 1:
|
|
|
|
stats = []
|
|
|
|
numChannels = 0
|
|
|
|
numWhoEntries = 0
|
|
|
|
for i in IRCPool.keys():
|
|
|
|
numChannels += len(IRCPool[i].channels)
|
|
|
|
for i in wholist.keys():
|
|
|
|
numWhoEntries += len(wholist[i].keys())
|
|
|
|
stats.append("Servers: %s" % len(IRCPool.keys()))
|
|
|
|
stats.append("Channels: %s" % numChannels)
|
|
|
|
stats.append("User records: %s" % numWhoEntries)
|
|
|
|
info("\n".join(stats))
|
|
|
|
return
|
|
|
|
|
|
|
|
elif length == 2:
|
|
|
|
stats = []
|
|
|
|
numChannels = 0
|
|
|
|
numWhoEntries = 0
|
|
|
|
|
|
|
|
failures = 0
|
|
|
|
if spl[1] in IRCPool.keys():
|
|
|
|
numChannels += len(IRCPool[spl[1]].channels)
|
|
|
|
else:
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
failures += 1
|
|
|
|
if spl[1] in wholist.keys():
|
|
|
|
numWhoEntries += len(wholist[spl[1]].keys())
|
|
|
|
else:
|
|
|
|
failure("Who entry does not exist: %s" % spl[1])
|
|
|
|
failures += 1
|
|
|
|
if failures == 2:
|
|
|
|
failure("No information found, aborting")
|
|
|
|
return
|
|
|
|
stats.append("Channels: %s" % numChannels)
|
|
|
|
stats.append("User records: %s" % numWhoEntries)
|
|
|
|
info("\n".join(stats))
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("stats")
|
|
|
|
|
2017-11-23 20:37:00 +00:00
|
|
|
elif cmd == "enable":
|
|
|
|
if length == 2:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
pool[spl[1]]["enabled"] = True
|
2017-11-24 19:16:08 +00:00
|
|
|
helper.savePool()
|
2017-11-25 19:44:03 +00:00
|
|
|
if not spl[1] in IRCPool.keys():
|
|
|
|
self.addBot(spl[1])
|
2017-11-25 20:28:49 +00:00
|
|
|
else:
|
2017-11-27 20:18:39 +00:00
|
|
|
pass
|
2017-11-23 20:37:00 +00:00
|
|
|
success("Successfully enabled bot %s" % spl[1])
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("enable")
|
|
|
|
return
|
|
|
|
|
|
|
|
elif cmd == "disable":
|
|
|
|
if length == 2:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
pool[spl[1]]["enabled"] = False
|
2017-11-24 19:16:08 +00:00
|
|
|
helper.savePool()
|
2017-11-23 20:37:00 +00:00
|
|
|
if spl[1] in IRCPool.keys():
|
2017-11-24 19:16:08 +00:00
|
|
|
if IRCPool[spl[1]].connected == True:
|
|
|
|
IRCPool[spl[1]].transport.loseConnection()
|
2017-11-25 20:26:56 +00:00
|
|
|
del IRCPool[spl[1]]
|
2017-11-23 20:37:00 +00:00
|
|
|
success("Successfully disabled bot %s" % spl[1])
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("disable")
|
|
|
|
return
|
|
|
|
|
2017-11-24 19:16:08 +00:00
|
|
|
elif cmd == "join":
|
|
|
|
if length == 3:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
if not spl[1] in IRCPool.keys():
|
|
|
|
failure("Name has no instance: %s" % spl[1])
|
|
|
|
return
|
|
|
|
IRCPool[spl[1]].join(spl[2])
|
|
|
|
success("Joined %s" % spl[2])
|
|
|
|
return
|
|
|
|
elif length == 4:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
if not spl[1] in IRCPool.keys():
|
|
|
|
failure("Name has no instance: %s" % spl[1])
|
|
|
|
return
|
|
|
|
IRCPool[spl[1]].join(spl[2], spl[3])
|
|
|
|
success("Joined %s with key %s" % (spl[2], spl[3]))
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("join")
|
2017-11-25 00:38:06 +00:00
|
|
|
return
|
2017-11-24 19:16:08 +00:00
|
|
|
|
|
|
|
elif cmd == "part":
|
|
|
|
if length == 3:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
if not spl[1] in IRCPool.keys():
|
|
|
|
failure("Name has no instance: %s" % spl[1])
|
|
|
|
return
|
|
|
|
IRCPool[spl[1]].part(spl[2])
|
|
|
|
success("Left %s" % spl[2])
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("part")
|
2017-11-25 00:38:06 +00:00
|
|
|
return
|
2017-11-24 19:16:08 +00:00
|
|
|
|
|
|
|
elif cmd == "get":
|
|
|
|
if length == 3:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
if not spl[1] in IRCPool.keys():
|
|
|
|
failure("Name has no instance: %s" % spl[1])
|
|
|
|
return
|
|
|
|
info(str(IRCPool[spl[1]].get(spl[2])))
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("get")
|
2017-11-25 00:38:06 +00:00
|
|
|
return
|
|
|
|
|
2017-12-25 19:02:17 +00:00
|
|
|
elif cmd == "who":
|
|
|
|
if length == 2:
|
|
|
|
result = self.getWho(spl[1])
|
|
|
|
rtrn = ""
|
|
|
|
for i in result.keys():
|
|
|
|
rtrn += "Matches from: %s" % i
|
|
|
|
rtrn += "\n"
|
|
|
|
for x in result[i]:
|
2017-12-25 22:09:38 +00:00
|
|
|
x = [y for y in x if not y == None]
|
|
|
|
rtrn += str((", ".join(x)))
|
2017-12-25 19:02:17 +00:00
|
|
|
rtrn += "\n"
|
|
|
|
info(rtrn)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("who")
|
|
|
|
return
|
|
|
|
|
2017-11-25 00:38:06 +00:00
|
|
|
elif cmd == "key":
|
|
|
|
if data.startswith("key add"):
|
2017-11-27 19:54:35 +00:00
|
|
|
if not data in ["key add ", "key add"] and data[3] == " ":
|
2017-11-25 00:38:06 +00:00
|
|
|
keywordsToAdd = data[8:]
|
|
|
|
keywords = keywordsToAdd.split(",")
|
|
|
|
for keyword in keywords:
|
|
|
|
rtrn = self.addKeyword(keyword)
|
|
|
|
if rtrn == "EXISTS":
|
|
|
|
failure("Keyword already exists: %s" % keyword)
|
|
|
|
elif rtrn == "ISIN":
|
|
|
|
failure("Keyword already matched: %s" % keyword)
|
|
|
|
elif rtrn == True:
|
|
|
|
success("Keyword added: %s" % keyword)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("key")
|
|
|
|
return
|
|
|
|
elif data.startswith("key del"):
|
2017-11-27 19:54:35 +00:00
|
|
|
if not data in ["key del ", "key del"] and data[3] == " ":
|
2017-11-25 00:38:06 +00:00
|
|
|
keywordsToDel = data[8:]
|
|
|
|
keywords = keywordsToDel.split(",")
|
|
|
|
for keyword in keywords:
|
|
|
|
rtrn = self.delKeyword(keyword)
|
|
|
|
if rtrn == "NOKEY":
|
|
|
|
failure("Keyword does not exist: %s" % keyword)
|
|
|
|
elif rtrn == True:
|
|
|
|
success("Keyword deleted: %s" % keyword)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("key")
|
|
|
|
return
|
2017-11-27 19:54:35 +00:00
|
|
|
if length == 4:
|
|
|
|
if spl[1] == "except":
|
2017-12-03 13:10:51 +00:00
|
|
|
if not spl[2] in keyconf["Keywords"]:
|
2017-11-27 19:54:35 +00:00
|
|
|
failure("No such keyword: %s" % spl[2])
|
|
|
|
return
|
2017-12-03 13:10:51 +00:00
|
|
|
if spl[2] in keyconf["KeywordsExcept"].keys():
|
|
|
|
if spl[3] in keyconf["KeywordsExcept"][spl[2]]:
|
2017-11-27 19:54:35 +00:00
|
|
|
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
|
2017-12-03 13:10:51 +00:00
|
|
|
keyconf["KeywordsExcept"][spl[2]] = []
|
2017-11-27 19:54:35 +00:00
|
|
|
|
2017-12-03 13:10:51 +00:00
|
|
|
keyconf["KeywordsExcept"][spl[2]].append(spl[3])
|
|
|
|
helper.saveKeywordConfig()
|
2017-11-27 19:54:35 +00:00
|
|
|
success("Successfully added exception %s for keyword %s" % (spl[3], spl[2]))
|
|
|
|
return
|
2017-12-03 19:11:06 +00:00
|
|
|
elif spl[1] == "master":
|
|
|
|
if not spl[2] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[2])
|
|
|
|
return
|
|
|
|
if spl[2] in IRCPool.keys():
|
|
|
|
if not spl[3] in IRCPool[spl[2]].channels:
|
|
|
|
info("Bot not on channel: %s" % spl[3])
|
|
|
|
config["Master"] = [spl[2], spl[3]]
|
|
|
|
helper.saveConfig()
|
|
|
|
success("Master set to %s on %s" % (spl[3], spl[2]))
|
|
|
|
return
|
2017-11-27 19:54:35 +00:00
|
|
|
elif spl[1] == "unexcept":
|
2017-12-03 13:10:51 +00:00
|
|
|
if not spl[2] in keyconf["KeywordsExcept"].keys():
|
2017-11-27 19:54:35 +00:00
|
|
|
failure("No such exception: %s" % spl[2])
|
|
|
|
return
|
2017-12-03 13:10:51 +00:00
|
|
|
if not spl[3] in keyconf["KeywordsExcept"][spl[2]]:
|
2017-11-27 19:54:35 +00:00
|
|
|
failure("Exception %s has no attribute %s" % (spl[2], spl[3]))
|
|
|
|
return
|
2017-12-03 13:10:51 +00:00
|
|
|
keyconf["KeywordsExcept"][spl[2]].remove(spl[3])
|
|
|
|
if keyconf["KeywordsExcept"][spl[2]] == []:
|
|
|
|
del keyconf["KeywordsExcept"][spl[2]]
|
|
|
|
helper.saveKeywordConfig()
|
2017-11-27 19:54:35 +00:00
|
|
|
success("Successfully removed exception %s for keyword %s" % (spl[3], spl[2]))
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("key")
|
|
|
|
return
|
2017-12-03 19:11:06 +00:00
|
|
|
elif length == 3:
|
2017-11-27 19:54:35 +00:00
|
|
|
if spl[1] == "unexcept":
|
2017-12-03 13:10:51 +00:00
|
|
|
if not spl[2] in keyconf["KeywordsExcept"].keys():
|
2017-11-27 19:54:35 +00:00
|
|
|
failure("No such exception: %s" % spl[2])
|
|
|
|
return
|
2017-12-03 13:10:51 +00:00
|
|
|
del keyconf["KeywordsExcept"][spl[2]]
|
|
|
|
helper.saveKeywordConfig()
|
2017-11-27 19:54:35 +00:00
|
|
|
success("Successfully removed exception list of %s" % spl[2])
|
|
|
|
return
|
2017-12-24 21:04:48 +00:00
|
|
|
elif spl[1] == "monitor":
|
|
|
|
if spl[2] == "on":
|
|
|
|
if not obj.addr in MonitorPool:
|
|
|
|
MonitorPool.append(obj.addr)
|
|
|
|
success("Keyword monitoring enabled")
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
failure("Keyword monitoring is already enabled")
|
|
|
|
return
|
|
|
|
elif spl[2] == "off":
|
|
|
|
if obj.addr in MonitorPool:
|
|
|
|
MonitorPool.remove(obj.addr)
|
|
|
|
success("Keyword monitoring disabled")
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
failure("Keyword monitoring is already disabled")
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("key")
|
|
|
|
return
|
2017-12-03 19:11:06 +00:00
|
|
|
else:
|
|
|
|
incUsage("key")
|
2017-12-24 21:04:48 +00:00
|
|
|
return
|
2017-12-03 19:11:06 +00:00
|
|
|
elif length == 2:
|
2017-11-27 19:54:35 +00:00
|
|
|
if spl[1] == "show":
|
2017-12-03 13:10:51 +00:00
|
|
|
info(",".join(keyconf["Keywords"]))
|
2017-11-27 19:54:35 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
elif spl[1] == "showexcept":
|
|
|
|
exceptMap = []
|
2017-12-03 13:10:51 +00:00
|
|
|
for i in keyconf["KeywordsExcept"].keys():
|
2017-11-27 19:54:35 +00:00
|
|
|
exceptMap.append("Key: %s" % i)
|
2017-12-03 13:10:51 +00:00
|
|
|
exceptMap.append("%s: %s" % (i, ",".join(keyconf["KeywordsExcept"][i])))
|
2017-11-27 19:54:35 +00:00
|
|
|
exceptMap.append("\n")
|
|
|
|
info("\n".join(exceptMap))
|
|
|
|
return
|
2017-12-03 19:11:06 +00:00
|
|
|
elif spl[1] == "master":
|
2017-11-25 00:38:06 +00:00
|
|
|
info(" - ".join(config["Master"]))
|
|
|
|
return
|
2017-12-24 21:04:48 +00:00
|
|
|
elif spl[1] == "monitor":
|
|
|
|
if obj.addr in MonitorPool:
|
|
|
|
info("Keyword monitoring is enabled on this connection")
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
info("Keyword monitoring is disabled on this connection")
|
|
|
|
return
|
2017-11-25 00:38:06 +00:00
|
|
|
else:
|
|
|
|
incUsage("key")
|
|
|
|
return
|
|
|
|
|
2017-12-25 19:02:17 +00:00
|
|
|
else:
|
|
|
|
incUsage("key")
|
|
|
|
return
|
|
|
|
|
2017-11-23 18:45:18 +00:00
|
|
|
elif cmd == "add":
|
2017-11-21 20:16:14 +00:00
|
|
|
if length == 6:
|
|
|
|
|
|
|
|
if spl[1] in pool.keys():
|
|
|
|
failure("Name already exists: %s" % spl[1])
|
2017-11-20 21:40:04 +00:00
|
|
|
return
|
2017-11-21 20:16:14 +00:00
|
|
|
|
|
|
|
protocol = spl[4].lower()
|
|
|
|
|
|
|
|
if not protocol in ["ssl", "plain"]:
|
|
|
|
incUsage("connect")
|
2017-11-20 21:40:04 +00:00
|
|
|
return
|
2017-11-21 20:16:14 +00:00
|
|
|
|
2017-11-23 19:19:48 +00:00
|
|
|
try:
|
|
|
|
int(spl[3])
|
|
|
|
except:
|
|
|
|
failure("Port must be an integer, not %s" % spl[3])
|
|
|
|
return
|
|
|
|
|
2017-11-23 20:37:00 +00:00
|
|
|
pool[spl[1]] = { "host": spl[2],
|
2017-11-21 20:16:14 +00:00
|
|
|
"port": spl[3],
|
|
|
|
"protocol": protocol,
|
2017-11-23 20:37:00 +00:00
|
|
|
"bind": None,
|
|
|
|
"timeout": 30,
|
2017-11-21 20:16:14 +00:00
|
|
|
"nickname": spl[5],
|
2017-11-25 19:20:23 +00:00
|
|
|
"username": config["Default"]["username"],
|
2017-11-23 19:11:29 +00:00
|
|
|
"realname": None,
|
|
|
|
"userinfo": None,
|
|
|
|
"finger": None,
|
|
|
|
"version": None,
|
|
|
|
"source": None,
|
2017-11-25 19:48:20 +00:00
|
|
|
"autojoin": [],
|
2017-11-25 19:20:23 +00:00
|
|
|
"authtype": config["Default"]["authtype"],
|
|
|
|
"password": config["Default"]["password"],
|
2017-11-23 20:37:00 +00:00
|
|
|
"authentity": "NickServ",
|
|
|
|
"key": config["ListenerKey"],
|
|
|
|
"certificate": config["ListenerCertificate"],
|
|
|
|
"enabled": config["ConnectOnCreate"],
|
2017-11-21 20:16:14 +00:00
|
|
|
}
|
2017-11-23 20:37:00 +00:00
|
|
|
if config["ConnectOnCreate"] == True:
|
|
|
|
self.addBot(spl[1])
|
2017-11-21 20:16:14 +00:00
|
|
|
success("Successfully created bot")
|
|
|
|
self.savePool()
|
|
|
|
return
|
|
|
|
else:
|
2017-11-23 18:45:18 +00:00
|
|
|
incUsage("add")
|
|
|
|
return
|
|
|
|
|
|
|
|
elif cmd == "del":
|
|
|
|
if length == 2:
|
|
|
|
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
del pool[spl[1]]
|
2017-11-23 20:37:00 +00:00
|
|
|
if spl[1] in IRCPool.keys():
|
2017-11-24 19:16:08 +00:00
|
|
|
if IRCPool[spl[1]].connected == True:
|
|
|
|
IRCPool[spl[1]].transport.loseConnection()
|
2017-11-23 20:37:00 +00:00
|
|
|
del IRCPool[spl[1]]
|
2017-11-23 18:45:18 +00:00
|
|
|
success("Successfully removed bot")
|
|
|
|
self.savePool()
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
incUsage("del")
|
2017-11-21 20:16:14 +00:00
|
|
|
return
|
|
|
|
|
2017-11-23 19:11:29 +00:00
|
|
|
elif cmd == "mod":
|
2017-11-23 20:37:00 +00:00
|
|
|
toUnset = False
|
2017-11-23 19:11:29 +00:00
|
|
|
if length == 2:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
optionMap = ["Viewing options for %s" % spl[1]]
|
|
|
|
for i in pool[spl[1]].keys():
|
|
|
|
optionMap.append("%s: %s" % (i, pool[spl[1]][i]))
|
|
|
|
info("\n".join(optionMap))
|
|
|
|
return
|
|
|
|
|
|
|
|
elif length == 3:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
if not spl[2] in pool[spl[1]].keys():
|
|
|
|
failure("No such key: %s" % spl[2])
|
|
|
|
return
|
|
|
|
info("%s: %s" % (spl[2], pool[spl[1]][spl[2]]))
|
|
|
|
return
|
|
|
|
|
|
|
|
elif length == 4:
|
|
|
|
if not spl[1] in pool.keys():
|
|
|
|
failure("Name does not exist: %s" % spl[1])
|
|
|
|
return
|
|
|
|
if not spl[2] in pool[spl[1]].keys():
|
|
|
|
failure("No such key: %s" % spl[2])
|
|
|
|
return
|
2017-11-23 20:37:00 +00:00
|
|
|
if spl[2] in ["port", "timeout"]:
|
2017-11-23 19:19:48 +00:00
|
|
|
try:
|
|
|
|
int(spl[3])
|
|
|
|
except:
|
2017-11-23 20:37:00 +00:00
|
|
|
failure("Value must be an integer, not %s" % spl[3])
|
2017-11-23 19:19:48 +00:00
|
|
|
return
|
|
|
|
if spl[2] == "protocol":
|
|
|
|
if not spl[3] in ["ssl", "plain"]:
|
|
|
|
failure("Protocol must be ssl or plain, not %s" % spl[3])
|
|
|
|
return
|
2017-11-23 19:11:29 +00:00
|
|
|
if spl[3] == pool[spl[1]][spl[2]]:
|
|
|
|
failure("Value already exists: %s" % spl[3])
|
|
|
|
return
|
2017-11-23 20:37:00 +00:00
|
|
|
|
|
|
|
if spl[3].lower() in ["none", "nil"]:
|
|
|
|
spl[3] = None
|
|
|
|
toUnset = True
|
|
|
|
|
|
|
|
if spl[2] == "authtype":
|
2017-11-25 19:29:48 +00:00
|
|
|
if not toUnset:
|
|
|
|
if not spl[3] in ["sp", "ns"]:
|
|
|
|
failure("Authtype must be sp or ns, not %s" % spl[3])
|
|
|
|
return
|
2017-11-23 20:37:00 +00:00
|
|
|
if spl[2] == "enabled":
|
|
|
|
failure("Use the enable and disable commands to manage this")
|
|
|
|
return
|
2017-11-25 19:48:20 +00:00
|
|
|
if spl[2] == "autojoin":
|
|
|
|
spl[3] = spl[3].split(",")
|
2017-11-23 20:37:00 +00:00
|
|
|
|
2017-11-23 19:11:29 +00:00
|
|
|
pool[spl[1]][spl[2]] = spl[3]
|
2017-11-24 19:16:08 +00:00
|
|
|
if spl[1] in IRCPool.keys():
|
|
|
|
IRCPool[spl[1]].refresh()
|
2017-11-23 20:37:00 +00:00
|
|
|
self.savePool()
|
|
|
|
if toUnset:
|
2017-11-25 19:26:13 +00:00
|
|
|
success("Successfully unset key %s on %s" % (spl[2], spl[1]))
|
2017-11-23 20:37:00 +00:00
|
|
|
else:
|
|
|
|
success("Successfully set key %s to %s on %s" % (spl[2], spl[3], spl[1]))
|
2017-11-23 19:11:29 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
else:
|
|
|
|
incUsage("mod")
|
2017-11-25 00:38:06 +00:00
|
|
|
return
|
2017-11-23 19:11:29 +00:00
|
|
|
|
2017-11-21 20:16:14 +00:00
|
|
|
else:
|
|
|
|
incUsage(None)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
if cmd == "pass" and length == 2:
|
2017-11-23 18:32:30 +00:00
|
|
|
if spl[1] == config["Password"]:
|
2017-11-21 20:16:14 +00:00
|
|
|
success("Authenticated successfully")
|
|
|
|
obj.authed = True
|
|
|
|
return
|
2017-11-20 21:40:04 +00:00
|
|
|
else:
|
2017-11-21 20:16:14 +00:00
|
|
|
failure("Password incorrect")
|
|
|
|
obj.transport.loseConnection()
|
2017-11-20 21:40:04 +00:00
|
|
|
return
|
|
|
|
else:
|
2017-11-21 20:16:14 +00:00
|
|
|
incUsage(None)
|
2017-11-20 21:40:04 +00:00
|
|
|
return
|
|
|
|
|
2017-11-19 14:46:42 +00:00
|
|
|
if __name__ == "__main__":
|
2017-11-20 19:53:25 +00:00
|
|
|
helper = Helper()
|
|
|
|
config = helper.getConfig()
|
2017-12-03 13:10:51 +00:00
|
|
|
keyconf = helper.getKeywordConfig()
|
2017-11-21 20:16:14 +00:00
|
|
|
pool = helper.getPool()
|
|
|
|
help = helper.getHelp()
|
2017-11-28 19:19:27 +00:00
|
|
|
|
2017-12-25 22:27:09 +00:00
|
|
|
wholist = helper.getWholist()
|
|
|
|
|
2017-11-23 20:37:00 +00:00
|
|
|
for i in pool.keys():
|
|
|
|
if pool[i]["enabled"] == True:
|
|
|
|
helper.addBot(i)
|
2017-11-19 14:46:42 +00:00
|
|
|
|
|
|
|
listener = BaseFactory()
|
2017-11-23 18:32:30 +00:00
|
|
|
if config["UseSSL"] == True:
|
|
|
|
reactor.listenSSL(config["Port"], listener, DefaultOpenSSLContextFactory(config["ListenerKey"], config["ListenerCertificate"]), interface=config["BindAddress"])
|
|
|
|
log("Threshold running with SSL on %s:%s" % (config["BindAddress"], config["Port"]))
|
2017-11-19 14:46:42 +00:00
|
|
|
else:
|
2017-11-23 18:32:30 +00:00
|
|
|
reactor.listenTCP(config["Port"], listener, interface=config["BindAddress"])
|
|
|
|
log("Threshold running on %s:%s" % (config["BindAddress"], config["Port"]))
|
2017-11-19 14:46:42 +00:00
|
|
|
|
|
|
|
reactor.run()
|