2121from .version import __version__
2222from .session import Session
2323from .archives import Archive , ArchiveList , OutputModes
24- from .exceptions import OpenTokException , RequestError , AuthError , NotFoundError , ArchiveError
24+ from .exceptions import OpenTokException , RequestError , AuthError , NotFoundError , ArchiveError , SignalingError
2525
2626class Roles (Enum ):
2727 """List of valid roles for a token."""
@@ -293,7 +293,7 @@ def headers(self):
293293 'X-OPENTOK-AUTH' : self ._create_jwt_auth_header ()
294294 }
295295
296- def archive_headers (self ):
296+ def json_headers (self ):
297297 """For internal use."""
298298 result = self .headers ()
299299 result ['Content-Type' ] = 'application/json'
@@ -311,6 +311,17 @@ def archive_url(self, archive_id=None):
311311 url = url + '/' + archive_id
312312 return url
313313
314+ def signaling_url (self , session_id , connection_id = None ):
315+ """For internal use."""
316+ url = self .api_url + '/v2/project/' + self .api_key + '/session/' + session_id
317+
318+ if connection_id :
319+ url += '/connection/' + connection_id
320+
321+ url += '/signal'
322+
323+ return url
324+
314325 def start_archive (self , session_id , has_audio = True , has_video = True , name = None , output_mode = OutputModes .composed , resolution = None ):
315326 """
316327 Starts archiving an OpenTok session.
@@ -361,7 +372,7 @@ def start_archive(self, session_id, has_audio=True, has_video=True, name=None, o
361372 'resolution' : resolution ,
362373 }
363374
364- response = requests .post (self .archive_url (), data = json .dumps (payload ), headers = self .archive_headers (), proxies = self .proxies , timeout = self .timeout )
375+ response = requests .post (self .archive_url (), data = json .dumps (payload ), headers = self .json_headers (), proxies = self .proxies , timeout = self .timeout )
365376
366377 if response .status_code < 300 :
367378 return Archive (self , response .json ())
@@ -394,7 +405,7 @@ def stop_archive(self, archive_id):
394405
395406 :rtype: The Archive object corresponding to the archive being stopped.
396407 """
397- response = requests .post (self .archive_url (archive_id ) + '/stop' , headers = self .archive_headers (), proxies = self .proxies , timeout = self .timeout )
408+ response = requests .post (self .archive_url (archive_id ) + '/stop' , headers = self .json_headers (), proxies = self .proxies , timeout = self .timeout )
398409
399410 if response .status_code < 300 :
400411 return Archive (self , response .json ())
@@ -417,7 +428,7 @@ def delete_archive(self, archive_id):
417428
418429 :param String archive_id: The archive ID of the archive to be deleted.
419430 """
420- response = requests .delete (self .archive_url (archive_id ), headers = self .archive_headers (), proxies = self .proxies , timeout = self .timeout )
431+ response = requests .delete (self .archive_url (archive_id ), headers = self .json_headers (), proxies = self .proxies , timeout = self .timeout )
421432
422433 if response .status_code < 300 :
423434 pass
@@ -435,7 +446,7 @@ def get_archive(self, archive_id):
435446
436447 :rtype: The Archive object.
437448 """
438- response = requests .get (self .archive_url (archive_id ), headers = self .archive_headers (), proxies = self .proxies , timeout = self .timeout )
449+ response = requests .get (self .archive_url (archive_id ), headers = self .json_headers (), proxies = self .proxies , timeout = self .timeout )
439450
440451 if response .status_code < 300 :
441452 return Archive (self , response .json ())
@@ -464,7 +475,7 @@ def get_archives(self, offset=None, count=None):
464475 if count is not None :
465476 params ['count' ] = count
466477
467- response = requests .get (self .archive_url () + "?" + urlencode (params ), headers = self .archive_headers (), proxies = self .proxies , timeout = self .timeout )
478+ response = requests .get (self .archive_url () + "?" + urlencode (params ), headers = self .json_headers (), proxies = self .proxies , timeout = self .timeout )
468479
469480 if response .status_code < 300 :
470481 return ArchiveList (self , response .json ())
@@ -475,6 +486,42 @@ def get_archives(self, offset=None, count=None):
475486 else :
476487 raise RequestError ("An unexpected error occurred" , response .status_code )
477488
489+ def signal (self , session_id , payload , connection_id = None ):
490+ """
491+ Send signals to all participants in an active OpenTok session or to a specific client
492+ connected to that session.
493+
494+ :param String session_id: The session ID of the OpenTok session that receives the signal
495+
496+ :param Dictionary payload: Structure that contains both the type and data fields. These
497+ correspond to the type and data parameters passed in the client signal received handlers
498+
499+ :param String connection_id: The connection_id parameter is an optional string used to
500+ specify the connection ID of a client connected to the session. If you specify this value,
501+ the signal is sent to the specified client. Otherwise, the signal is sent to all clients
502+ connected to the session
503+ """
504+ response = requests .post (
505+ self .signaling_url (session_id , connection_id ),
506+ data = json .dumps (payload ),
507+ headers = self .json_headers (),
508+ proxies = self .proxies ,
509+ timeout = self .timeout
510+ )
511+
512+ if response .status_code == 204 :
513+ pass
514+ elif response .status_code == 400 :
515+ raise SignalingError ('One of the signal properties - data, type, sessionId or connectionId - is invalid.' )
516+ elif response .status_code == 403 :
517+ raise AuthError ('You are not authorized to send the signal. Check your authentication credentials.' )
518+ elif response .status_code == 404 :
519+ raise SignalingError ('The client specified by the connectionId property is not connected to the session.' )
520+ elif response .status_code == 413 :
521+ raise SignalingError ('The type string exceeds the maximum length (128 bytes), or the data string exceeds the maximum size (8 kB).' )
522+ else :
523+ raise RequestError ("An unexpected error occurred" , response .status_code )
524+
478525 def _sign_string (self , string , secret ):
479526 return hmac .new (secret .encode ('utf-8' ), string .encode ('utf-8' ), hashlib .sha1 ).hexdigest ()
480527
0 commit comments