Implement join/part, channel tracking and retrieving variables from IRCBot classes at runtime

This commit is contained in:
Mark Veidemanis 2017-11-24 19:16:08 +00:00
parent 0912ac71cb
commit 73e16aebae
2 changed files with 108 additions and 30 deletions

View File

@ -4,6 +4,8 @@
"add": "add <name> <address> <port> <ssl|plain> <nickname>", "add": "add <name> <address> <port> <ssl|plain> <nickname>",
"del": "del <name>", "del": "del <name>",
"mod": "mod <name> [<key>] [<value>]", "mod": "mod <name> [<key>] [<value>]",
"get": "get <name> <variable>",
"join": "join <name> <channel> [<key>]",
"enable": "enable <name", "enable": "enable <name",
"disable": "disable <name>", "disable": "disable <name>",
"list": "list", "list": "list",

132
threshold
View File

@ -1,5 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.internet.ssl import DefaultOpenSSLContextFactory from twisted.internet.ssl import DefaultOpenSSLContextFactory
from twisted.internet.protocol import Protocol, Factory from twisted.internet.protocol import Protocol, Factory
from twisted.internet.endpoints import SSL4ClientEndpoint, TCP4ClientEndpoint, connectProtocol from twisted.internet.endpoints import SSL4ClientEndpoint, TCP4ClientEndpoint, connectProtocol
@ -39,6 +40,9 @@ def sendInfo(addr, data):
class IRCBot(IRCClient): class IRCBot(IRCClient):
def __init__(self, name): def __init__(self, name):
self.connected = False
self.channels = []
self.name = name self.name = name
instance = pool[name] instance = pool[name]
@ -64,7 +68,7 @@ class IRCBot(IRCClient):
self.password = instance["password"] self.password = instance["password"]
def refresh(self): def refresh(self):
instance = pool[name] instance = pool[self.name]
if not instance["nickname"] == self.nickname: if not instance["nickname"] == self.nickname:
self.nickname = instance["nickname"] self.nickname = instance["nickname"]
self.setNick(self.nickname) self.setNick(self.nickname)
@ -76,6 +80,13 @@ class IRCBot(IRCClient):
self.versionEnv = None self.versionEnv = None
self.sourceURL = instance["source"] self.sourceURL = instance["source"]
def get(self, var):
try:
result = getattr(self, var)
except AttributeError:
result = None
return result
def sanitize(self, user): def sanitize(self, user):
user = user.replace("!", "") user = user.replace("!", "")
user = user.replace("~", "") user = user.replace("~", "")
@ -99,36 +110,12 @@ class IRCBot(IRCClient):
self.setNick(self._attemptedNick) self.setNick(self._attemptedNick)
def irc_ERR_PASSWDMISMATCH(self, prefix, params): def irc_ERR_PASSWDMISMATCH(self, prefix, params):
ircLog(self.ident, "Password mismatch") log("%s: password mismatch" % self.name)
manager.handleWrongPassword(self.ident, prefix, params) helper.sendAll("%s: password mismatch" % self.name)
def irc_RPL_NAMREPLY(self, prefix, params):
channel = params[2]
nicklist = params[3].split(' ')
if channel not in self._names:
return
n = self._names[channel][1]
n += nicklist
def irc_RPL_ENDOFNAMES(self, prefix, params):
channel = params[1]
if channel not in self._names:
return
callbacks, namelist = self._names[channel]
for cb in callbacks:
cb.callback((channel, namelist))
del self._names[channel]
def got_names(self, nicklist):
ncklist = []
for i in nicklist[1]:
ncklist.append(self.sanitize(i))
self.nameslist[nicklist[0]] = ncklist
def who(self, channel): def who(self, channel):
channel = channel channel = channel
d = defer.Deferred() d = Deferred()
if channel not in self._who: if channel not in self._who:
self._who[channel] = ([], {}) self._who[channel] = ([], {})
self._who[channel][0].append(d) self._who[channel][0].append(d)
@ -161,12 +148,37 @@ class IRCBot(IRCClient):
self.wholist[whoinfo[0]] = whoinfo[1] self.wholist[whoinfo[0]] = whoinfo[1]
def signedOn(self): def signedOn(self):
self.connected = True
if self.authtype == "ns": if self.authtype == "ns":
self.msg(self.authentity, "IDENTIFY %s" % self.nspass) self.msg(self.authentity, "IDENTIFY %s" % self.nspass)
def joined(self, channel): def joined(self, channel):
if not channel in self.channels:
self.channels.append(channel)
self.who(channel).addCallback(self.got_who) self.who(channel).addCallback(self.got_who)
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)
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))
class Base(Protocol): class Base(Protocol):
def __init__(self, addr): def __init__(self, addr):
self.addr = addr self.addr = addr
@ -258,9 +270,16 @@ class Helper(object):
sendFailure(addr, "Usage: " + help[mode]) sendFailure(addr, "Usage: " + help[mode])
return return
def sendAll(self, data):
global connections
for i in connections:
connections[i].send(data)
return
def addBot(self, name): def addBot(self, name):
global IRCPool global IRCPool
instance = pool[name] instance = pool[name]
log("Started bot %s to %s:%s protocol %s nickname %s" % (name, instance["host"], instance["port"], instance["protocol"], instance["nickname"]))
if instance["protocol"] == "plain": if instance["protocol"] == "plain":
if instance["bind"] == None: if instance["bind"] == None:
point = TCP4ClientEndpoint(reactor, instance["host"], int(instance["port"]), timeout=int(instance["timeout"])) point = TCP4ClientEndpoint(reactor, instance["host"], int(instance["port"]), timeout=int(instance["timeout"]))
@ -345,6 +364,7 @@ class Helper(object):
failure("Name does not exist: %s" % spl[1]) failure("Name does not exist: %s" % spl[1])
return return
pool[spl[1]]["enabled"] = True pool[spl[1]]["enabled"] = True
helper.savePool()
self.addBot(spl[1]) self.addBot(spl[1])
success("Successfully enabled bot %s" % spl[1]) success("Successfully enabled bot %s" % spl[1])
return return
@ -358,7 +378,9 @@ class Helper(object):
failure("Name does not exist: %s" % spl[1]) failure("Name does not exist: %s" % spl[1])
return return
pool[spl[1]]["enabled"] = False pool[spl[1]]["enabled"] = False
helper.savePool()
if spl[1] in IRCPool.keys(): if spl[1] in IRCPool.keys():
if IRCPool[spl[1]].connected == True:
IRCPool[spl[1]].transport.loseConnection() IRCPool[spl[1]].transport.loseConnection()
success("Successfully disabled bot %s" % spl[1]) success("Successfully disabled bot %s" % spl[1])
return return
@ -366,6 +388,57 @@ class Helper(object):
incUsage("disable") incUsage("disable")
return return
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")
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")
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")
elif cmd == "add": elif cmd == "add":
if length == 6: if length == 6:
@ -421,6 +494,7 @@ class Helper(object):
return return
del pool[spl[1]] del pool[spl[1]]
if spl[1] in IRCPool.keys(): if spl[1] in IRCPool.keys():
if IRCPool[spl[1]].connected == True:
IRCPool[spl[1]].transport.loseConnection() IRCPool[spl[1]].transport.loseConnection()
del IRCPool[spl[1]] del IRCPool[spl[1]]
success("Successfully removed bot") success("Successfully removed bot")
@ -486,6 +560,8 @@ class Helper(object):
return return
pool[spl[1]][spl[2]] = spl[3] pool[spl[1]][spl[2]] = spl[3]
if spl[1] in IRCPool.keys():
IRCPool[spl[1]].refresh()
self.savePool() self.savePool()
if toUnset: if toUnset:
success("Successfully unset key %s on %s" % (spl[2], spl[3], spl[1])) success("Successfully unset key %s on %s" % (spl[2], spl[3], spl[1]))