summaryrefslogtreecommitdiff
path: root/omegle/icq.py
blob: b134dd66db1c3d238ffe5067815abc420ecef3c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/python
# -*- vim: encoding: utf-8 -*-
# Yves Fischer, xapek.org 2009
import struct

#from twisted.words.protocols import oscar
from tlib import oscar
from twisted.internet import reactor, protocol, defer
from twisted.internet.protocol import ClientFactory

__all__ = ['ReconnectingOSCARLoginFactory', 'ExtendedBOSConnection']

CAP_TYPING  = '\x56\x3f\xc8\x09\x0b\x6f\x41\xbd\x9f\x79\x42\x26\x09\xdf\xa2\xf3'
class ExtendedBOSConnection( oscar.BOSConnection ):
    capabilities = [oscar.CAP_CHAT, CAP_TYPING]

    def __init__(self,username, cookie, authenticator = None): 
        oscar.BOSConnection.__init__(self, username, cookie)
        self.authenticator = authenticator
        print self.authenticator
 
    """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 state == '\x00\x00': #finish
                self.receiveTyping(user, 'finish')
            elif state == '\x00\x01': #idle
                self.receiveTyping(user, 'idle')
            elif state == '\x00\x02': #begin
                self.receiveTyping(user, 'begin')
            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 receiveTyping(self, user, state):
        pass
        
    def initDone( self ):
        self.requestSelfInfo()
        self.requestSSI().addCallback(self.gotBuddyList)

    def shutdown( self ):
        pass

    def updateBuddy(self, user):
        print 'updateBuddy %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, '')
 
    """message - utf8"""
    def receiveCleanMessage( self, user, message, flags ):
        raise NotImplementedError('receiveCleanMessage( self, user, message, flags )')

    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])
        return message

 
    def receiveMessage( self, user, multiparts, flags ):
        print 'icq: receiveMessage(%s,%s,%s)' % (user,multiparts,flags)
        if flags != None and 'auto' in flags:
            return #skip 'auto' messages

        # because i cant receive the 'buddy added signal' i auth on every message
        self.sendAuthorizationResponse(user.name, True, '')

        #cleanup message
        try:
            message = self._getMessage( multiparts )
            #filter qip \x00CHAR\x00CHAR - qip sucks at unicode?
            message = filter(lambda x: x!=u'\x00', message)

            self.receiveCleanMessage( user, message, flags )
        except Exception,e:
            print 'Exception: %s' % e

    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 sendMessage(self, user, messageUtf8):
        message = messageUtf8.encode('latin1','replace')
        oscar.BOSConnection.sendMessage(self,user,message)

    def connectionLost(self, reason):
        self.factory.clientConnectionLost(self, reason)

        oscar.BOSConnection.connectionLost(self,reason)

class ReconnectingOSCARFactory(protocol.ClientFactory):
    delay = 10.0
    BOSClass = oscar.BOSConnection
    def __init__(self, uid, cookie, password, host, port):
        self.uid = uid
        self.cookie = cookie
        self.password = password
        self.host = host
        self.port = port
    def buildProtocol(self, addr):
        p = self.BOSClass(self.uid, self.cookie)
        p.factory = self
        return p
    def clientConnectionLost(self, connector, reason):
        reactor.callLater(self.delay, self._reconnect)
    def _reconnect(self):
        print "_reconnect"
        f = ReconnectingOSCARLoginFactory(self.uid, self.password)
        f.BOSClass = self.BOSClass
        return reactor.connectTCP(self.host, self.port, f)

class Authenticator(oscar.OscarAuthenticator):
    BOSClass = oscar.BOSConnection
    def connectToBOS(self, host, port):
        f = ReconnectingOSCARFactory(self.username, self.cookie, self.password, host, port)
        f.BOSClass = self.BOSClass
        reactor.connectTCP(host, port, f)
        return defer.Deferred() #dummy

class ReconnectingOSCARLoginFactory(protocol.ReconnectingClientFactory):
    BOSClass = oscar.BOSConnection
    def __init__(self, uid, password):
        self.uid = uid
        self.password = password
    def buildProtocol(self, addr):
        p = Authenticator(self.uid, self.password)
        p.BOSClass = self.BOSClass
        p.factory = self
        return p
    ## only reconnect on *failures*
    def clientConnectionLost(self, con, reason):
        pass