Fix LIST handling and message parsing
* Always use simple LIST syntax if it succeeded once after a failed complex query * Reject asking for a LIST twice * Quickly discard any ISUPPORT messages that don't contain things we need to use * Detect the server name and drop any messages from the server
This commit is contained in:
parent
f34de8940f
commit
b4fa747853
86
core/bot.py
86
core/bot.py
|
@ -106,22 +106,26 @@ class IRCBot(IRCClient):
|
|||
self.realname = alias["realname"]
|
||||
self.username = alias["nick"]+"/"+relay["net"]
|
||||
self.password = main.config["Relay"]["Password"]
|
||||
self.userinfo = None
|
||||
self.fingerReply = None
|
||||
self.versionName = None
|
||||
self.versionNum = None
|
||||
self.versionEnv = None
|
||||
self.sourceURL = None
|
||||
self.userinfo = None #
|
||||
self.fingerReply = None #
|
||||
self.versionName = None # don't tell anyone information about us
|
||||
self.versionNum = None #
|
||||
self.versionEnv = None #
|
||||
self.sourceURL = None #
|
||||
|
||||
self._getWho = {} # LoopingCall objects -- needed to be able to stop them
|
||||
|
||||
self._tempWho = {} # Temporary storage for gathering WHO info
|
||||
self._tempNames = {} # Temporary storage for gathering NAMES info
|
||||
self._tempList = ([], []) # Temporary storage for gathering LIST info
|
||||
self.listOngoing = False
|
||||
self.listRetried = False
|
||||
self._tempWho = {} # temporary storage for gathering WHO info
|
||||
self._tempNames = {} # temporary storage for gathering NAMES info
|
||||
self._tempList = ([], []) # temporary storage for gathering LIST info
|
||||
self.listOngoing = False # we are currently receiving a LIST
|
||||
self.listRetried = False # we asked and got nothing so asked again
|
||||
self.listAttempted = False # we asked for a list
|
||||
self.listSimple = False # after asking again we got the list, so
|
||||
# use the simple syntax from now on
|
||||
|
||||
self.chanlimit = 0
|
||||
self.servername = None
|
||||
|
||||
def joinChannels(self, channels):
|
||||
sleeptime = 0.0
|
||||
|
@ -151,11 +155,13 @@ class IRCBot(IRCClient):
|
|||
if cast[i] == "": # a dictionary that changes length with each iteration
|
||||
del cast[i]
|
||||
if "muser" in cast.keys():
|
||||
if cast["muser"] == self.servername:
|
||||
return
|
||||
if "channel" in cast.keys():
|
||||
if cast["channel"] == "*":
|
||||
return
|
||||
if not {"nick", "ident", "host"}.issubset(set(cast.keys())):
|
||||
cast["nick"], cast["ident"], cast["host"] = parsen(cast["muser"])
|
||||
# additional checks here to see if it's a server -- irc.example.net
|
||||
# discard if it is
|
||||
#if not cast["type"] in ["nick", "kick", "quit", "part", "join"]:
|
||||
# del cast["muser"]
|
||||
if set(["nick", "ident", "host", "msg"]).issubset(set(cast)):
|
||||
if "msg" in cast.keys():
|
||||
if cast["ident"] == "znc" and cast["host"] == "znc.in":
|
||||
|
@ -166,6 +172,7 @@ class IRCBot(IRCClient):
|
|||
del cast["host"]
|
||||
del cast["channel"]
|
||||
if "Disconnected from IRC" in cast["msg"]:
|
||||
log("ZNC disconnected on %s - %i" (self.net, self.num))
|
||||
self.connected = False
|
||||
if not cast["type"] in ["query", "self", "highlight", "znc", "who"]:
|
||||
if "channel" in cast.keys() and not cast["type"] == "mode": # don't handle modes here
|
||||
|
@ -323,10 +330,16 @@ class IRCBot(IRCClient):
|
|||
newNicklist.append(f)
|
||||
userinfo.initialNames(self.net, nicklist[0], newNicklist)
|
||||
|
||||
def myInfo(self, servername, version, umodes, cmodes):
|
||||
self.servername = servername
|
||||
|
||||
def _list(self, noargs):
|
||||
d = Deferred()
|
||||
self._tempList = ([], [])
|
||||
self._tempList[0].append(d)
|
||||
if self.listSimple:
|
||||
self.sendLine("LIST")
|
||||
return d
|
||||
if noargs:
|
||||
self.sendLine("LIST")
|
||||
else:
|
||||
|
@ -334,10 +347,19 @@ class IRCBot(IRCClient):
|
|||
return d
|
||||
|
||||
def list(self, noargs=False):
|
||||
if not self.listAttempted:
|
||||
self.listAttempted = True
|
||||
else:
|
||||
debug("List request dropped, already asked for LIST - %s - %i" % (self.net, self.num))
|
||||
return
|
||||
if not self.listOngoing:
|
||||
self._list(noargs).addCallback(self.got_list)
|
||||
else:
|
||||
debug("List request dropped, already ongoing - %s - %i" % (self.net, self.num))
|
||||
return
|
||||
|
||||
def irc_RPL_LISTSTART(self, prefix, params):
|
||||
self.listAttempted = False
|
||||
self.listOngoing = True
|
||||
|
||||
def irc_RPL_LIST(self, prefix, params):
|
||||
|
@ -359,12 +381,16 @@ class IRCBot(IRCClient):
|
|||
if noResults:
|
||||
if not self.listRetried:
|
||||
self.list(True)
|
||||
self.listRetried = True
|
||||
else:
|
||||
warn("List still empty after retry: %s - %i" % (net, num))
|
||||
self.listRetried = False
|
||||
return
|
||||
else:
|
||||
self.listRetried = False
|
||||
if self.listRetried:
|
||||
self.listRetried = False
|
||||
debug("List received after retry - defaulting to simple list syntax")
|
||||
self.listSimple = True
|
||||
|
||||
def got_list(self, listinfo):
|
||||
if len(listinfo) == 0: # probably ngircd not supporting LIST >0
|
||||
|
@ -372,19 +398,33 @@ class IRCBot(IRCClient):
|
|||
chankeep.initialList(self.net, self.num, listinfo, self.chanlimit)
|
||||
|
||||
def isupport(self, options):
|
||||
for i in options:
|
||||
interested = ("CHANLIMIT", "MAXCHANNELS")
|
||||
if not any((x for x in options if any(y in x for y in interested))):
|
||||
return # check if any of interested is in any of options, some networks
|
||||
chanlimit = None # call isupport() more than once, so discard swiftly anything
|
||||
for i in options: # we don't care about
|
||||
if i.startswith("CHANLIMIT"):
|
||||
if ":" in i:
|
||||
split = i.split(":")
|
||||
if len(split) >= 2:
|
||||
chanlimit = split[1]
|
||||
try:
|
||||
self.chanlimit = int(chanlimit)
|
||||
return
|
||||
except TypeError:
|
||||
warn("Invalid CHANLIMIT: %s" % i)
|
||||
break
|
||||
elif i.startswith("MAXCHANNELS"):
|
||||
if "=" in i:
|
||||
split = i.split("=")
|
||||
if len(split) == 2:
|
||||
chanlimit = split[1]
|
||||
break
|
||||
if chanlimit:
|
||||
try:
|
||||
self.chanlimit = int(chanlimit)
|
||||
except TypeError:
|
||||
warn("Invalid chanlimit: %s" % i)
|
||||
if self.num == 1: # Only one instance should do a list, so
|
||||
self.list() # why not this one? :P
|
||||
if self.chanlimit:
|
||||
self.list() # why not this one? :P
|
||||
else:
|
||||
debug("Aborting LIST due to bad chanlimit")
|
||||
self.checkChannels()
|
||||
|
||||
#twisted sucks so i have to do this to actually get the user info
|
||||
|
|
|
@ -27,7 +27,6 @@ def getChanFree(net, new):
|
|||
name = net+str(i)
|
||||
chanfree[i] = main.IRCPool[name].chanlimit-len(main.IRCPool[name].channels)
|
||||
chanlimits.add(main.IRCPool[name].chanlimit)
|
||||
|
||||
if not len(chanlimits) == 1:
|
||||
error("Network %s has servers with different CHANMAX values" % net)
|
||||
return False
|
||||
|
@ -39,7 +38,6 @@ def emptyChanAllocate(net, flist, relay, new):
|
|||
return
|
||||
for i in new:
|
||||
chanfree[0][i] = chanfree[1]
|
||||
print("chanfree", chanfree)
|
||||
allocated = {}
|
||||
toalloc = len(flist)
|
||||
if toalloc > sum(chanfree[0].values()):
|
||||
|
|
|
@ -7,7 +7,7 @@ from utils.logging.debug import debug
|
|||
from utils.parsing import parsen
|
||||
|
||||
def getWhoSingle(name, query):
|
||||
result = main.r.sscan("live.who."+name, 0, query, count=-1)
|
||||
result = main.r.sscan("live.who."+name, 0, query, count=999999)
|
||||
if result[1] == []:
|
||||
return None
|
||||
return (i.decode() for i in result[1])
|
||||
|
|
Loading…
Reference in New Issue