#!/usr/bin/python import struct,sys from twisted.python import log from twisted.words.protocols import oscar from twisted.internet import reactor, protocol from random import randint uin = '370496181' password = 'megahal123' host, port = ('login.oscar.aol.com', 5190) class Member(object): def __init__(self,id,name): self.id = id self.name = name class Room(object): def __init__(self): self.members = [] self.msg_cbs = [] def addMessageCallback(self,cb): self.msg_cbs.append(cb) def removeMessageCallback(self,cb): self.msg_cbs.remove(cb) def join(self,member): self.members.append(member) def leave(self,member): self.members.remove(member) def getMemberById(self,id): l=filter(lambda member: member.id == id, self.members) if len(l) > 0: return l[0] else: return None instance = None @classmethod def getInstance(klass): if klass.instance == None: klass.instance = Room() return klass.instance CAP_TYPING = '\x56\x3f\xc8\x09\x0b\x6f\x41\xbd\x9f\x79\x42\x26\x09\xdf\xa2\xf3' class icqBot( oscar.BOSConnection ): capabilities = [oscar.CAP_CHAT,CAP_TYPING] def __init__(self,*args,**kwargs): print "__INI",args,kwargs oscar.BOSConnection.__init__(self,*args,**kwargs) def initDone( self ): self.requestSelfInfo() self.requestSSI().addCallback(self.gotBuddyList) self.room = Room.getInstance() self.members = dict() def oscar_04_14(self,snac): pass #TODO: handle typing event - see omegle_icq.py def updateBuddy(self, user): print "Update buddy %s" % user def gotBuddyList( self, buddylist ): self.activateSSI() self.setProfile("Forget ICQ, MSN, Yahoo and the other shitty protocols! Use Jabber!") self.setIdleTime( 0 ) self.clientReady() for user in buddylist[0][0].users: self.sendAuthorizationResponse(user.name, True, '') print buddylist def _getMessage(self,multiparts): message = None if len(multiparts[0]) == 2: if multiparts[0][1] == "unicode": message = unicode(multiparts[0][0]) else: message = multiparts[0][0].decode(multiparts[0][1],'latin1') else: message = str(multiparts[0][0]) #filter qip \x00CHAR\x00CHAR - qip sucks at unicode? message = filter(lambda x: x!=u"\x00", message) return message def sendMessage(self, user, messageUtf8): message = messageUtf8.encode('latin1','replace') oscar.BOSConnection.sendMessage(self,user,message) def receiveMessage( self, user, multiparts, flags ): try: try: message = self._getMessage(multiparts) except Exception,e: print e self.sendMessage(user.name, str(e)) return if self.room.getMemberById(user.name) != None: member = self.room.getMemberById(user.name) if message.strip() == "/leave": self.room.leave(member) self.sendMessage(user.name, 'You left') for otherMember in self.room.members: self.sendMessage(otherMember.id, "===== %s/%s left"%(member.name,member.id) ) elif message.strip().startswith("/invite"): otherUin = message.strip().split("/invite")[1].strip() self.sendMessage(otherUin, "Youre invited by %s to join this room!, Type \" /join nickname\""%(user.name)) self.sendMessage(member.id, "Invitation sent to %s"%otherUin) elif message.strip().startswith("/nick"): newNick = message.strip().split("/nick")[1] for otherMember in self.room.members: self.sendMessage(otherMember.id, "===== %s now known as %s" % (member.name,newNick)) member.name = newNick elif message.strip().startswith("/msg"): otherNick = message.strip().split("/msg")[1].strip().split(" ")[0] otherMember = filter(lambda m: m.name == otherNick, self.room.members) if len(otherMember) == 0: self.sendMessage(member.id, "===== Nick %s gibts nicht!" % otherNick) else: self.sendMessage(otherMember[0].id, "=== Privat von %s/%s: %s" % (member.name,member.id,message)) elif message.strip() == "/list": self.sendMessage(member.id, "===== List: %s"%", ".join(map(lambda m: "%s/%s"%(m.id,m.name),self.room.members)) ) elif message.strip().startswith("/"): self.sendMessage(member.id, "===== kennich nicht") else: i=0 for otherMember in self.room.members: i += 1 if otherMember.id == user.name: continue reactor.callLater(i, self.sendMessage, otherMember.id, "%s: %s" %(member.name, message.strip())) else: if message.strip().startswith("/join"): nick = message.strip().split("/join")[1].strip() member = Member(user.name, nick) self.room.join(member) i=0 for otherMember in self.room.members: i += 1 reactor.callLater(i, self.sendMessage, otherMember.id, "===== %s/%s joined" % (member.name,member.id)) # self.sendMessage(otherMember.id, "===== %s/%s joined" % (member.name,member.id)) else: if randint(0,5) == 3: self.sendMessage(user.name, "Use '/join Nickname' or ' /join Nickname'") self.sendAuthorizationResponse(user.name, True, '') except Exception,e: print "error: %s %s\n%s" % (user,multiparts,e) def chatReceiveMessage( self, chat, user, message ): self.receiveMessage( self, user, message, 0 ) """ def receiveSendFileRequest(self, *args): # def receiveSendFileRequest(self, user, file, description, cookie): print args """ 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) def connectionLost(self,*args,**kwargs): print "Connection lost" oscar.BOSConnection.connectionLost(self,*args,**kwargs) class ReconnectingOSCARFactory(protocol.ClientFactory): delay = 10.0 protocol = icqBot def __init__(self, un, cookie): self.un = un self.cookie = cookie def buildProtocol(self, addr): p = self.protocol(self.un, self.cookie) p.factory = self return p def clientConnectionLost(self, connector, reason): reactor.callLater(self.delay, self._reconnect) def _reconnect(self): f = ReconnectingOSCARLoginFactory(uin, password) return reactor.connectTCP(host, port, f) class OscarCrap( oscar.OscarAuthenticator ): BOSClass = icqBot connectfactory = ReconnectingOSCARFactory def connectToBOS(self, server, port): f = self.connectfactory(self.username, self.cookie) return reactor.connectTCP(server, int(port), f) class ReconnectingOSCARLoginFactory(protocol.ReconnectingClientFactory): protocol = OscarCrap def __init__(self, sn, pass_): self.sn = sn self.pass_ = pass_ def buildProtocol(self, addr): p = self.protocol(self.sn, self.pass_, icq=1) p.factory = self return p ## only reconnect on *failures* def clientConnectionLost(self, con, reason): pass if __name__ == '__main__': log.startLogging(sys.stdout) f = ReconnectingOSCARLoginFactory(uin, password) reactor.connectTCP(host, port, f) reactor.run()