def __init__(self, ircd, name): if not isValidChannelName(name): raise InvalidChannelNameError self.ircd = ircd self.name = name[:self.ircd.config.get("channel_name_length", 64)] self.users = WeakKeyDictionary() self.modes = {} self.existedSince = now() self.topic = "" self.topicSetter = "" self.topicTime = now() self._metadata = CaseInsensitiveDictionary() self.cache = {}
def load(self): self.targetIndex = CaseInsensitiveDictionary() # We'll run a cleaner every minute. The reason we do this is that, since there can be multiple # notified users for a target, the index is implemented as a CaseInsensitiveDictionary pointing # to WeakSets as opposed to simply a CaseInsensitiveDictionary(WeakValueDictionary). Because of # this, we'll need to check for empty WeakSets on occasion and garbage-collect them to prevent # memory getting full. self.indexCleaner = LoopingCall(self.cleanIndex) self.indexCleaner.start(60, now=False) if "unloading-monitor" in self.ircd.dataCache: del self.ircd.dataCache["unloading-monitor"] return if "cap-add" in self.ircd.functionCache: self.ircd.functionCache["cap-add"]("metadata-notify")
def __init__(self, ircd, ip, uuid=None, host=None): self.ircd = ircd self.uuid = ircd.createUUID() if uuid is None else uuid registrationTimeout = self.ircd.config.get("user_registration_timeout", 10) self.nick = None self.ident = None if ip[0] == ":": # Normalize IPv6 address for IRC ip = "0{}".format(ip) if host is None: self.realHost = ip else: self.realHost = host self.ip = ip self._hostStack = [] self._hostsByType = {} self.gecos = None self._metadata = CaseInsensitiveDictionary() self.cache = {} self.channels = [] self.modes = {} self.connectedSince = now() self.nickSince = now() self.idleSince = now() self._registerHolds = set(("connection", "dns", "NICK", "USER")) self.disconnectedDeferred = Deferred() self._messageBatches = {} self._errorBatchName = None self._errorBatch = [] self.ircd.users[self.uuid] = self self.localOnly = False self.secureConnection = False self._pinger = LoopingCall(self._ping) self._registrationTimeoutTimer = reactor.callLater( registrationTimeout, self._timeoutRegistration) self._connectHandlerTimer = None self._startDNSResolving(registrationTimeout)
def __init__(self, config, options = None, sslCert = None): reactor.addSystemEventTrigger("before", "shutdown", self.cleanup) self.dead = False self.config = config self.version = "txircd-{}".format(__version__) self.created = now() self.servers = CaseInsensitiveDictionary() self.users = CaseInsensitiveDictionary() self.userid = {} self.channels = CaseInsensitiveDictionary() self.peerConnections = {} self.ssl_cert = sslCert self.client_ports = {} self.server_ports = {} self.modules = {} self.module_abilities = {} self.actions = { "connect": [], "register": [], "welcome": [], "join": [], "joinmessage": [], "nick": [], "quit": [], "topic": [], "mode": [], "nameslistentry": [], "chancreate": [], "chandestroy": [], "commandextra": [], "commandunknown": [], "commandpermission": [], "metadataupdate": [], "recvdata": [], "senddata": [], "netmerge": [], "netsplit": [] } self.commands = {} self.channel_modes = [{}, {}, {}, {}] self.channel_mode_type = {} self.user_modes = [{}, {}, {}, {}] self.user_mode_type = {} self.prefixes = {} self.prefix_symbols = {} self.prefix_order = [] self.server_commands = {} self.module_data_cache = {} self.server_factory = None self.common_modules = set() log.msg("Loading module data...") try: with open("data.yaml", "r") as dataFile: self.serialized_data = yaml.safe_load(dataFile) if self.serialized_data is None: self.serialized_data = {} except IOError: self.serialized_data = {} self.isupport = {} self.usercount = { "localmax": 0, "globalmax": 0 } log.msg("Loading configuration...") self.servconfig = {} if not options: options = {} self.load_options(options) self.name = self.servconfig["server_name"] log.msg("Loading modules...") self.all_module_load() self.save_serialized_deferred = None self.autoconnect_servers = LoopingCall(self.server_autoconnect) self.autoconnect_servers.start(60, now=False) # The server factory isn't added to here yet # Fill in the default ISUPPORT dictionary once config and modules are loaded, since some values depend on those self.isupport["CASEMAPPING"] = "rfc1459" self.isupport["CHANMODES"] = ",".join(["".join(modedict.keys()) for modedict in self.channel_modes]) self.isupport["CHANNELLEN"] = "64" self.isupport["CHANTYPES"] = "#" self.isupport["MODES"] = 20 self.isupport["NETWORK"] = self.servconfig["server_network_name"] self.isupport["NICKLEN"] = "32" self.isupport["PREFIX"] = "({}){}".format("".join(self.prefix_order), "".join([self.prefixes[mode][0] for mode in self.prefix_order])) self.isupport["STATUSMSG"] = "".join([self.prefixes[mode][0] for mode in self.prefix_order]) self.isupport["TOPICLEN"] = "316" self.isupport["USERMODES"] = ",".join(["".join(modedict.keys()) for modedict in self.user_modes])
def __init__(self): self.banList = CaseInsensitiveDictionary()
def __init__(self): self.exceptList = CaseInsensitiveDictionary()
def __init__(self): self.history = CaseInsensitiveDictionary()
class Logger(Module): # This is to help save from excessive disk I/O by holding the log files instead of constantly opening/flushing/closing them logfiles = CaseInsensitiveDictionary() def timePrefix(self): nowtime = now() return "[{:02d}:{:02d}:{:02d}]".format(nowtime.hour, nowtime.minute, nowtime.second) def writeLog(self, chan, line): line = "{} {}\n".format(self.timePrefix(), line) if chan.name not in self.logfiles: self.logfiles[chan.name] = DailyLogFile( chan.name, self.ircd.servconfig["app_log_dir"]) logFile = self.logfiles[chan.name] if logFile.shouldRotate(): logFile.rotate() logFile.write(line) def logMsg(self, cmd, data): if cmd in ["PRIVMSG", "NOTICE"]: if "targetchan" not in data or not data["targetchan"]: return user = data["user"] message = data["message"] if cmd == "PRIVMSG": if message[0:7] == "\x01ACTION": message = data["message"][8:] if message[-1] == "\x01": message = message[:-1] for index, chan in enumerate(data["targetchan"]): prefix = self.ircd.prefixes[ chan.users[user] [0]][0] if user in chan.users and chan.users[ user] else "" if data["chanmod"][index]: self.writeLog( chan, "*({}#) {}{} {}".format( data["chanmod"][index], prefix, user.nickname, message)) else: self.writeLog( chan, "* {}{} {}".format(prefix, user.nickname, message)) else: for index, chan in enumerate(data["targetchan"]): prefix = self.ircd.prefixes[ chan.users[user] [0]][0] if user in chan.users and chan.users[ user] else "" if data["chanmod"][index]: self.writeLog( chan, "<{}#:{}{}> {}".format(data["chanmod"][index], prefix, user.nickname, message)) else: self.writeLog( chan, "<{}{}> {}".format(prefix, user.nickname, message)) elif cmd == "NOTICE": for index, chan in enumerate(data["targetchan"]): prefix = self.ircd.prefixes[chan.users[user][0]][ 0] if user in chan.users and chan.users[user] else "" if data["chanmod"][index]: self.writeLog( chan, "-{}#:{}{}- {}".format(data["chanmod"][index], prefix, user.nickname, message)) else: self.writeLog( chan, "-{}{}- {}".format(prefix, user.nickname, message)) elif cmd == "PART": if "reason" in data: for chan in data["targetchan"]: self.writeLog( chan, "< {} has left the channel: {}".format( data["user"].nickname, data["reason"])) else: for chan in data["targetchan"]: self.writeLog( chan, "< {} has left the channel".format( data["user"].nickname)) elif cmd == "KICK": self.writeLog( data["targetchan"], "< {} was kicked by {} ({})".format( data["targetuser"].nickname, data["user"].nickname, data["reason"])) def logJoin(self, user, channel): self.writeLog(channel, "> {} has joined the channel".format(user.nickname)) def logNick(self, user, oldNick): for cdata in self.ircd.channels.itervalues(): if user in cdata.users: self.writeLog( cdata, "! {} is now known as {}".format(oldNick, user.nickname)) def logQuit(self, user, reason): for cdata in self.ircd.channels.itervalues(): if user in cdata.users: self.writeLog( cdata, "< {} has quit: {}".format(user.nickname, reason)) def logTopic(self, channel, topic, setter): self.writeLog( channel, "! {} has set the channel topic: {}".format(setter, topic)) def logMode(self, channel, source, modeLine, modesChanged): # Filter out users so that we only work on channels try: channel.name except AttributeError: return self.writeLog(channel, "! {} has set modes {}".format(source, modeLine)) def onDestroy(self, channel): if channel.name in self.logfiles: self.logfiles[channel.name].close() del self.logfiles[channel.name] def closeAllFiles(self): for logFile in self.logfiles.itervalues(): logFile.close() self.logfiles.clear()