import irc import string class Recipient: def __init__(self, interface, name): self.__interface = interface self.__name = name def name(self): return self.__name def tell(self, text): """Tell the recipient something""" return self.write_raw(["PRIVMSG", self.__name], text) def notice(self, text): """Send a notice to the recipient""" return self.write_raw(["NOTICE", self.__name], text) def ctcp(self, command, text): """Send a CTCP command to the recipient""" return self.tell("\001%s %s\001" % (irc.upper(command), text)) def act(self, text): """Send an action to the recipient""" return self.ctcp("ACTION", text) def cnotice(self, command, text): """Send a CTCP notice to the recipient""" return self.notice("\001%s %s\001" % (irc.upper(command), text)) def kick(self, text): """Kick the recipient off""" pass def mode(self, mode, addl=None): """Set modes on the recipient""" pass def write_raw(self, args, text): """Send raw data to the IRC server""" return self.__interface.write(args, text) class Channel(Recipient): pass class User(Recipient): pass class Server(Recipient): pass class Interface: def __init__(self, interface): self.__server = None self.__empty = Recipient(NullInterface(), "") self.__interface = interface def connect(self, server, port, nick, gecos): self.__server = irc.Client() self.__server.connect(server, port, nick, gecos) def fileno(self): return self.__server.fileno() def write(self, args, *text): apply (self.__server.write, (args,) + tuple(text)) def recipient(self, name): if name[0] in ["&", "#"]: return Channel(self, name) else: return User(self, name) def guess_forum(self, sender, args): if args[2][0] in ("&", "#"): return Channel(self, args[2]) else: return sender def handle_input(self): while 1: line = self.__server.get_line() if not line: return op, args, text = self.__server.parse_line(line) op, sender, recip, forum, addl = self._parse_more(op, args, text) self.__interface.handle_message(op, sender, recip, forum, addl, args, text) def _parse_more(self, op, args, text): """Parse more, creating objects and stuff This returns a 4-tuple: (sender, recip, forum, addl) The first three are Recipient objects, set up so that you don't have to worry about whether a message was sent privately, to a channel, or whether or not there was a recipient. For any places where it would not make sense to have an object defined, a Null recipient is used--you can jabber to it as much as you like, but nothing will be sent out. addl is another tuple, containing additional information which might be relelvant. Here's what it will contain, based on the server operation: op | contents ---------|------------ PRIVMSG | Text of the message NOTICE | Text of the notice CPRIVMSG | CTCP command, Text of the command CNOTICE | CTCP command, Text of the command KICK | Text of the kick MODE | Not sure yet JOIN | Empty PART | Empty QUIT | Quit message PING | Ping text (usually the time) """ try: sender = self.recipient(irc.unpack_nuhost(args[0])[0]) except ValueError: sender = Server(self, args[0]) recip = self.__empty forum = self.__empty addl = () if op in ("PRIVMSG", "NOTICE"): forum = self.guess_forum(sender, args) addl = (text,) elif op in ("CPRIVMSG", "CNOTICE"): forum = self.guess_forum(sender, args) splits = string.split(text, " ") if splits[0] == "DCC": op = "DC" + op addl = (splits[1],) + tuple(splits[2:]) else: addl = (splits[0],) + tuple(splits[1:]) elif op in ("KICK",): recip = self.recipient(args[3]) forum = self.recipient(args[2]) addl = (text,) elif op in ("MODE",): forum = self.recipient(args[2]) addl = args[3:] elif op in ("JOIN", "PART"): forum = self.recipient(text) elif op in ("QUIT",): addl = (text,) elif op in ("PING",): addl = (text,) else: try: int(op) except ValueError: print "WARNING: can't parse_more:", op if forum == self.__empty: forum = Server(self, args[0]) return (op, sender, recip, forum, addl) class NullInterface(Interface): """Null Interface stub class for empty values""" def __init__(self): pass def connect(self, *ignored): pass def fileno(self): raise AttributeError, "filenumber requested on null interface" def write(self, *ignored): pass def handle_input(self): pass