summaryrefslogtreecommitdiff
path: root/omegle
diff options
context:
space:
mode:
Diffstat (limited to 'omegle')
-rw-r--r--omegle/__init__.py269
-rw-r--r--omegle/icqBuddy.py224
-rw-r--r--omegle/icqChatroomBuddy.py37
3 files changed, 530 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)
+
diff --git a/omegle/icqBuddy.py b/omegle/icqBuddy.py
new file mode 100644
index 0000000..f162a7c
--- /dev/null
+++ b/omegle/icqBuddy.py
@@ -0,0 +1,224 @@
+#!/usr/bin/python
+# -*- vim: encoding: utf-8 -*-
+import struct
+import sys
+import thread
+
+from twisted.words.protocols import oscar
+from twisted.internet import reactor, protocol
+from twisted.internet.protocol import ClientFactory
+from twisted.python import log
+
+from omegle import OmegleChat
+
+ICQ_UIN = '446323989'
+ICQ_PASSWORD = 'gagaga'
+
+class OmegleICQChat(OmegleChat):
+ def __init__(self,icqconn,user):
+ self.user = user
+ self.icqconn = icqconn
+ OmegleChat.__init__(self,name="omegle")
+
+ def on_message(self,message):
+ self.send_icqconn( message )
+
+ def send_icqconn(self,message):
+ #send stopped typing snac
+ reactor.callFromThread(self.icqconn.sendSNAC, 0x04, 0x14, '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'+chr(len(self.user))+self.user+"\x00\x00")
+ #von omegle kommt immer unicode, icq sendet latin1/iso-8859-1
+ message = unicode(message)
+ message = message.encode("iso-8859-1","replace")
+ print "Omegle->%s: %s" % (self.user,message.__repr__())
+ reactor.callFromThread(self.icqconn.sendMessage, self.user, message )
+
+ def on_typing(self):
+ """
+ 0x02 begin
+ 0x01 idle
+ 0x00 finish
+ """
+ reactor.callFromThread(self.icqconn.sendSNAC, 0x04, 0x14, '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'+chr(len(self.user))+self.user+"\x00\x02")
+ print "Omegle->%s: (begin typing)" % self.user
+
+ def on_stopped_typing(self):
+ reactor.callFromThread(self.icqconn.sendSNAC, 0x04, 0x14, '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'+chr(len(self.user))+self.user+"\x00\x01")
+
+ def on_connect(self):
+ print "Omegle->%s: (connected)" % self.user
+ self.send_icqconn( "== Sup dawg, we heard u need some stranger in ur chatroom, so we put a Stranger in ur chatroom so u can chat with him while u chat with others (until you type %disconnect% anywhere) ==" )
+
+ def on_disconnect(self):
+ print "Omegle->%s: (disconnected)" % self.user
+ self.send_icqconn( "==Stranger Disconnected ==" )
+
+CAP_TYPING = '\x56\x3f\xc8\x09\x0b\x6f\x41\xbd\x9f\x79\x42\x26\x09\xdf\xa2\xf3'
+# [4, 20, 0, 0, 2854066430L, '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\t222840035\x00\x02']
+
+class OmegleICQ( oscar.BOSConnection ):
+ capabilities = [oscar.CAP_CHAT,CAP_TYPING]
+
+ def __init__(self,s,p,**kwargs):
+ oscar.BOSConnection.__init__(self, s, p,**kwargs)
+
+ """
+ handles typing SNAC
+ """
+ def oscar_04_14(self,snac):
+ data = snac[3]
+ if len(data) == len("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\t222840035\x00\x02"):
+ user = data[11:20]
+ state = data[20:22]
+ if not self.omegleConns.has_key(user):
+ self.omegleConns[user] = OmegleICQChat(self,user)
+
+ if state == "\x00\x00": #finish
+ try:
+ self.omegleConns[user].stopped_typing()
+ except:
+ pass
+ elif state == "\x00\x01": #idle
+ pass
+ elif state == "\x00\x02": #begin
+ try:
+ self.omegleConns[user].typing()
+ except:
+ pass
+ else:
+ print "Unknown state in typing snac\nuser %s\ndata %s\nsnac %s\nstate %X%X" % (user,data,snac,state[0],sate[1])
+ else:
+ print "komisches tpying snac"
+
+ def initDone( self ):
+ self.requestSelfInfo()
+ self.requestSSI().addCallback(self.gotBuddyList)
+
+ self.omegleConns = {}
+
+ def shutdown( self ):
+ for conn in self.omegleConns:
+ if conn.is_connected:
+ conn.disconnect()
+
+ def updateBuddy(self, user):
+ print "icq: Update buddy %s" % user
+
+ def gotBuddyList( self, buddylist ):
+ self.activateSSI()
+ self.setProfile("Forget ICQ, MSN, Yahoo and the other shitty protocols! Use XMPP/Jabber!")
+ self.setIdleTime( 0 )
+ self.clientReady()
+ for user in buddylist[0][0].users:
+ print "icq: Authorize %s" % user.name
+ self.sendAuthorizationResponse(user.name, True, '')
+
+ def receiveMessage( self, user, multiparts, flags ):
+ print "icq: receiveMessage(%s,%s,%s)" % (user,multiparts,flags)
+ if "auto" in flags:
+ print "'auto' message, abort"
+ return
+
+ # because i cant receive the "budded added signal" i auth on every message
+ self.sendAuthorizationResponse(user.name, True, '')
+
+ if not self.omegleConns.has_key(user.name):
+ self.omegleConns[user.name] = OmegleICQChat(self,user.name)
+
+ try:
+ message = None
+ if len(multiparts[0]) == 2:
+ if multiparts[0][1] == "unicode":
+ message = unicode(multiparts[0][0])
+ else:
+ try:
+ message = multiparts[0][0].decode(multiparts[0][1])
+ except Exception,e:
+ self.sendMessage(user.name,str(e))
+ else:
+ try:
+ message = multiparts[0][0].decode('latin1')
+ except Exception,e:
+ self.sendMessage(user.name,str(e))
+
+ #filter qip \x00CHAR\x00CHAR - qip sucks at unicode?
+ message_neu = filter(lambda x: x!=u"\x00", message)
+ if len(message_neu) != len(message):
+ client_sucks = True
+ message = message_neu
+
+ if not self.omegleConns[user.name].is_connected:
+ if u"%connect%" in message:
+ self.omegleConns[user.name].start()
+ self.sendMessage(user.name, "Please stand by.....")
+ if client_sucks:
+ self.sendMessage(user.name, "Hey, dein ICQ-Client sendet scheiss")
+ else:
+ print "Not connected"
+# self.sendMessage(user.name, "Not connected, type >connect<")
+ elif self.omegleConns[user.name].is_connected and u"%disconnect%" in message:
+ try:
+ self.omegleConns[user.name].disconnect()
+ except Exception,e:
+ self.sendMessage(user.name, str(e))
+ self.sendMessage(user.name, "Disconnecting")
+ elif self.omegleConns[user.name].is_connected and not self.omegleConns[user.name].is_confirmed:
+ self.sendMessage(user.name, "Wait for connection confirm from omegle")
+ else:
+ try:
+ print "%s->Omegle: %s" % (user.name, message.__repr__())
+ self.omegleConns[user.name].send(message)
+ except Exception,e:
+ print "icq(%s): Error %s" % (user.name,e)
+ self.sendMessage(user.name,str(e))
+ except Exception,e:
+ print "error: %s %s -> %s" % (user,multiparts,e)
+
+ def chatReceiveMessage( self, chat, user, message ):
+ self.receiveMessage( self, user, message, 0 )
+
+ def sendAuthorizationResponse(self, uin, success, responsString):
+ packet = struct.pack("b", len(uin)) + uin
+ if success:
+ packet += struct.pack("b", 1)
+ else:
+ packet += struct.pack("b", 0)
+ packet += struct.pack(">H", len(responsString)) + responsString
+ self.sendSNACnr(0x13, 0x1a, packet)
+
+class Authenticator( oscar.OscarAuthenticator ):
+ BOSClass = OmegleICQ
+ def connectionLost(self,reason):
+ oscar.OscarAuthenticator.connectionLost(self,reason)
+ self.factory.connectionLost(reason)
+
+class OscarFactory(ClientFactory):
+ OAClass=Authenticator
+ def __init__(self, uid, password,icq=1):
+ self.uid = uid
+ self.password = password
+ self.icq = icq
+
+ def buildProtocol(self, addr):
+ p = OscarFactory.OAClass(self.uid, self.password,icq=self.icq)
+ p.factory = self
+ return p
+
+ def startedConnecting(self, connector):
+ print 'Started to connect to oscar'
+
+ def connectionLost(self,reason):
+ print "CONECTION LOST - start njew factory"
+ reactor.callLater(4.0, reactor.connectTCP,
+ 'login.icq.com', 5238, self)
+# reactor.connectTCP('login.icq.com', 5238, OscarFactory(self.uin, self.password,icq=1))
+
+
+if __name__ == '__main__':
+ import logging
+ logging.basicConfig(level=logging.INFO)
+
+ log.startLogging(sys.stdout)
+ reactor.connectTCP('login.icq.com', 5238,
+ OscarFactory(uin,password,icq=1))
+ reactor.run()
+
diff --git a/omegle/icqChatroomBuddy.py b/omegle/icqChatroomBuddy.py
new file mode 100644
index 0000000..d4c2edc
--- /dev/null
+++ b/omegle/icqChatroomBuddy.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+# -*- vim: encoding: utf-8 -*-
+import sys
+
+from twisted.words.protocols import oscar
+from twisted.internet import reactor, protocol
+from twisted.python import log
+
+from omegle.icqBuddy import OmegleICQ, OscarFactory
+
+ICQ_UIN = '446323989'
+ICQ_PASSWORD = 'gagaga'
+ICQ_CHATROOM_UID = '370496181'
+
+class OmegleICQChatroomBuddy( OmegleICQ ):
+ def gotBuddyList( self, buddylist ):
+ OmegleICQ.gotBuddyList( self, buddylist )
+ self.sendMessage(ICQ_CHATROOM_UID, "/join OMEGLE")
+ def shutdown( self ):
+ self.sendMessage(ICQ_CHATROOM_UID, "/leave")
+ OmegleICQ.shutdown(self)
+
+class Authenticator( oscar.OscarAuthenticator ):
+ BOSClass = OmegleICQChatroomBuddy
+
+class MyOscarFactory(OscarFactory):
+ BOSClass = Authenticator
+
+
+if __name__ == '__main__':
+ import logging
+ logging.basicConfig(level=logging.INFO)
+
+ log.startLogging(sys.stdout)
+ reactor.connectTCP('login.icq.com', 5238,
+ MyOscarFactory(ICQ_UIN,ICQ_PASSWORD,icq=1))
+ reactor.run()