#!/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()