#!/usr/bin/env python from Tkinter import * import tkMessageBox import socket import select import sys import thread import time import string import logging HOST = "localhost" PORT = 123450 LANGS = [] # listen for incoming messages from server # inspired by chat code by pyczak@gmx.de def listenServer(connection, window): inbound = [connection] outbound = [] error_track = [] logger.debug("listenServer - client listener thread started") while 1: r,w,e = select.select(inbound, outbound, error_track, 1.0) if r: data = connection.recv(1024) logger.debug("listenServer - incoming data %s", data) if data: if string.find(data, "_NAMES>") != -1: data_word = data.split(">") s=data_word[1].split(":") names=s[1:] names.sort() window.fenster.listbox.delete(0,END) for n in names: na=n.split(",") lang=na[1] name = na[0] logger.debug("listenServer - processing name %s", name) logger.debug("listenServer - processing language %s", lang) if lang not in LANGS: LANGS.append(lang) window.fenster.listbox.insert(END,name) LANGS.sort() window.fenster.whis_butt=apply(OptionMenu, (window.fenster.down_frame, window.fenster.variable) + tuple(LANGS)) window.fenster.whis_butt.grid(column=2, row=0) elif string.find(data, "_NEW_CHATTER>") != -1: lst = data.split(">") wrd = lst[1] data_word = wrd.split(",") names.append(data_word[0]) names.sort() LANGS.append(data_word[1]) window.fenster.listbox.delete(0,END) for name in names: # check for silly comma on name -horrible hack but will fix later if string.find(name, ",") != -1: aux = name.split(",") name = aux[0] window.fenster.listbox.insert(END,name) #window.fenster.listbox.insert(window.fenster.listbox.size()-1,name) LANGS.sort() window.fenster.whis_butt=apply(OptionMenu, (window.fenster.down_frame, window.fenster.variable) + tuple(LANGS)) window.fenster.whis_butt.grid(column=2, row=0) # if this guy got another chatter calling in, then he's local window.fenster.local = True elif string.find(data, "_QUIT") != -1: data_word = data.split(":") # FIX ME, data_word doesnt come as a string for i in names: if i.startswith(data_word[0]): names.remove(i) break names.sort() window.fenster.listbox.delete(0,END) for name in names: window.fenster.listbox.insert(END,name) else: in_msg = data lst = in_msg.split(":") sender = lst[0] in_msg = data original = in_msg if string.find(in_msg, "_TRANS>") != -1: lst = in_msg.split("_TRANS>") original = lst[0] logger.debug("listenServer - original message %s", original) translated = lst[1] logger.debug("listenServer - translated message %s", translated) else: translated = sender + ": Translation service unavailable" window.fenster.l2.append(translated) window.fenster.l1.append(original) #if window.fenster.local: window.printText(translated) #else: # window.printText(original) else: connection.close() # connects the client to the server, checks and reports if client is _CLIENT_ACCEPTED def startClient(host, port, nick, language): global HOST global PORT global name global lang HOST = host PORT = port name = nick lang = language LANGS.append(lang) print HOST, PORT, name, lang if HOST == "": HOST = "localhost" global client client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: client.connect((HOST, PORT)) except: tkMessageBox.showerror("Login-Error", "server unreachable") logger.exception("startClient - server unreachable") sys.exit() client.send(name+","+lang) returnmsg=client.recv(1024) if string.find(returnmsg, "_NAME_ALREADY_EXISTS") != -1: tkMessageBox.showerror("Login-Error", "name already in use") logger.debug("startClient - name already in use") sys.exit() elif string.find(returnmsg, "_SERVER_FULL") != -1: tkMessageBox.showerror("Login-Error", "sorry, server overloaded") logger.debug("startClient - server unable to handle more clients") sys.exit() elif string.find(returnmsg, "_CLIENT_ACCEPTED") == -1: sys.exit() #returnmsg=client.recv(1024) logger.debug("startClient - server handshake message %s", returnmsg) # disconnects client from server def stopClient(): try: client.send(name+":\t_QUIT") except: logger.exception("stopClient - server seems to be down") time.sleep(10) client.close() sys.exit() # send message to server def sendData(message): message = name+": " + message if string.find(message,"_QUIT") != -1: logger.debug("sendData - client quit") try: client.send(message) except: logger.exception("sendData - server down or unreachable") tkMessageBox.showerror("Connection Error", "server down or unreachable") try: unicd = message.encode('utf-8') client.send(unicd) except Exception, e: logger.exception("sendData - encoding error", e) except: logger.exception("sendData - server down or unreachable") tkMessageBox.showerror("Connection Error", "server down or unreachable") # window for direct input of server name and port and connection class StartWin: def initialize(self): self.startw=Tk(className="Login") self.startw.servlab=Label(self.startw, text="Server:") self.startw.servin=Entry(self.startw, width=15) self.startw.servin.insert(INSERT, "localhost") self.startw.servlab.grid(column=0, row=0) self.startw.servin.grid(column=1, row=0) self.startw.portlab=Label(self.startw, text="Port:") self.startw.portin=Entry(self.startw, width=15) self.startw.portin.insert(INSERT, "123450") self.startw.portlab.grid(column=0, row=1) self.startw.portin.grid(column=1, row=1) self.startw.nicklab=Label(self.startw, text="Nickname:") self.startw.nickin=Entry(self.startw, width=15) self.startw.nicklab.grid(column=0, row=2) self.startw.nickin.grid(column=1, row=2) self.startw.l1=Label(self.startw, text="Language:") self.startw.l1.grid(column=0, row=3) OPTIONS = ["en","es","el","zh","de","fr","it","pt","ja","ko","ru"] self.startw.variable = StringVar() self.startw.variable.set(OPTIONS[0]) # default value self.startw.whis_butt=apply(OptionMenu, (self.startw, self.startw.variable) + tuple(OPTIONS)) self.startw.whis_butt.grid(column=1, row=3) self.startw.login_butt=Button(self.startw, text="Login", command=self.connect) self.startw.login_butt.grid(column=0, row=4) self.startw.exit_butt=Button(self.startw, text="Exit", command=self.exit) self.startw.exit_butt.grid(column=1, row=4) self.startw.mainloop() # connect client with inserted data def connect(self): if self.startw.portin.get() == "": self.startw.portin.insert(INSERT, "123450") startClient(self.startw.servin.get(), int(self.startw.portin.get()), self.startw.nickin.get(), self.startw.variable.get()) self.startw.quit() self.startw.destroy() def exit(self): self.startw.quit() self.startw.destroy() #sys.exit() # main chat window class ClientGUI: def startWindow(self): self.fenster=Tk(className=" Jiim Client") self.fenster.top_frame=Frame(self.fenster) self.fenster.scrollbar1=Scrollbar(self.fenster.top_frame) self.fenster.scrollbar2=Scrollbar(self.fenster.top_frame) self.fenster.scrollbar1.grid(column=1, row=0, ipady=65, padx=0) self.fenster.scrollbar2.grid(column=3, row=0, ipady=65, padx=0) self.fenster.text=Text(self.fenster.top_frame, width=40, height=13, wrap=WORD, yscrollcommand=self.fenster.scrollbar1.set) self.fenster.scrollbar1.config(command=self.fenster.text.yview) self.fenster.text.grid(column=0, row=0) self.fenster.listbox=Listbox(self.fenster.top_frame, selectmode=SINGLE, width=15, yscrollcommand=self.fenster.scrollbar2.set) self.fenster.listbox.grid(column=2, row=0) self.fenster.scrollbar2.config(command=self.fenster.listbox.yview) self.fenster.down_frame=Frame(self.fenster) self.fenster.inbox=Entry(self.fenster.down_frame, width=40) self.fenster.inbox.grid(column=0, row=0) self.fenster.send_butt=Button(self.fenster.down_frame,text="Send",command=self.dispatch) self.fenster.send_butt.grid(column=1, row=0) self.fenster.options = LANGS self.fenster.variable = StringVar() self.fenster.variable.set(LANGS[0]) # default value self.fenster.variable.trace('w', doLangChoices) # trace choices self.fenster.whis_butt=apply(OptionMenu, (self.fenster.down_frame, self.fenster.variable) + tuple(LANGS)) self.fenster.whis_butt.grid(column=2, row=0) # create a menu menu = Menu(self.fenster) self.fenster.config(menu=menu) filemenu = Menu(menu) menu.add_cascade(label="File", menu=filemenu) # filemenu.add_separator() filemenu.add_command(label="Exit", command=stopClient) lmenu = Menu(menu) lmenu.add_command(label="Original", command=self.doL1) lmenu.add_command(label="Translated", command=self.doL2) menu.add_cascade(label="Language", menu=lmenu) # create about pulldown menu helpmenu = Menu(menu, tearoff=0) helpmenu.add_command(label="About", command=self.doAbout) menu.add_cascade(label="Help", menu=helpmenu) self.fenster.top_frame.pack(side=TOP) self.fenster.down_frame.pack(side=BOTTOM) self.messageline="" sendData("_NAMES>") # history log for original instant messages self.fenster.l1 = [] # history log for translated instant messages self.fenster.l2 = [] self.fenster.local = False def doAbout(self): tkMessageBox.showinfo("About", """ Jiim - Cross-Linguistic IM by Jorge De Castro jorge@bcs.org.uk http://www.jorgetown.net http://www.jiim.org """) return # send data to server def dispatch(self): msg=self.fenster.inbox.get() self.fenster.inbox.delete(0,END) sendData(msg) # send private message def privateTalk(self): msg=self.fenster.inbox.get() recipient=self.fenster.listbox.get(self.fenster.listbox.curselection()) self.fenster.inbox.delete(0, END) msg="_PRIVATE>" + recipient + ": " + msg self.fenster.text.insert(END,msg+"\n") self.fenster.text.see(END) sendData(msg) def poll(self): if self.messageline != in_msg: self.messageline = in_msg self.printText(self.messageline) # print message to text field def printText(self, msg): self.fenster.text.insert(END,msg+"\n") self.fenster.inbox.delete(0,29) self.fenster.text.see(END) def doL1(self): self.fenster.text.delete(1.0, END) for l in self.fenster.l1: self.fenster.text.insert(END,l+"\n") self.fenster.text.see(END) def doL2(self): self.fenster.text.delete(1.0, END) for l in self.fenster.l2: self.fenster.text.insert(END,l+"\n") self.fenster.text.see(END) def doLangChoices(name, index, mode): logger.debug("callback called with name=%r, index=%r, mode=%r" % (name, index, mode)) # HOW TO ACCESS THE VAR VALUE HERE?? varValue = root.getvar(name) print varValue # create logger logger = logging.getLogger("Jiim Client") logger.setLevel(logging.DEBUG) # create file handler and set level to info fh = logging.FileHandler("client.log") fh.setLevel(logging.DEBUG) # create formatter formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") # add formatter to fh fh.setFormatter(formatter) # add fh to logger logger.addHandler(fh) logger.debug("client started") conn=StartWin() conn.initialize() try: root=ClientGUI() thread.start_new_thread(listenServer, (client, root)) root.startWindow() mainloop() except Exception: logger.exception("client thread aborted")