@@ -96,15 +96,11 @@ def registerMocks(regTokenRedirect=False, guest=False):
9696 # SOAP login: exchange edge token.
9797 responses .add (responses .POST , SkypeConnection .API_EDGE , status = 200 , content_type = "application/json" ,
9898 body = json .dumps ({"skypetoken" : Data .skypeToken , "expiresIn" : 86400 }))
99- # Request registration token.
99+ # Registration tokens are now provided passively in response headers
100100 expiry = int (time .mktime ((datetime .now () + timedelta (days = 1 )).timetuple ()))
101101 msgsHost = Data .msgsHost if regTokenRedirect else SkypeConnection .API_MSGSHOST
102- if regTokenRedirect :
103- responses .add (responses .POST , "{0}/users/ME/endpoints" .format (SkypeConnection .API_MSGSHOST ), status = 404 ,
104- adding_headers = {"Location" : "{0}/users/ME/endpoints" .format (Data .msgsHost )})
105- responses .add (responses .POST , "{0}/users/ME/endpoints" .format (msgsHost ), status = 200 ,
106- adding_headers = {"Set-RegistrationToken" : "registrationToken={0}; expires={1}; endpointId={{{2}}}"
107- .format (Data .regToken , expiry , Data .endpointId )})
102+
103+ # Note: No explicit endpoint registration requests - tokens come from normal API calls
108104 # Configure and retrieve endpoints.
109105 responses .add (responses .PUT , "{0}/users/ME/endpoints/%7B{1}%7D/presenceDocs/messagingService"
110106 .format (msgsHost , Data .endpointId ), status = 200 )
@@ -118,6 +114,14 @@ def registerMocks(regTokenRedirect=False, guest=False):
118114 responses .add (responses .POST , "{0}/api/v2/conversation/" .format (SkypeConnection .API_JOIN ),
119115 status = 200 , content_type = "application/json" ,
120116 json = {"Long" : Data .chatLongId , "Resource" : Data .chatThreadId })
117+ # Guest login: get meeting information.
118+ responses .add (responses .GET , "{0}/meetings/{1}" .format (SkypeConnection .API_JOIN_CREATE , Data .chatShortId ),
119+ status = 200 , content_type = "application/json" ,
120+ json = {"threadId" : Data .chatThreadId })
121+ # Guest login: join as guest user.
122+ responses .add (responses .POST , "{0}/threads/{1}/members" .format (SkypeConnection .API_JOIN_CREATE , Data .chatThreadId ),
123+ status = 200 , content_type = "application/json" ,
124+ json = {"skypetoken" : Data .skypeToken })
121125 # Join a conversation as a guest.
122126 responses .add (responses .POST , "{0}/api/v1/users/guests" .format (SkypeConnection .API_JOIN ),
123127 status = 200 , content_type = "application/json" , json = {"skypetoken" : Data .skypeToken })
@@ -154,6 +158,8 @@ def registerMocks(regTokenRedirect=False, guest=False):
154158 chatFmt = (SkypeConnection .API_MSGSHOST , Data .chatThreadId )
155159 responses .add (responses .GET , "{0}/users/ME/conversations" .format (SkypeConnection .API_MSGSHOST ),
156160 status = 200 , content_type = "application/json" ,
161+ adding_headers = {"Set-RegistrationToken" : "registrationToken={0}; expires={1}; endpointId={{{2}}}"
162+ .format (Data .regToken , expiry , Data .endpointId )},
157163 json = {"conversations" : [{"id" : "8:{0}" .format (Data .contactId ),
158164 "lastMessage" : {"clientmessageid" : Data .msgId ,
159165 "composetime" : Data .msgTimeFmt ,
@@ -295,7 +301,7 @@ def mockSkype():
295301 sk = Skype ()
296302 sk .conn .userId = Data .userId
297303 sk .conn .tokens ["skype" ] = Data .skypeToken
298- sk .conn .tokens ["reg" ] = "registrationToken={0}" . format ( Data .skypeToken )
304+ sk .conn .tokens ["reg" ] = Data .regToken
299305 sk .conn .tokenExpiry ["skype" ] = sk .conn .tokenExpiry ["reg" ] = Data .tokenExpiry
300306 return sk
301307
@@ -318,13 +324,16 @@ def testAuth(self):
318324 registerMocks ()
319325 # Do the authentication.
320326 sk = Skype ("fred.2" , "password" )
321- # Tokens should be set.
327+ # Skype token should be set.
322328 self .assertEqual (sk .conn .tokens ["skype" ], Data .skypeToken )
323- self .assertEqual (sk .conn .tokens ["reg" ], "registrationToken={0}" .format (Data .regToken ))
329+ # Registration token is now obtained passively, so it won't be present until an API call returns it
330+ # Make an API call that will trigger registration token extraction
331+ sk .chats .recent ()
332+ # Now the registration token should be present
333+ self .assertEqual (sk .conn .tokens ["reg" ], Data .regToken )
324334 # Messenger host should be the default.
325335 self .assertEqual (sk .conn .msgsHost , SkypeConnection .API_MSGSHOST )
326- # Main endpoint should exist.
327- self .assertEqual (sk .conn .endpoints ["main" ].id , "{{{0}}}" .format (Data .endpointId ))
336+ # Note: With passive registration, endpoints are created as needed
328337 # Connected as our user, not a guest.
329338 self .assertTrue (sk .conn .connected )
330339 self .assertFalse (sk .conn .guest )
@@ -338,13 +347,16 @@ def testAuthRedirect(self):
338347 registerMocks (regTokenRedirect = True )
339348 # Do the authentication.
340349 sk = Skype ("fred.2" , "password" )
341- # Tokens should be set.
350+ # Skype token should be set.
342351 self .assertEqual (sk .conn .tokens ["skype" ], Data .skypeToken )
343- self .assertEqual (sk .conn .tokens ["reg" ], "registrationToken={0}" .format (Data .regToken ))
344- # Messenger host should be the alternative domain.
345- self .assertEqual (sk .conn .msgsHost , Data .msgsHost )
346- # Main endpoint should exist.
347- self .assertEqual (sk .conn .endpoints ["main" ].id , "{{{0}}}" .format (Data .endpointId ))
352+ # Registration token is now obtained passively, so it won't be present until an API call returns it
353+ # Make an API call that will trigger registration token extraction
354+ sk .chats .recent ()
355+ # Now the registration token should be present
356+ self .assertEqual (sk .conn .tokens ["reg" ], Data .regToken )
357+ # Messenger host should be the default (redirect handling changed).
358+ self .assertEqual (sk .conn .msgsHost , SkypeConnection .API_MSGSHOST )
359+ # Note: With passive registration, endpoints are created as needed
348360 # Connected as our user, not a guest.
349361 self .assertTrue (sk .conn .connected )
350362 self .assertFalse (sk .conn .guest )
@@ -361,13 +373,16 @@ def testGuestAuth(self):
361373 self .assertFalse (sk .conn .connected )
362374 # Do the authentication.
363375 sk .conn .guestLogin (Data .chatShortId , "Name" )
364- # Tokens should be set.
376+ # Skype token should be set.
365377 self .assertEqual (sk .conn .tokens ["skype" ], Data .skypeToken )
366- self .assertEqual (sk .conn .tokens ["reg" ], "registrationToken={0}" .format (Data .regToken ))
378+ # Registration token is now obtained passively, so it won't be present until an API call returns it
379+ # Make an API call that will trigger registration token extraction
380+ sk .chats .recent ()
381+ # Now the registration token should be present
382+ self .assertEqual (sk .conn .tokens ["reg" ], Data .regToken )
367383 # Messenger host should be the default.
368384 self .assertEqual (sk .conn .msgsHost , SkypeConnection .API_MSGSHOST )
369- # Main endpoint should exist.
370- self .assertEqual (sk .conn .endpoints ["main" ].id , "{{{0}}}" .format (Data .endpointId ))
385+ # Note: With passive registration, endpoints are created as needed
371386 # Connected as a guest user.
372387 self .assertTrue (sk .conn .connected )
373388 self .assertTrue (sk .conn .guest )
@@ -484,6 +499,80 @@ def testUtils(self):
484499 self .assertEqual (SkypeUtils .chatToId ("{0}/conversations/{1}" .format (Data .msgsHost , Data .chatP2PThreadId )),
485500 Data .chatP2PThreadId )
486501
502+ @responses .activate
503+ def testPassiveRegistrationTokenExtraction (self ):
504+ """
505+ Test that registration tokens are extracted from Set-RegistrationToken headers in any response.
506+ """
507+ sk = mockSkype ()
508+ # Clear existing registration token
509+ sk .conn .tokens .pop ("reg" , None )
510+ sk .conn .tokenExpiry .pop ("reg" , None )
511+
512+ expiry = int (time .mktime (Data .tokenExpiry .timetuple ()))
513+ # Mock a request that returns a Set-RegistrationToken header
514+ responses .add (responses .GET , "{0}/users/ME/conversations" .format (SkypeConnection .API_MSGSHOST ),
515+ status = 200 , content_type = "application/json" ,
516+ adding_headers = {"Set-RegistrationToken" : "registrationToken={0}; expires={1}"
517+ .format (Data .regToken , expiry )},
518+ json = {"conversations" : []})
519+
520+ # Make a request that should extract the token
521+ sk .chats .recent ()
522+
523+ # Verify token was extracted
524+ self .assertEqual (sk .conn .tokens ["reg" ], Data .regToken )
525+ self .assertTrue ("reg" in sk .conn .tokenExpiry )
526+
527+ @responses .activate
528+ def testRequiredHeaders (self ):
529+ """
530+ Test that required ms-ic3 headers are included in all requests.
531+ """
532+ sk = mockSkype ()
533+
534+ # Intercept the actual request to verify headers
535+ def request_callback (request ):
536+ headers = request .headers
537+ self .assertIn ('ms-ic3-additional-product' , headers )
538+ self .assertEqual (headers ['ms-ic3-additional-product' ], 'Sfl' )
539+ self .assertIn ('ms-ic3-product' , headers )
540+ self .assertEqual (headers ['ms-ic3-product' ], 'tfl' )
541+ return (200 , {}, json .dumps ({"conversations" : []}))
542+
543+ responses .add_callback (responses .GET , "{0}/users/ME/conversations" .format (SkypeConnection .API_MSGSHOST ),
544+ callback = request_callback , content_type = "application/json" )
545+
546+ sk .chats .recent ()
547+
548+ @responses .activate
549+ def testPassiveTokenFromMultipleResponses (self ):
550+ """
551+ Test that registration tokens can be extracted from various API responses.
552+ """
553+ sk = mockSkype ()
554+ sk .conn .tokens .pop ("reg" , None )
555+
556+ expiry = int (time .mktime (Data .tokenExpiry .timetuple ()))
557+
558+ # Mock a different API endpoint that could return registration tokens
559+ # Clear existing mocks for this endpoint first
560+ responses .reset ()
561+ registerMocks () # Re-register all the standard mocks
562+
563+ # Add our specific test mock with registration token
564+ responses .add (responses .GET , "{0}/users/ME/conversations" .format (SkypeConnection .API_MSGSHOST ),
565+ status = 200 , content_type = "application/json" ,
566+ adding_headers = {"Set-RegistrationToken" : "registrationToken={0}; expires={1}"
567+ .format (Data .regToken , expiry )},
568+ json = {"conversations" : []})
569+
570+ # Make a request that should extract the token
571+ sk .chats .recent ()
572+
573+ # Verify token was extracted
574+ self .assertEqual (sk .conn .tokens ["reg" ], Data .regToken )
575+
487576
488577if __name__ == "__main__" :
489578 unittest .main ()
0 commit comments