Skip to content

Commit 439141e

Browse files
normanarguetaManik Sachdeva
authored andcommitted
Adding 'force_disconnect()' method (#132)
*Add force_disconnect API
1 parent 1e407b6 commit 439141e

File tree

6 files changed

+138
-2
lines changed

6 files changed

+138
-2
lines changed

README.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,19 @@ The method return a Stream object that contains information of an OpenTok stream
259259
print stream.name #stream name
260260
print stream.layoutClassList #['full']
261261
262+
Force Disconnect
263+
~~~~~~~~~~~~~~~~~~~~~
264+
265+
Your application server can disconnect a client from an OpenTok session by calling the force_disconnect(session_id, connection_id) method of the OpenTok class, or the force_disconnect(connection_id) method of the Session class.
266+
267+
.. code:: python
268+
269+
session_id = 'SESSIONID'
270+
connection_id = 'CONNECTIONID'
271+
272+
# To send a request to disconnect a client:
273+
opentok.force_disconnect(session_id, connection_id)
274+
262275
Samples
263276
-------
264277

opentok/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .opentok import OpenTok, Roles, MediaModes, ArchiveModes
22
from .session import Session
33
from .archives import Archive, ArchiveList, OutputModes
4-
from .exceptions import OpenTokException
4+
from .exceptions import OpenTokException, AuthError, ForceDisconnectError
55
from .version import __version__
66
from .stream import Stream

opentok/endpoints.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,10 @@ def get_stream_url(self, session_id, stream_id):
3030
url = self.api_url + '/v2/project/' + self.api_key + '/session/' + session_id + '/stream/' + stream_id
3131
return url
3232

33+
def force_disconnect_url(self, session_id, connection_id):
34+
""" this method returns the force disconnect url endpoint """
35+
url = (
36+
self.api_url + '/v2/project/' + self.api_key + '/session/' +
37+
session_id + '/connection/' + connection_id
38+
)
39+
return url

opentok/exceptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,11 @@ class GetStreamError(OpenTokException):
4040
"""Indicates that the data in the request is invalid, or the session_id or stream_id
4141
are invalid"""
4242
pass
43+
44+
class ForceDisconnectError(OpenTokException):
45+
"""
46+
Indicates that there was a force disconnect specific problem:
47+
One of the arguments is invalid or the client specified by the connectionId property
48+
is not connected to the session
49+
"""
50+
pass

opentok/opentok.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
NotFoundError,
3131
ArchiveError,
3232
SignalingError,
33-
GetStreamError
33+
GetStreamError,
34+
ForceDisconnectError
3435
)
3536

3637
class Roles(Enum):
@@ -534,6 +535,31 @@ def get_stream(self, session_id, stream_id):
534535
else:
535536
raise RequestError('An unexpected error occurred', response.status_code)
536537

538+
def force_disconnect(self, session_id, connection_id):
539+
"""
540+
Sends a request to disconnect a client from an OpenTok session
541+
542+
:param String session_id: The session ID of the OpenTok session from which the
543+
client will be disconnected
544+
545+
:param String connection_id: The connection ID of the client that will be disconnected
546+
"""
547+
endpoint = self.endpoints.force_disconnect_url(session_id, connection_id)
548+
response = requests.delete(
549+
endpoint, headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout
550+
)
551+
552+
if response.status_code == 204:
553+
pass
554+
elif response.status_code == 400:
555+
raise ForceDisconnectError('One of the arguments - sessionId or connectionId - is invalid.')
556+
elif response.status_code == 403:
557+
raise AuthError('You are not authorized to forceDisconnect, check your authentication credentials.')
558+
elif response.status_code == 404:
559+
raise ForceDisconnectError('The client specified by the connectionId property is not connected to the session.')
560+
else:
561+
raise RequestError('An unexpected error occurred', response.status_code)
562+
537563
def _sign_string(self, string, secret):
538564
return hmac.new(secret.encode('utf-8'), string.encode('utf-8'), hashlib.sha1).hexdigest()
539565

tests/test_force_disconnect.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import unittest
2+
from six import u
3+
from expects import *
4+
import httpretty
5+
6+
from opentok import OpenTok, __version__, AuthError, ForceDisconnectError
7+
from .validate_jwt import validate_jwt_header
8+
9+
class OpenTokForceDisconnectTest(unittest.TestCase):
10+
"""" Class that contains test for force disconnect functionality """
11+
12+
def setUp(self):
13+
self.api_key = u('123456')
14+
self.api_secret = u('1234567890abcdef1234567890abcdef1234567890')
15+
self.opentok = OpenTok(self.api_key, self.api_secret)
16+
self.session_id = u('SESSIONID')
17+
self.connection_id = u('CONNECTIONID')
18+
19+
@httpretty.activate
20+
def test_force_disconnect(self):
21+
""" Method to test force disconnect functionality using an OpenTok instance """
22+
23+
httpretty.register_uri(
24+
httpretty.DELETE,
25+
u('https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}').format(
26+
self.api_key,
27+
self.session_id,
28+
self.connection_id
29+
),
30+
status=204,
31+
content_type=u('application/json')
32+
)
33+
34+
self.opentok.force_disconnect(self.session_id, self.connection_id)
35+
36+
validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')])
37+
expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__))
38+
expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json')))
39+
40+
@httpretty.activate
41+
def test_throws_force_disconnect_exception(self):
42+
""" This method should throw a ForceDisconnectError """
43+
44+
httpretty.register_uri(
45+
httpretty.DELETE,
46+
u('https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}').format(
47+
self.api_key,
48+
self.session_id,
49+
self.connection_id
50+
),
51+
status=400,
52+
content_type=u('application/json')
53+
)
54+
55+
self.assertRaises(
56+
ForceDisconnectError,
57+
self.opentok.force_disconnect,
58+
self.session_id,
59+
self.connection_id
60+
)
61+
62+
@httpretty.activate
63+
def test_throws_auth_exception(self):
64+
""" This method should throw an AuthError """
65+
66+
httpretty.register_uri(
67+
httpretty.DELETE,
68+
u('https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}').format(
69+
self.api_key,
70+
self.session_id,
71+
self.connection_id
72+
),
73+
status=403,
74+
content_type=u('application/json')
75+
)
76+
77+
self.assertRaises(
78+
AuthError,
79+
self.opentok.force_disconnect,
80+
self.session_id,
81+
self.connection_id
82+
)

0 commit comments

Comments
 (0)