diff --git a/core/bot.py b/core/bot.py index 73e18f8..e2df83e 100644 --- a/core/bot.py +++ b/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 diff --git a/modules/chankeep.py b/modules/chankeep.py index 43a3d32..d9dd94c 100644 --- a/modules/chankeep.py +++ b/modules/chankeep.py @@ -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()): diff --git a/modules/userinfo.py b/modules/userinfo.py index c8c46cb..b903e80 100644 --- a/modules/userinfo.py +++ b/modules/userinfo.py @@ -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])