diff options
Diffstat (limited to 'omegle/__init__.py')
-rw-r--r-- | omegle/__init__.py | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/omegle/__init__.py b/omegle/__init__.py new file mode 100644 index 0000000..528b629 --- /dev/null +++ b/omegle/__init__.py @@ -0,0 +1,269 @@ +import sys +import httplib +import socket +import urllib +import time +import json +import logging +from threading import Thread, Lock, Event + +__all__ = ['OmegleChat', 'get_count'] + +class Timer(Thread): + """ + This class defines a object that calls the function object + given as func every given interval in a Thread and stops immedietly after + stop() has been called + """ + def __init__(self,func,interval=0.50): + Thread.__init__(self) + self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__) + self.func = func + self.interval = interval + + self.running = False + + self.event = Event() + + def run(self): + self.running = True + while self.running: + self.func() + self.event.wait(self.interval) + self.event.clear() + self.logger.debug("self.running == False") + + def stop(self): + """ XXX break func() ? """ + self.running = False + self.event.set() + +class RESTClient(object): + """Some routines used for calling the webservice""" + headers = { + "Content-type": "application/x-www-form-urlencoded; charset=utf-8", + "Accept": "application/json" + } + def __init__(self,host,http_debuglevel=0): + self.host=host + self.conn_lock = Lock() + self.conn = httplib.HTTPConnection(host) + self.conn.set_debuglevel(http_debuglevel) + + def request(self,method,path,params): + self.conn_lock.acquire() + try: + headers = RESTClient.headers.copy() + headers['Host'] = self.host + headers['Content-Length'] = str(len(params)) + self.conn.request(method,path,params,headers) + resp = self.conn.getresponse() + finally: + self.conn_lock.release() + return resp + + +class OmegleChat(RESTClient): + def __init__(self,poll_interval=0.5,name="",host="omegle.com"): + self.name = name + self.poll_interval=poll_interval + RESTClient.__init__(self,host) + + self.timer = Timer(self._events, poll_interval) + self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__ + name) + self.is_confirmed = False #after getting a connection confirm + self.is_connected = False #after having self.id + + def start(self): + """Starts a chat session. You have to wait until + is_confirmed is set (or use on_connect)""" + self.logger.debug("/start host=%s" % self.host) + if self.is_connected: + self.logger.error("Already connected") + raise Exception("Already connected") + resp = RESTClient.request(self, "POST", "/start", {}) + body=resp.read() + id=body.split("\"") + if id.__len__() == 3: + self.id = id[1] + self.logger.info("Connected id=%s" % self.id) + #start /events polling + self.is_connected = True + self.timer = Timer(self._events, self.poll_interval) + self.timer.start() + else: + self.logger.error("Bad response: %s" % body) + raise Exception("Bad response: %s" % body) + + def disconnect(self): + """Close a chat session.""" + self.logger.debug("disconnect()") + self.is_confirmed = False + self.timer.stop() + if self.is_connected: + r = RESTClient.request(self,"POST", "/disconnect", urllib.urlencode({'id': self.id})) + body = r.read() + self.logger.debug("/disconnect sent. Read: %s" % body) + if body == "win": + self.is_connected = False + self.id = None + self.conn.close() + else: + raise Exception("/disconnect; Bad response: %s" % body) + + def _events(self): + """does use its own "HTTPConnection" because its called async from a thread""" + conn = httplib.HTTPConnection(self.host) + params = urllib.urlencode({'id' : self.id}) + headers = OmegleChat.headers.copy() + headers['Host'] = "omegle.com" + headers['Content-Length'] = str(len(params)) + conn.request("POST", + "/events", + params, + OmegleChat.headers) + r=conn.getresponse() + body=r.read() + self._dispatch_event(conn,body) + conn.close() + + def send(self,msg): + """Send a message to the Stranger + Arguments: + msg -- the message - in utf8 + """ + #if a raw string given, assume its utf8 + if msg.__class__ == str: + try: + msg = msg.decode("utf8") + except UnicodeDecodeError: + pass + #convert utf8 to RAW-utf8 + try: + msg = msg.encode("utf8") + except UnicodeEncodeError,e: + self.logger.critical(e) + + if not self.is_confirmed: + self.logger.error("Cant send message if not is_confirmed") + return ###XXX raise?? + + params = {'id':self.id,'msg':msg} + params = urllib.urlencode(params) + try: + r = RESTClient.request(self,"POST","/send",params) + except Exception,e: + self.logger.error("Error by /send request: %s" % e) + raise e + return + + body = r.read() + if body != "win": + self.logger.error("/send; Bad response %s" % body) + raise Exception("/send; Bad response %s" % body) + + def typing(self): + """Notify the Stranger that youre typing a message""" + r = RESTClient.request(self, "POST", "/typing", urllib.urlencode({'id':self.id})) + body = r.read() + if body != "win": + self.logger.error("/typing; Bad response %s" % body) + raise Exception("/typing; Bad response %s" % body) + + def stopped_typing(self): + """Notify the Stranger that youre stopped typing""" + r = RESTClient.request(self, "POST", "/stoppedtyping", urllib.urlencode({'id':self.id})) + body = r.read() + if body != "win": + self.logger.error("/stoppedtyping; Bad response %s" % body) + raise Exception("/stoppedtyping; Bad response %s" % body) + + def _dispatch_event(self,conn,body): + try: + data_set=json.read(body.decode("utf8")) + if not data_set: + self.on_idle() + return + for data in data_set: + if not self.is_connected: #in case of disconnect + break #stop dispatching messages + if data[0] == "typing": + self.on_typing() + elif data[0] == "gotMessage" and data.__len__() == 2: + self.on_message(data[1]) + elif data[0] == "connected": + self.is_confirmed = True + self.on_connect() + elif data[0] == "strangerDisconnected": + self.is_confirmed = False + self.is_connected = False + self.timer.stop() + self.on_disconnect() + elif data[0] == "stoppedTyping": + self.on_stopped_typing() + elif data[0] == "waiting": + self.on_wait() + else: + self.logger.error("Unknown JSON Data: %s" % body) + except json.ReadException: + self.logger.error("Json ReadException. Body: %s" % body) + + def on_idle(self): + self.logger.debug("event: no data received") + def on_message(self,message): + """To be overwritten""" + self.logger.info("<<< %s" % message) + def on_connect(self): + """To be overwritten""" + self.logger.info("Connection confirmed") + def on_typing(self): + """To be overwritten""" + self.logger.info("Stranger is typing") + def on_stopped_typing(self): + """To be overwritten""" + self.logger.info("Stranger stopped typing") + def on_disconnect(self): + """To be overwritten""" + self.logger.info("Stranger Disconnectet") + def on_wait(self): + """To be overwritten""" + self.logger.info("Server sent [\"waiting\"]") + +def get_count(host="omegle.com"): + """Return the number of current online omegle users""" + headers = { + "Host" : host, + "Content-type": "application/x-www-form-urlencoded; charset=utf-8", + "Accept": "application/json"} + conn = httplib.HTTPConnection(host) + conn.request("GET", + "/count", + urllib.urlencode({}), + headers) + body = conn.getresponse().read() + conn.close() + return body + +if __name__ == "__main__": + """Extrem einfacher Chat-Client""" + logging.basicConfig(level=logging.INFO) + print "Lets chat. Type \"quit\" to disconnect" + chat = OmegleChat() + def exit(): + OmegleChat.on_disconnect(chat) + sys.exit(0) + chat.on_disconnect = exit + chat.start() + while 1==1: + try: + cmd=sys.stdin.readline().strip() + except KeyboardInterrupt: + chat.disconnect() + break + if cmd=="quit": + chat.disconnect() + break + else: + print ">>> %s" % cmd + chat.send(cmd) + |