Skip to content

Commit a93f26e

Browse files
normanarguetaManik Sachdeva
authored andcommitted
Added get_streams method to get the list of streams in a session (#135)
* Add list_streams API
1 parent 439141e commit a93f26e

File tree

7 files changed

+146
-16
lines changed

7 files changed

+146
-16
lines changed

README.rst

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,12 @@ Once a Session is created, you can send signals to everyone in the session or to
231231
# To send a signal to a specific connection in the session:
232232
opentok.signal(session_id, payload, connection_id)
233233
234-
Get Stream
234+
Working with Streams
235235
~~~~~~~~~~~~~~~~~~~~~
236236

237-
Use this method to get information on an OpenTok stream (or all streams in a session).
237+
You can get information about a stream by calling the `get_stream(session_id, stream_id)` method of the `OpenTok` class.
238238

239-
You can get information about a stream by calling the `get_stream(session_id, stream_id)` method of the `OpenTok` class, or by calling the `get_stream(stream_id)` method on the `Session` class.
240-
241-
The method return a Stream object that contains information of an OpenTok stream:
239+
The method returns a Stream object that contains information of an OpenTok stream:
242240

243241
* ``id``: The stream ID
244242
* ``videoType``: "camera" or "screen"
@@ -259,6 +257,24 @@ The method return a Stream object that contains information of an OpenTok stream
259257
print stream.name #stream name
260258
print stream.layoutClassList #['full']
261259
260+
Also, you can get information about all the streams in a session by calling the `list_streams(session_id)` method of the `OpenTok` class.
261+
262+
The method returns a StreamList object that contains a list of all the streams
263+
264+
.. code:: python
265+
266+
# To get all streams in a session:
267+
stream_list = opentok.list_streams(session_id)
268+
269+
# Getting the first stream of the list
270+
stream = stream_list.items[0]
271+
272+
# Stream properties:
273+
print stream.id #8b732909-0a06-46a2-8ea8-074e64d43422
274+
print stream.videoType #camera
275+
print stream.name #stream name
276+
print stream.layoutClassList #['full']
277+
262278
Force Disconnect
263279
~~~~~~~~~~~~~~~~~~~~~
264280

opentok/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
from .archives import Archive, ArchiveList, OutputModes
44
from .exceptions import OpenTokException, AuthError, ForceDisconnectError
55
from .version import __version__
6-
from .stream import Stream
6+
from .stream import Stream
7+
from .streamlist import StreamList

opentok/endpoints.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ def signaling_url(self, session_id, connection_id=None):
2626
url += '/signal'
2727
return url
2828

29-
def get_stream_url(self, session_id, stream_id):
30-
url = self.api_url + '/v2/project/' + self.api_key + '/session/' + session_id + '/stream/' + stream_id
29+
def get_stream_url(self, session_id, stream_id=None):
30+
""" this method returns the url to get streams information """
31+
url = self.api_url + '/v2/project/' + self.api_key + '/session/' + session_id + '/stream'
32+
if stream_id:
33+
url = url + '/' + stream_id
3134
return url
3235

3336
def force_disconnect_url(self, session_id, connection_id):

opentok/opentok.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from .session import Session
2424
from .archives import Archive, ArchiveList, OutputModes
2525
from .stream import Stream
26+
from .streamlist import StreamList
2627
from .exceptions import (
2728
OpenTokException,
2829
RequestError,
@@ -508,7 +509,7 @@ def signal(self, session_id, payload, connection_id=None):
508509
elif response.status_code == 413:
509510
raise SignalingError('The type string exceeds the maximum length (128 bytes), or the data string exceeds the maximum size (8 kB).')
510511
else:
511-
raise RequestError("An unexpected error occurred", response.status_code)
512+
raise RequestError('An unexpected error occurred', response.status_code)
512513

513514
def get_stream(self, session_id, stream_id):
514515
"""
@@ -535,6 +536,29 @@ def get_stream(self, session_id, stream_id):
535536
else:
536537
raise RequestError('An unexpected error occurred', response.status_code)
537538

539+
def list_streams(self, session_id):
540+
"""
541+
Returns a list of Stream objects that contains information of all
542+
the streams in a OpenTok session, with the following attributes:
543+
544+
-count: An integer that indicates the number of streams in the session
545+
-items: List of the Stream objects
546+
"""
547+
endpoint = self.endpoints.get_stream_url(session_id)
548+
549+
response = requests.get(
550+
endpoint, headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout
551+
)
552+
553+
if response.status_code == 200:
554+
return StreamList(response.json())
555+
elif response.status_code == 400:
556+
raise GetStreamError('Invalid request. This response may indicate that data in your request data is invalid JSON. Or it may indicate that you do not pass in a session ID or you passed in an invalid stream ID.')
557+
elif response.status_code == 403:
558+
raise AuthError('You passed in an invalid OpenTok API key or JWT token.')
559+
else:
560+
raise RequestError('An unexpected error occurred', response.status_code)
561+
538562
def force_disconnect(self, session_id, connection_id):
539563
"""
540564
Sends a request to disconnect a client from an OpenTok session

opentok/stream.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
1+
from datetime import datetime, date
2+
from six import iteritems, PY2, PY3, u
3+
import json
4+
from six.moves import map
5+
dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime) or isinstance(obj, date) else None
6+
7+
from .exceptions import GetStreamError
8+
19
class Stream(object):
2-
"""
3-
Represents an OpenTok stream
4-
"""
10+
"""
11+
Represents an OpenTok stream
12+
"""
13+
14+
def __init__(self, kwargs):
15+
self.id = kwargs.get('id')
16+
self.videoType = kwargs.get('videoType')
17+
self.name = kwargs.get('name')
18+
self.layoutClassList = kwargs.get('layoutClassList')
19+
20+
def attrs(self):
21+
"""
22+
Returns a dictionary of the Stream's attributes.
23+
"""
24+
return dict((k, v) for k, v in iteritems(self.__dict__))
525

6-
def __init__(self, kwargs):
7-
for key, value in kwargs.items():
8-
setattr(self, key, value)
26+
def json(self):
27+
"""
28+
Returns a JSON representation of the Stream.
29+
"""
30+
return json.dumps(self.attrs(), default=dthandler, indent=4)

opentok/streamlist.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from six import u
2+
import json
3+
from .opentok import Stream
4+
from .exceptions import GetStreamError
5+
6+
class StreamList(object):
7+
"""
8+
Represents a list of OpenTok stream objects
9+
"""
10+
11+
def __init__(self, values):
12+
self.count = values.get('count')
13+
self.items = list(map(lambda x: Stream(x), values.get('items', [])))
14+
15+
def __iter__(self):
16+
for x in self.items:
17+
yield x
18+
19+
def json(self):
20+
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)
21+
22+
def __getitem__(self, key):
23+
return self.items.get(key)
24+
25+
def __setitem__(self, key, item):
26+
raise GetStreamError(u('Cannot set item {0} for key {1} in Archive object').format(item, key))
27+
28+
def __len__(self):
29+
return len(self.items)

tests/test_get_stream.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import unittest
22
from six import text_type, u, b, PY2, PY3
3-
from opentok import OpenTok, Stream, __version__
3+
from opentok import OpenTok, Stream, StreamList, __version__
44
import httpretty
55
import json
66
import textwrap
@@ -83,3 +83,38 @@ def test_get_stream_with_name(self):
8383
expect(stream_response).to(have_property(u('name'), stream.name))
8484
expect(stream_response).to(have_property(u('layoutClassList'), stream.layoutClassList))
8585
expect(list(stream_response.layoutClassList)).to(have_length(1))
86+
87+
@httpretty.activate
88+
def test_get_stream_list(self):
89+
httpretty.register_uri(
90+
httpretty.GET,
91+
u('https://api.opentok.com/v2/project/{0}/session/{1}/stream').format(self.api_key, self.session_id),
92+
body=textwrap.dedent(u("""\
93+
{
94+
"count": 2,
95+
"items": [
96+
{
97+
"id": "8b732909-0a06-46a2-8ea8-074e64d43422",
98+
"videoType": "camera",
99+
"name": "stream1",
100+
"layoutClassList": ["full"]
101+
},
102+
{
103+
"id": "7b732909-0a06-46a2-8ea8-074e64d43423",
104+
"videoType": "camera",
105+
"name": "stream2",
106+
"layoutClassList": ["full"]
107+
}
108+
]
109+
}""")),
110+
status=200,
111+
content_type=u('application/json')
112+
)
113+
114+
stream_list = self.opentok.list_streams(self.session_id)
115+
validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')])
116+
expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__))
117+
expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json')))
118+
expect(stream_list).to(be_an(StreamList))
119+
expect(stream_list).to(have_property(u('count'), 2))
120+
expect(list(stream_list.items)).to(have_length(2))

0 commit comments

Comments
 (0)