#! /usr/bin/env python import sys, random, string, ssl import irc.bot#, irc.strings from irc.client import ip_numstr_to_quad#, ip_quad_to_numstr from postgres import Postgres import commands.public, commands.admin, commands.games, commands.statistics import events.on_join, events.on_kick, events.on_pubmsg from common.networkservices import NickServ from common import log bold = "\x02" italic = "\x1D" underline = "\x1F" reverse = "\x16" # swap background and foreground colors ("reverse video") reset = "\x0F" blue = "\x0302" green = "\x0303" red = "\x0304" grey = "\x0314" class PyRot(irc.bot.SingleServerIRCBot): def __init__(self, network, db, homechannel, nickname, username, password, host, port=6667, usessl=False, cmdchar="!", helpchar="@"): self.network = network self.db = db self.homechannel = homechannel self.password = password self.cmdchar = cmdchar self.helpchar = helpchar if usessl: factory = irc.connection.Factory(wrapper=ssl.wrap_socket) else: factory = irc.connection.Factory() log.info("Connecting to " + host + ":" + str(port) + "/" + self.homechannel) try: irc.bot.SingleServerIRCBot.__init__(self, [(host, port)], nickname, username, connect_factory=factory) except irc.client.ServerConnectionError: sys.stderr.write(sys.exc_info()[1]) # Events. def on_nicknameinuse(self, connection, event): log.info("Nickname in use, attempting to recover: " + connection.nickname) connection.nick(connection.nickname + ''.join(random.choice(string.digits) for _ in range(3))) # Take temporary nick. Without this recovering via NickServ won't work. NickServ.recover_nick(connection, self.password) def on_welcome(self, connection, event): log.info(event) # Handy for debugging. Keep this. if self.password: # Id with NickServ connection.privmsg("NickServ", "identify " + connection.nickname + " " + self.password) # Identify with NickServ. channels = self.db.all("SELECT name FROM channels WHERE network='" + self.network + "' AND autojoin=True") connection.join(self.homechannel) for channel in channels: # Join channels with autojoin function. connection.join(channel) connection.join(self.homechannel) def on_error(self, connection, event): log.notice(event) connection.privmsg(self.homechannel, "ERROR: " + event) def on_nick(self, connection, event): if event.source.nick == connection.nickname: # If the nick boing changes is the bots prefered nickname. log.info("Assuming original nick.") NickServ.recover_nick(connection, self.password) def on_join(self, connection, event): print(event) events.on_join.process_event(self, connection, event) def on_kick(self, connection, event): print(event) events.on_kick.process_event(self, connection, event) def on_mode(self, connection, event): print(event) def on_part(self, connection, event): print(event) def on_quit(self, connection, event): print(event) def on_invite(self, connection, event): print(event) def on_topic(self, connection, event): print(event) def on_pubmsg(self, connection, event): commands.public.do_command(self, connection, event) commands.admin.do_command(self, connection, event) commands.statistics.do_command(self, connection, event) try: games = self.db.one("SELECT games FROM channels WHERE name='" + event.target + "' AND network='" + self.network + "'") except: pass if games: commands.games.do_command(self, connection, event) events.on_pubmsg.process_event(self, connection, event) def on_pubnotice(self, connection, event): print(event) def on_privmsg(self, connection, event): log.info(event) commands.public.do_command(self, connection, event) commands.admin.do_command(self, connection, event) commands.statistics.do_command(self, connection, event) commands.games.do_command(self, connection, event) def on_privnotice(self, connection, event): log.info(event) commands.public.do_command(self, connection, event) commands.admin.do_command(self, connection, event) commands.statistics.do_command(self, connection, event) commands.games.do_command(self, connection, event) if event.source.nick == NickServ and event.arguments[0].startswith("This nickname is registered"): connection.privmsg("NickServ", "identify " + connection.nickname + " " + connection.password) # Identify with NickServ. def on_action(self, connection, event): print(event) # DCC stuff from originalexample file. def on_dccmsg(self, c, e): # non-chat DCC messages are raw bytes; decode as text text = e.arguments[0].decode('utf-8') c.privmsg("You said: " + text) def on_dccchat(self, c, e): if len(e.arguments) != 2: return args = e.arguments[1].split() if len(args) == 4: try: address = ip_numstr_to_quad(args[2]) port = int(args[3]) except ValueError: return self.dcc_connect(address, port) def main(): # Check system arguments. if len(sys.argv) != 2: print(sys.argv) print("Usage: rotbot ") sys.exit(1) instance = sys.argv[1] # Instance is the database network id. db = Postgres("postgres://pyRot:4h8q(.@localhost/pyRot") # Database. # Get network from database. try: network = db.one("SELECT * FROM networks WHERE id=" + str(instance)) except: print("Invalid network ID.") sys.exit(1) if not network: print("Invalid network ID.") sys.exit(1) bot = PyRot(network.name, db, network.home_channel, network.nickname, network.username, network.password, network.host, network.port, network.use_ssl, network.command_character, network.help_character) bot.start() if __name__ == "__main__": try: main() except KeyboardInterrupt: log.info('Interrupted by keyboard.') sys.exit(0)