# Currently written with Wax. # Liable to change because I have a prejudice against GUI toolkits written by # people who put stock in astrology. import sys import socket import oboe import threading from wax import * FIXED_FONT = ('Monospace', 10) class OboeClient(oboe.Haver): def __init__(self, frame, *args, **kwargs): oboe.Haver.__init__(self, *args, **kwargs) self.rooms = {} self.room = None self.frame = frame def OnMessage(self, command, *args): if not hasattr(self, u'On%s' % command): self.frame.Write(u'Unhandled command %s: %s' % (command, args)) def OnHAVER(self, host, version, extensions): self.frame.Write(u'** Connected to %s, running %s' % (host, version)) if extensions: self.frame.Write(u'** Server extensions: %s' % extensions) self.put(u'IDENT', self.username) def OnHELLO(self, username, address): if username != self.username: self.frame.Write(u'** Wanted username %s, but got %s' % ( self.username, username)) self.username = username self.frame.Write(u'** Logged in with address %s' % address) def OnJOIN(self, room, username): if username == self.username: if room in self.rooms: self.room = room self.UpdateUserList() self.frame.Write(u'** Selected room %s' % room) else: self.room = room self.rooms[room] = [] self.put(u'USERSOF', room) self.frame.Write(u'** Joined room %s' % room) else: self.frame.Write(u'** %s joined %s' % (username, room)) self.rooms[room].append(username) self.UpdateUserList() def OnPART(self, room, username, event, reason=None): if username == self.username: self.frame.Write(u'** Parted room %s' % room) del self.rooms[room] if self.rooms: self.OnJOIN(self.rooms.keys()[0], self.username) else: self.room = None self.frame.Write(u'** Parted all rooms') else: self.rooms[room].remove(username) if reason: self.frame.Write(u'** %s parted %s: %s (%s)' % (username, room, event, reason)) else: self.frame.Write(u'** %s parted %s: %s' % (username, room, event)) self.UpdateUserList() def OnUSERSOF(self, room, *users): self.rooms[room] = list(users) self.UpdateUserList() def OnIN(self, room, user, type, *args): txt = u'\x09'.join(args) if type == 'say': self.frame.Write(u'(%s) <%s> %s' % (room, user, txt)) elif type == 'do': self.frame.Write(u'(%s) * %s %s' % (room, user, txt)) else: self.frame.Write(u'(%s) %s %s %s' % (room, user, type, txt)) def OnFAIL(self, command, error, *args): self.frame.Write(u'** Error sending %s (%s): %s' % (command, error, u', '.join(args))) def UpdateUserList(self): self.frame.names.Fill(self.rooms[self.room]) def HandleInput(self, s): if len(s) > 1 and s[0] == u'/' and s[1] != u'/': split = s[1:].split(u' ', 1) cmd = split[0].lower() rest = split[1] if cmd == u'join': if rest in self.rooms: self.OnJOIN(rest, self.username) else: self.put(u'JOIN', rest) elif cmd == u'part': self.put(u'PART', rest) else: self.frame.Write(u'** Unknown command: %s' % cmd) else: if self.room: self.put(u'IN', self.room, 'say', s) else: self.frame.Write(u'** No room') class InputBox(TextBox): def __init__(self, parent, *args, **kwargs): TextBox.__init__(self, parent, *args, **kwargs) self.frame = parent def OnKeyDown(self, event): k = event.GetKeyCode() if k == 13 or k == 372: self.frame.client.HandleInput(self.Value) self.Value = u'' elif k == 9: pass else: event.Skip() class MainFrame(Frame): def Body(self): # upper container upper = Panel(self) # info box self.textbox = TextBox(upper, multiline=True, wrap=True, readonly=True) self.textbox.SetFont(FIXED_FONT) # name list self.names = ListBox(upper) # add to upper container upper.AddComponent(self.textbox, expand='both') upper.AddComponent(self.names, expand='vertical') upper.Pack() # input box self.input = InputBox(self) self.input.SetFont(FIXED_FONT) # add to window self.AddComponent(upper, expand='both') self.AddComponent(self.input, expand='horizontal') self.Pack() self.Size = 640, 480 # client stuff sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((sys.argv[1], int(sys.argv[2]))) self.client = OboeClient(self, sock, sys.argv[3]) thread = threading.Thread(target=self.client.run) thread.setDaemon(True) thread.start() def Write(self, x): self.textbox.AppendText(str(x) + u'\n') app = Application(MainFrame, title=u'Oboe', direction='vertical') app.Run()