Source code for irc

import socket, traceback, time, threading, api, globals
from config import Config
[docs]class IRC: def __init__(self, server, config, log, wrapper, address, port, nickname, channels): self.socket = False self.server = server self.config = config self.wrapper = wrapper self.address = address self.port = port self.nickname = nickname self.channels = channels self.log = log self.timeout = False self.msgQueue = [] self.api = api.API(self.wrapper, "IRC") self.api.registerEvent("player.message", self.playerMessageHandle) self.api.registerEvent("server.say", self.sayMessageHandle)
[docs] def init(self): while not self.wrapper.halt: try: self.log.info("Connecting to IRC...") self.connect() t = threading.Thread(target=self.queue, args=()) t.daemon = True t.start() self.handle() except: for line in traceback.format_exc().split("\n"): self.log.error(line) self.disconnect("Error in Wrapper.py - restarting") self.log.info("Disconnected from IRC") time.sleep(5)
[docs] def connect(self): self.socket = socket.socket() self.socket.connect((self.address, self.port)) self.socket.setblocking(120) self.send("NICK %s" % self.nickname) self.send("USER %s 0 * :%s" % (self.nickname, self.nickname))
[docs] def disconnect(self, message): try: self.send("QUIT :%s" % message) self.socket.close() self.socket = False except: pass
[docs] def send(self, payload): if self.socket: self.socket.send("%s\n" % payload) else: return False
[docs] def playerMessageHandle(self, payload): player = payload["player"] message = payload["message"] self.msgQueue.append("<%s> %s" % (player, message))
[docs] def sayMessageHandle(self, payload): player = payload["player"] message = payload["message"] self.msgQueue.append("[%s] %s" % (player, message))
[docs] def handle(self): while self.socket: try: buffer = self.socket.recv(1024) if buffer == "": self.log.error("Disconnected from IRC") self.socket = False break except socket.timeout: if self.timeout: self.socket = False break else: self.send("PING :%s" % self.randomString()) self.timeout = True buffer = "" except: buffer = "" for line in buffer.split("\n"): self.line = line self.parse()
[docs] def queue(self): while self.socket: for i,message in enumerate(self.msgQueue): for channel in self.channels: self.send("PRIVMSG %s :%s" % (channel, message)) del self.msgQueue[i] self.msgQueue = [] time.sleep(0.1)
[docs] def filterName(self, name): if self.config["IRC"]["obstruct-nicknames"]: return "_" + name[1:] else: return name
[docs] def rawConsole(self, payload): self.server.console(payload)
[docs] def console(self, channel, payload): if self.config["IRC"]["show-channel-server"]: self.rawConsole({"text": "[%s] " % channel, "color": "gold", "extra": payload}) else: self.rawConsole({"extra": payload})
[docs] def parse(self): if self.args(1) == "001": for command in self.config["IRC"]["autorun-irc-commands"]: self.send(command) for channel in self.channels: self.send("JOIN %s" % channel) self.log.info("Connected to IRC!") self.state = True if self.args(1) == "JOIN": nick = self.args(0)[1:self.args(0).find("!")] channel = self.args(2)[1:][:-1] self.log.info("%s joined %s" % (nick, channel)) self.console(channel, [{"text": nick, "color": "green"}, {"text": " joined the channel", "color": "white"}]) self.wrapper.callEvent("irc.channelJoin", {"user": nick, "channel": channel}) if self.args(1) == "PART": nick = self.args(0)[1:self.args(0).find("!")] channel = self.args(2) self.log.info("%s parted from %s" % (nick, channel)) self.console(channel, [{"text": nick, "color": "green"}, {"text": " left the channel", "color": "white"}]) self.wrapper.callEvent("irc.channelPart", {"user": nick, "channel": channel}) if self.args(1) == "MODE": try: nick = self.args(0)[1:self.args(0).find('!')] channel = self.args(2) modes = self.args(3) user = self.args(4)[:-1] self.console(channel, [{"text": user, "color": "green"}, {"text": " received modes %s from %s" % (modes, nick), "color": "white"}]) except: pass if self.args(0) == "PING": self.send("PONG %s" % self.args(1)) if self.args(1) == "QUIT": nick = self.args(0)[1:self.args(0).find("!")] message = " ".join(self.line.split(" ")[2:])[1:].strip("\n").strip("\r") self.wrapper.callEvent("irc.quit", {"user": nick, "message": message}) self.rawConsole({"text": "[IRC] ", "color": "gold", "extra":[{"text": nick, "color": "green"}, {"text": " quit from IRC", "color": "white"}]}) if self.args(1) == "PRIVMSG": channel = self.args(2) nick = self.args(0)[1:self.args(0).find("!")] message = " ".join(self.line.split(" ")[3:])[1:].strip("\n").strip("\r") if channel[0] == "#": self.wrapper.callEvent("irc.channelMessage", {"user": nick, "channel": channel, "message": message}) if message.strip() == ".players": users = "" for user in self.server.players: users += "%s " % user self.send("PRIVMSG %s :There are currently %s users on the server: %s" % (channel, len(self.server.players), users)) elif message.strip() == ".about": self.send("PRIVMSG %s :Wrapper.py version %s (build #%d)" % (channel, Config.version, globals.build)) else: self.log.info('[%s] (%s) %s' % (channel, nick, message)) message = message.decode("utf-8", "ignore") self.console(channel, [{"text": "(%s) " % nick, "color": "green"}, {"text": message, "color": "white"}]) elif self.config["IRC"]["control-from-irc"]: self.log.info('[PRIVATE] (%s) %s' % (nick, message)) def args(i): try: return message.split(" ")[i] except: return "" def msg(string): print "[PRIVATE] (%s) %s" % (self.config["IRC"]["nick"], string) self.send("PRIVMSG %s :%s" % (nick, string)) try: self.authorized except: self.authorized = {} if nick in self.authorized: if int(time.time()) - self.authorized[nick] < 900: if args(0) == 'hi': msg('Hey there!') elif args(0) == 'help': # eventually I need to make help only one or two lines, to prevent getting kicked/banned for spam msg("run [command] - run command on server") msg("togglebackups - temporarily turn backups on or off. this setting is not permanent and will be lost on restart") msg("halt - shutdown server and Wrapper.py, will not auto-restart") msg("kill - force server restart without clean shutdown - only use when server is unresponsive") msg("start/restart/stop - start the server/automatically stop and start server/stop the server without shutting down Wrapper") msg('status - show status of the server') msg("Wrapper.py Version %s by benbaptist" % self.wrapper.getBuildString()) #msg('console - toggle console output to this private message') elif args(0) == 'togglebackups': self.config["Backups"]["enabled"] = not self.config["Backups"]["enabled"] if self.config["Backups"]["enabled"]: msg('Backups are now on.') else: msg('Backups are now off.') configure.save() elif args(0) == 'run': if args(1) == '': msg('Usage: run [command]') else: command = " ".join(message.split(' ')[1:]) self.server.run(command) elif args(0) == 'halt': self.wrapper.halt = True self.server.run("stop") self.server.status = 3 elif args(0) == 'restart': self.server.run('stop') self.server.status = 3 elif args(0) == 'stop': self.server.run('stop') self.server.start = False self.server.status = 3 msg("Server stopping") elif args(0) == 'start': self.server.start = True msg("Server starting") elif args(0) == 'kill': self.server.status = 0 self.server.proc.kill() msg("Server terminated.") elif args(0) == 'status': if self.server.status == 2: msg("Server is running.") elif self.server.status == 1: msg("Server is currently starting/frozen.") elif self.server.status == 0: msg("Server is stopped. Type 'start' to fire it back up.") elif self.server.status == 3: msg("Server is in the process of shutting down/restarting.") else: msg("Server is in unknown state. This is probably a Wrapper.py bug - report it!") elif args(0) == "about": msg("Wrapper.py by benbaptist - version %s (build #%d)" % (Config.version, globals.build)) else: msg('Unknown command. Type help for more commands') else: msg("Session expired, re-authorize.") del self.authorized[nick] else: if args(0) == 'auth': if args(1) == self.config["IRC"]["control-irc-pass"]: msg("Authorization success! You'll remain logged in for 15 minutes.") self.authorized[nick] = int(time.time()) else: msg("Invalid password.") else: msg('Not authorized. Type "auth [password]" to login.')
[docs] def args(self, i): try: return self.line.split(" ")[i] except: pass