def handleCmd_FJOIN(self, prefix, args): # :268 FJOIN #opers 1238298761 +nt :o,268AAAAAF v,268AAAAAE scfg = getServiceConfig() chan = args[0] if chan != scfg.channel: return # If we're not syncd yet, process the channel modes. if not self.ism.syncd: self.handleCmd_FMODE(prefix, args[:-1]) # Keep track of earliest creation time for this channel. self.chan_time = min(self.chan_time, int(args[1])) for uinfo in args[-1].split(): modes, uuid = uinfo.split(",", 1) u = self.ism.findUser(uuid) self.ism.joinChannel(u) changes = {} for m in modes: if m in scfg.chan_umodes.modes: changes[m] = True if changes: self.ism.setChannelUserModes("", u, changes)
def handleCmd_KICK(self, prefix, args): chan = args[0] l33t = prefix n00b = args[1] reason = irc_strip(args[2]) scfg = getServiceConfig() if chan != scfg.channel: return # Rejoin the bot if it's killed. if self.ism.isMyBot(n00b): if self.ism.syncd: self.pushBotJoin() return l33t = self.ism.findUser(l33t).inick n = self.ism.findDtellaNode(inick=n00b) if n: self.ism.kickDtellaNode(n, l33t, reason) else: n00b_u = self.ism.findUser(n00b) message = ("%s has kicked %s: %s" % (irc_to_dc(l33t), irc_to_dc(n00b_u.inick), reason)) CHECK(self.ism.partChannel(n00b_u, message))
def handleCmd_PRIVMSG(self, prefix, args): src_nick = prefix target = args[0] text = args[1] flags = 0 if (text[:8], text[-1:]) == ('\001ACTION ', '\001'): text = text[8:-1] flags |= core.SLASHME_BIT text = irc_strip(text) scfg = getServiceConfig() if target == scfg.channel: self.ism.sendChannelMessage(src_nick, text, flags) #Format> :Global PRIVMSG $irc3.dhirc.com :TESTING.... #Handle global messages delivered to the bridge. elif target == "$" + scfg.my_host: flags |= core.NOTICE_BIT self.ism.sendChannelMessage(src_nick, text, flags) else: n = self.ism.findDtellaNode(inick=target) if n: self.ism.sendPrivateMessage(n, src_nick, text, flags)
def handleCmd_PART(self, prefix, args): nick = prefix chans = args[0].split(',') scfg = getServiceConfig() if scfg.channel in chans: CHECK(self.ism.partChannel(self.ism.findUser(nick)))
def connectionMade(self): scfg = getServiceConfig() LOG.info("Connected to IRC server.") self.challenge = make_challenge() my_capabs = [ ("NICKMAX", 32), ("HALFOP", 1), ("CHANMAX", 65), ("MAXMODES", 20), ("IDENTMAX", 12), ("MAXQUIT", 255), ("MAXTOPIC", 307), ("MAXKICK", 255), ("MAXGECOS", 128), ("MAXAWAY", 200), ("IP6SUPPORT", 1), ("PROTOCOL", 1201), ("CHALLENGE", self.challenge), ] my_capabs_str = ' '.join("%s=%s" % x for x in my_capabs) self.sendLine("CAPAB START") self.sendLine("CAPAB CAPABILITIES :%s" % my_capabs_str) self.sendLine("CAPAB END")
def handleCmd_PING(self, prefix, args): LOG.info("PING? PONG!") scfg = getServiceConfig() if len(args) == 1: self.sendLine("PONG %s :%s" % (scfg.my_host, args[0])) elif len(args) == 2: self.sendLine("PONG %s :%s" % (args[1], args[0]))
def handleCmd_JOIN(self, prefix, args): nick = prefix chans = args[0].split(',') scfg = getServiceConfig() if scfg.channel in chans: self.ism.joinChannel(self.ism.findUser(nick))
def handleCmd_WHOIS(self, prefix, args): # Somewhat simplistic handling of WHOIS requests if not (prefix and len(args) >= 1): return src = prefix who = args[-1] scfg = getServiceConfig() if who.lower() == self.ism.bot_user.inick.lower(): self.pushWhoisReply(311, src, who, B_USER, scfg.my_host, "*", B_REALNAME) self.pushWhoisReply(312, src, who, scfg.my_host, scfg.my_name) self.pushWhoisReply(319, src, who, scfg.channel) else: n = self.ism.findDtellaNode(inick=who) if not (n and hasattr(n, "hostmask")): return self.pushWhoisReply(311, src, who, n_user(n.ipp), n.hostmask, "*", "Dtella %s" % n.dttag[3:]) self.pushWhoisReply(312, src, who, scfg.my_host, scfg.my_name) self.pushWhoisReply(319, src, who, scfg.channel) if local.use_locations: self.pushWhoisReply(320, src, who, "Location: %s" % local.hostnameToLocation(n.hostname)) self.pushWhoisReply(318, src, who, "End of /WHOIS list.")
def handleCmd_WHOIS(self, prefix, args): # Somewhat simplistic handling of WHOIS requests if not (prefix and len(args) >= 1): return src = prefix who = args[-1] scfg = getServiceConfig() if who.lower() == self.ism.bot_user.inick.lower(): self.pushWhoisReply(311, src, who, B_USER, scfg.my_host, '*', B_REALNAME) self.pushWhoisReply(312, src, who, scfg.my_host, scfg.my_name) self.pushWhoisReply(319, src, who, scfg.channel) else: n = self.ism.findDtellaNode(inick=who) if not (n and hasattr(n, 'hostmask')): return self.pushWhoisReply(311, src, who, n_user(n.ipp), n.hostmask, '*', "Dtella %s" % n.dttag[3:]) self.pushWhoisReply(312, src, who, scfg.my_host, scfg.my_name) self.pushWhoisReply(319, src, who, scfg.channel) if local.use_locations: self.pushWhoisReply( 320, src, who, "Location: %s" % local.hostnameToLocation(n.hostname)) self.pushWhoisReply(318, src, who, "End of /WHOIS list.")
def handleCmd_KICK(self, prefix, args): chan = args[0] l33t = prefix n00b = args[1] reason = irc_strip(args[2]) scfg = getServiceConfig() if chan != scfg.channel: return # Rejoin the bot if it's killed. if self.ism.isMyBot(n00b): if self.ism.syncd: self.pushBotJoin() return l33t = self.ism.findUser(l33t).inick n = self.ism.findDtellaNode(inick=n00b) if n: self.ism.kickDtellaNode(n, l33t, reason) else: n00b_u = self.ism.findUser(n00b) message = ( "%s has kicked %s: %s" % (irc_to_dc(l33t), irc_to_dc(n00b_u.inick), reason)) CHECK(self.ism.partChannel(n00b_u, message))
def handleCmd_SERVER(self, prefix, args): if prefix: # Not from our connected server return if self.server_name: # Could be a dupe? Ignore it. return # We got a reply from the our connected IRC server, so our password # was just accepted. Send the Dtella state information into IRC. # Save server name CHECK(args[0]) self.server_name = args[0] LOG.info("IRC Server Name: %s" % self.server_name) # Tell the ReconnectingClientFactory that we're cool self.factory.resetDelay() # This isn't very correct, because the Dtella nicks # haven't been sent yet, but it's the best we can practically do. scfg = getServiceConfig() cloak_checksum = scfg.hostmasker.getChecksum() self.sendLine("NETINFO 0 %d 0 %s 0 0 0 :%s" % (time.time(), cloak_checksum, scfg.network_name)) self.sendLine(":%s EOS" % scfg.my_host)
def handleCmd_EOS(self, prefix, args): if prefix != self.server_name: return if self.ism.syncd: return LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.sendLine( "TKL + Q * %s* %s 0 %d :Reserved for Dtella" % (cfg.dc_to_irc_prefix, scfg.my_host, time.time())) self.ism.killConflictingUsers() # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def handleCmd_ENDBURST(self, prefix, args): if self.ism.syncd: # FIXME LOG.warning("Ignoring ENDBURST") return CHECK(self.server_name) LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.ism.killConflictingUsers() self.sendLine(":%s ADDLINE Q %s* %s %d 0 :%s" % (self.sid, cfg.dc_to_irc_prefix, scfg.my_host, time.time(), self.qline_reason)) # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def pushWhoisReply(self, code, target, who, *strings): scfg = getServiceConfig() line = ":%s %d %s %s " % (scfg.my_host, code, target, who) strings = list(strings) strings[-1] = ":" + strings[-1] line += ' '.join(strings) self.sendLine(line)
def handleCmd_ENDBURST(self, prefix, args): if self.ism.syncd: # FIXME LOG.warning("Ignoring ENDBURST") return CHECK(self.server_name) LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.ism.killConflictingUsers() self.sendLine( ":%s ADDLINE Q %s* %s %d 0 :%s" % (self.sid, cfg.dc_to_irc_prefix, scfg.my_host, time.time(), self.qline_reason)) # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def handleCmd_EOS(self, prefix, args): if prefix != self.server_name: return if self.ism.syncd: return LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.sendLine("TKL + Q * %s* %s 0 %d :Reserved for Dtella" % (cfg.dc_to_irc_prefix, scfg.my_host, time.time())) self.ism.killConflictingUsers() # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def event_Notice(self, src_n, dst_u, text): scfg = getServiceConfig() if dst_u is None: target = scfg.channel else: target = dst_u.inick self.sendLine(":%s NOTICE %s :%s" % (src_n.nick, target, text))
def handleCmd_FTOPIC(self, prefix, args): # :268 FTOPIC #dtella 1238306219 nick!host :hello chan = args[0] whoset = args[2].split('!', 1)[0] text = irc_strip(args[-1]) scfg = getServiceConfig() if chan == scfg.channel: self.ism.setTopic(whoset, text)
def handleCmd_TOPIC(self, prefix, args): # :Paul TOPIC #dtella Paul 1169420711 :Dtella :: Development Stage chan = args[0] whoset = args[1] text = irc_strip(args[-1]) scfg = getServiceConfig() if chan == scfg.channel: self.ism.setTopic(whoset, text)
def handleCmd_TOPIC(self, prefix, args): # :268AAAAAO TOPIC #dtella :hello world whoset_uuid = prefix chan = args[0] text = irc_strip(args[-1]) scfg = getServiceConfig() if chan == scfg.channel: whoset = self.ism.findUser(whoset_uuid).inick self.ism.setTopic(whoset, text)
def pushBotJoin(self, do_nick=False): scfg = getServiceConfig() uuid = self.ism.bot_user.uuid if do_nick: self.pushUID(uuid, self.ism.bot_user.inick, B_USER, scfg.my_host, None, "", None, B_REALNAME) # Join channel, and grant ops. self.pushJoin(uuid, "o")
def pushBotJoin(self, do_nick=False): scfg = getServiceConfig() if do_nick: self.pushNick(self.ism.bot_user.inick, B_USER, scfg.my_host, "Sq", None, B_REALNAME) # Join channel, and grant ops. self.pushJoin(self.ism.bot_user.inick) self.sendLine( ":%s MODE %s +ao %s %s" % (scfg.my_host, scfg.channel, self.ism.bot_user.inick, self.ism.bot_user.inick) )
def cb(): self.ping_dcall = None if self.ping_waiting: LOG.error("Ping timeout!") self.transport.loseConnection() else: scfg = getServiceConfig() self.sendLine("PING :%s" % scfg.my_host) self.ping_waiting = True self.ping_dcall = reactor.callLater(60.0, cb)
def pushBotJoin(self, do_nick=False): scfg = getServiceConfig() if do_nick: self.pushNick(self.ism.bot_user.inick, B_USER, scfg.my_host, "Sq", None, B_REALNAME) # Join channel, and grant ops. self.pushJoin(self.ism.bot_user.inick) self.sendLine(":%s MODE %s +ao %s %s" % (scfg.my_host, scfg.channel, self.ism.bot_user.inick, self.ism.bot_user.inick))
def pushNick(self, nick, ident, host, modes, ip, name): # If an IP was provided, convert to a base64 parameter. if ip: ip = ' ' + binascii.b2a_base64(ip).rstrip() else: ip = '' scfg = getServiceConfig() self.sendLine( "NICK %s 1 %d %s %s %s 1 +%s *%s :%s" % (nick, time.time(), ident, host, scfg.my_host, modes, ip, name))
def event_Message(self, src_n, dst_u, text, action=False): scfg = getServiceConfig() if dst_u is None: target = scfg.channel else: target = dst_u.inick if action: text = "\001ACTION %s\001" % text self.sendLine(":%s PRIVMSG %s :%s" % (src_n.inick, target, text))
def pushBotJoin(self, do_nick=False): scfg = getServiceConfig() uuid = self.ism.bot_user.uuid if do_nick: self.pushUID( uuid, self.ism.bot_user.inick, B_USER, scfg.my_host, None, "", None, B_REALNAME) # Join channel, and grant ops. self.pushJoin(uuid, "o")
def setupSID(self): scfg = getServiceConfig() if scfg.sid: self.sid = scfg.sid return # Generate a 3-digit SID, based on some config constants. # This isn't the same algorithm as inspircd.cpp, but it doesn't # really matter. input_str = "%s\0%s" % (scfg.my_host, scfg.my_name) sid, = struct.unpack("!I", sha256(input_str).digest()[:4]) self.sid = "%03d" % (sid % 999)
def handleCmd_NOTICE(self, prefix, args): src_nick = prefix target = args[0] text = irc_strip(args[1]) flags = core.NOTICE_BIT scfg = getServiceConfig() if target == scfg.channel: self.ism.sendChannelMessage(src_nick, text, flags) else: n = self.ism.findDtellaNode(inick=target) if n: self.ism.sendPrivateMessage(n, src_nick, text, flags)
def pushUID(self, uuid, nick, ident, host, cloak_host, modes, ip, gecos): # If an IP was provided, convert to a base64 parameter. if not ip: ip = '0.0.0.0' if not cloak_host: cloak_host = host scfg = getServiceConfig() now = time.time() self.sendLine(":%s UID %s %d %s %s %s %s %s %d +%s :%s" % (self.sid, uuid, now, nick, host, cloak_host, ident, ip, now, modes, gecos))
def pushUID(self, uuid, nick, ident, host, cloak_host, modes, ip, gecos): # If an IP was provided, convert to a base64 parameter. if not ip: ip = '0.0.0.0' if not cloak_host: cloak_host = host scfg = getServiceConfig() now = time.time() self.sendLine( ":%s UID %s %d %s %s %s %s %s %d +%s :%s" % (self.sid, uuid, now, nick, host, cloak_host, ident, ip, now, modes, gecos))
def handleCmd_CAPAB(self, prefix, args): capab_mode = args[0] scfg = getServiceConfig() if capab_mode == "START": CHECK(not self.capabs) elif capab_mode == "CAPABILITIES": for capab in args[1].split(): k, v = capab.split("=", 1) self.capabs[k] = v elif capab_mode == "END": challenge = self.capabs["CHALLENGE"] response = ihmac(scfg.sendpass, challenge) self.sendLine("SERVER %s %s 0 %s :%s" % (scfg.my_host, response, self.sid, scfg.my_name))
def runBridge(): import dtella.bridge_config as cfg setLogFile(cfg.file_base + ".log", 4 << 20, 4) LOG.debug("Bridge Logging Manager Initialized") addTwistedErrorCatcher(LOG.critical) from dtella.bridge.main import DtellaMain_Bridge dtMain = DtellaMain_Bridge() from dtella.bridge.bridge_server import getServiceConfig scfg = getServiceConfig() scfg.startService(dtMain) reactor.run()
def runBridge(): import dtella.bridge_config as cfg setLogFile(cfg.file_base + ".log", 4<<20, 4) LOG.debug("Bridge Logging Manager Initialized") addTwistedErrorCatcher(LOG.critical) from dtella.bridge.main import DtellaMain_Bridge dtMain = DtellaMain_Bridge() from dtella.bridge.bridge_server import getServiceConfig scfg = getServiceConfig() scfg.startService(dtMain) reactor.run()
def handleCmd_CAPAB(self, prefix, args): capab_mode = args[0] scfg = getServiceConfig() if capab_mode == "START": CHECK(not self.capabs) elif capab_mode == "CAPABILITIES": for capab in args[1].split(): k, v = capab.split("=", 1) self.capabs[k] = v elif capab_mode == "END": challenge = self.capabs["CHALLENGE"] response = ihmac(scfg.sendpass, challenge) self.sendLine( "SERVER %s %s 0 %s :%s" % (scfg.my_host, response, self.sid, scfg.my_name))
def handleCmd_SERVER(self, prefix, args): # :foo.dhirc.com SERVER s.dhirc.com * 1 00A :Services hostname = args[0] password = args[1] sid = args[3] # Register each server as a user, because it's easier. LOG.info("Recording server: hostname=%s sid=%s" % (hostname, sid)) self.ism.addUser(hostname, sid) if prefix: # Not my directly-connected server. return if self.server_name: # Could be a dupe? Ignore it. return # We got a reply from the our connected IRC server, so our password # was just accepted. Send the Dtella state information into IRC. scfg = getServiceConfig() # Save server name CHECK(args[0]) self.server_name = args[0] # Verify challenge response. if scfg.recvpass is None: LOG.info("Skipping validation of recvpass") else: ch_response = args[1] if ch_response != ihmac(scfg.recvpass, self.challenge): raise ValueError("Incorrect recvpass") LOG.info("Correct recvpass") LOG.info("IRC Server Name: %s" % self.server_name) # Tell the ReconnectingClientFactory that we're cool self.factory.resetDelay() self.sendLine("BURST %d" % time.time()) self.sendLine("ENDBURST")
def shutdown(self): if self.shutdown_deferred: return self.shutdown_deferred # Remove nick ban self.pushRemoveQLine(cfg.dc_to_irc_prefix + "*") # Scream self.pushQuit(self.ism.bot_user.inick, "AIEEEEEEE!") # Send SQUIT for completeness scfg = getServiceConfig() self.sendLine(":%s SQUIT %s :Bridge Shutting Down" % (scfg.my_host, scfg.my_host)) # Close connection self.transport.loseConnection() # This will complete after loseConnection fires self.shutdown_deferred = defer.Deferred() return self.shutdown_deferred
def handleCmd_KICK(self, prefix, args): chan = args[0] l33t = prefix n00b = args[1] reason = irc_strip(args[2]) scfg = getServiceConfig() if chan != scfg.channel: return if n00b.lower() == self.ism.bot_user.inick.lower(): if self.ism.syncd: self.pushBotJoin() return n = self.ism.findDtellaNode(inick=n00b) if n: self.ism.kickDtellaNode(n, l33t, reason) else: message = "%s has kicked %s: %s" % (irc_to_dc(l33t), irc_to_dc(n00b), reason) CHECK(self.ism.partChannel(self.ism.findUser(n00b), message))
def handleCmd_KICK(self, prefix, args): chan = args[0] l33t = prefix n00b = args[1] reason = irc_strip(args[2]) scfg = getServiceConfig() if chan != scfg.channel: return if n00b.lower() == self.ism.bot_user.inick.lower(): if self.ism.syncd: self.pushBotJoin() return n = self.ism.findDtellaNode(inick=n00b) if n: self.ism.kickDtellaNode(n, l33t, reason) else: message = ("%s has kicked %s: %s" % (irc_to_dc(l33t), irc_to_dc(n00b), reason)) CHECK(self.ism.partChannel(self.ism.findUser(n00b), message))
def event_NodeSetTopic(self, n, topic): scfg = getServiceConfig() self.sendLine( ":%s TOPIC %s %s %d :%s" % (n.inick, scfg.channel, n.inick, time.time(), topic))
def event_NodeSetTopic(self, n, topic): scfg = getServiceConfig() self.sendLine(":%s TOPIC %s %s %d :%s" % (n.inick, scfg.channel, n.inick, time.time(), topic))