#!/usr/bin/env python import sys import socket import select import string import time import thread import re import urllib import urllib2 import htmllib import locale import codecs import logging from threading import Thread PORT = 123450 TRANSLATE = True ABBRV = {} # inspired by Jonathan Feinberg's babelizer (http://babel.MrFeinberg.com/) __where = [ re.compile(r'name=\"q\">([^<]*)'), re.compile(r'td bgcolor=white>([^<]*)'), re.compile(r'td bgcolor=white class=s>
([^<]*)'), re.compile(r'<\/strong>
([^<]*)') ] class BabelfishError(Exception): pass class LanguageNotAvailableError(BabelfishError): pass class BabelfishChangedError(BabelfishError): pass class BabelfishIOError(BabelfishError): pass def clean(text): return ' '.join(string.replace(text.strip(), "\n", ' ').split()) def translateByCode(phrase, from_code, to_code): phrase = clean(phrase) params = urllib.urlencode( { 'BabelFishFrontPage' : 'yes', 'doit' : 'done', 'urltext' : phrase, 'lp' : from_code + '_' + to_code, 'ienc' : 'utf8' } ) logger.debug("translateByCode - URL encoding: %s", params) try: req = urllib2.Request('http://world.altavista.com/babelfish/tr') req.add_header('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7') response = urllib2.urlopen(req, params) except IOError, what: raise BabelfishIOError("Couldn't talk to server: %s" % (what,)) except: logger.exception("translateByCode - unexpected error: %s", sys.exc_info()[0]) html = response.read() for regex in __where: match = regex.search(html) if match: break if not match: raise BabelfishChangedError("Can't recognize translated string.") logger.debug("translateByCode - translation returned: %s", clean(match.group(1))) return clean(match.group(1)) # inspired by chat code by pyczak@gmx.de def runServer(server): global inbound names = [] langs = {} ls = {} inbound = [server] outbound = [] error_track = [] while 1: r, w, e = select.select(inbound, outbound, error_track, 1.0) for sock in r: if sock == server: channel, info = server.accept() logger.debug("runServer - connection from: %s",info) data = channel.recv(1024) logger.debug("runServer - data received: %s", data) lst = data.split(",") name = lst[0] lang = lst[1] if name: if names.count(name) == 0 and len(names)<8: inbound.append(channel) names.append(name) langs[name] = lang ls[channel] = lang logger.debug("runServer - languages: %s", langs) channel.send("_CLIENT_ACCEPTED") logger.debug("runServer - client Nr. %s", len(names)) for i in range(len(names) + 1): if inbound[i] != server and names[i - 1] != name: data = "_NEW_CHATTER>" + name + "," + langs[name] logger.debug("runServer - sent message to client Nr. %s", i) inbound[i].send(data) elif len(names) >= 8: try: channel.send("_SERVER_FULL") finally: channel.close() else: try: channel.send("_NAME_ALREADY_EXISTS") finally: channel.close() else: logger.debug("runServer - processing client") data = sock.recv(1024) if data: logger.debug("runServer - received data: %s", repr(data)) if string.find(data, "_PRIVATE>") != -1: contents = data.split(":") sender = contents[0] contents = data.split(">") contents = contents[1].split(":") dest = contents[0] logger.debug("runServer - connected from: %s, Nr. %s" % (sender,names.index(sender),)) msg = sender + ": " + contents[1] + "_TRANS>" + sender + ": " + contents[1] if names.count(contents[0]) == 1: inbound[names.index(dest)+1].send(msg) elif string.find(data, "_NAMES>") != -1: contents = data.split(":") msg = "_NAMES>" for name in langs: msg = msg + ":" + name + "," + langs[name] inbound[names.index(contents[0])+1].send(msg) else: for i in range(len(names) + 1): if inbound[i] != server: logger.debug("runServer - sent message to client Nr. %s", i) item = inbound[i] dest_l = ls[item] if string.find(data, "_QUIT") == -1 and string.find(data, "_NAMES>") == -1: if string.find(data, "_TRANS>") != -1: content = data.split("_TRANS>") data = content[0] content = data.split(":") logger.debug("runServer - normalized content: %s", content) n = content[0] src_l = langs[n] # if source and destination are the same, leave text as it is if (src_l == dest_l): translated = content[1] logger.debug("runServer - -default translation: %s", translated) if TRANSLATE and (src_l != dest_l): if src_l == "en" and len(ABBRV) > 0: lst = content[1].split() print lst aux = [] for word in lst: if ABBRV.has_key(word.lower()): aux.append(ABBRV[word.lower()]) else: aux.append(word) content[1] = " ".join(aux) try: translated = translateByCode(content[1], src_l, dest_l) except Exception, e: logger.exception("runServer - error translating %s", e) translated = "Translation failed" logger.debug("runServer - translation service source: %s", src_l) logger.debug("runServer - translation service destination: %s", dest_l) logger.debug("runServer - translation service result: %s", translated) data = n + ": " + content[1] + "_TRANS>" + n + ": " + translated logger.debug("runServer - returned translated data: %s", data) inbound[i].send(data) if string.find(data, "_QUIT") != -1: try: inbound.remove(sock) contents=data.split(":") names.remove(contents[0]) del langs[contents[0]] finally: sock.close() else: try: inbound.remove(sock) finally: sock.close() time.sleep(0.2) # create logger logger = logging.getLogger("Jiim Server") logger.setLevel(logging.DEBUG) # create file handler and set level to info fh = logging.FileHandler("server.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) # run server application if sys.argv[1:]: if sys.argv[1] == "-t": if sys.argv[5:]: PORT = int(sys.argv[5]) else: PORT = 123450 else: PORT = int(sys.argv[1]) # load abbreviations, acronyms and alternate spellings try: fileHandle = open("abbreviations.txt", "r") fileList = fileHandle.readlines() for fileLine in fileList: lst = fileLine.split("=") if len(lst) > 1: key = lst[0].lower().strip() value = lst[1].lower().strip() ABBRV[key] = value fileHandle.close() logger.info("Loaded table of abbreviations, acronyms and alternate spellings") print "Loaded table of abbreviations, acronyms and alternate spellings" except Exception, e: ABBRV = {} logger.exception("Unable to load table of abbreviations, emoticons and alternate spellings. %s", e) print "Unable to load table of abbreviations, emoticons and alternate spellings." server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logger.info("Server started. Type 'QUIT' to exit.") print "Server started. Type 'QUIT' to exit." server.bind(("", PORT)) server.listen(1) #thread = Thread(target=runServer, args=(server,)) #thread.setDaemon(True) #thread.start() thread.start_new_thread(runServer,(server,)) logger.debug("Listening at Port %s", PORT) print "Listening at Port", PORT if sys.argv[1:]: print "0" if sys.argv[1] == "-t": TRANSLATE = False while 1: inmsg = sys.stdin.readline() if string.find(inmsg, "QUIT") != -1: logger.info("Server quiting") print "Server quiting" break try: for sock in range(len(names) + 1): if inbound[sock] != server: logger.debug("Closing remaining open sockets") inbound[sock].close() time.sleep(5) finally: logger.info("Server shut down") time.sleep(10) server.close()