Skip to content

Commit

Permalink
feat: add broadcasts list REST API wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
ihors-livestorm committed Jan 5, 2022
1 parent 09c1672 commit 32dd5cc
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 2 deletions.
14 changes: 14 additions & 0 deletions lib/opentok/broadcast_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require "opentok/broadcast"

module OpenTok
# A class for accessing an array of Broadcast objects.
class BroadcastList
# The total number of broadcasts.
attr_reader :total

def initialize(interface, json)
@total = json["count"]
super json["items"].map { |item| ::OpenTok::Broadcast.new interface, item }
end
end
end
19 changes: 19 additions & 0 deletions lib/opentok/broadcasts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ def find(broadcast_id)
Broadcast.new self, broadcast_json
end

# Returns a BroadcastList, which is an array of broadcasts that are completed and in-progress,
# for your API key.
#
# @param [Hash] options A hash with keys defining which range of broadcasts to retrieve.
# @option options [integer] :offset Optional. The index offset of the first broadcast. 0 is offset
# of the most recently started broadcast. 1 is the offset of the broadcast that started prior to
# the most recent broadcast. If you do not specify an offset, 0 is used.
# @option options [integer] :count Optional. The number of broadcasts to be returned. The maximum
# number of broadcasts returned is 1000.
# @option options [String] :session_id Optional. The session ID that broadcasts belong to.
# https://tokbox.com/developer/rest/#list_broadcasts
#
# @return [BroadcastList] An BroadcastList object, which is an array of Broadcast objects.
def all(options = {})
raise ArgumentError, "Limit is invalid" unless options[:count].nil? || (0..1000).include?(options[:count])

broadcast_list_json = @client.list_broadcasts(options[:offset], options[:count], options[:sessionId])
BroadcastList.new self, broadcast_list_json
end

# Stops an OpenTok broadcast
#
Expand Down
22 changes: 22 additions & 0 deletions lib/opentok/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,28 @@ def stop_broadcast(broadcast_id)
raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
end

def list_broadcasts(offset, count, session_id)
query = Hash.new
query[:offset] = offset unless offset.nil?
query[:count] = count unless count.nil?
query[:sessionId] = session_id unless session_id.nil?
response = self.class.get("/v2/project/#{@api_key}/broadcast", {
:query => query.empty? ? nil : query,
:headers => generate_headers,
})
case response.code
when 200
response
when 403
raise OpenTokAuthenticationError,
"Authentication failed while retrieving broadcasts. API Key: #{@api_key}"
else
raise OpenTokBroadcastError, "The broadcasts could not be retrieved."
end
rescue StandardError => e
raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
end

def layout_broadcast(broadcast_id, opts)
opts.extend(HashExtensions)
response = self.class.put("/v2/project/#{@api_key}/broadcast/#{broadcast_id}/layout", {
Expand Down
2 changes: 1 addition & 1 deletion lib/opentok/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module OpenTok
# @private
VERSION = '4.2.0'
VERSION = '4.3.0'
end
45 changes: 45 additions & 0 deletions sample/Broadcast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,51 @@ You will now see the participant in the broadcast.
end
```

### All broadcasts

Start by visiting the list page at <http://localhost:4567/all>. You will see a table that
displays all the broadcasts created with your API Key. If there are more than five, the next ones
can be seen by clicking the "Next →" link. If you click on the name of an archive, your browser
will start downloading the archive file. If you click the "Delete" link in the end of the row
for any archive, that archive will be deleted and no longer available. Some basic information like
when the archive was created, how long it is, and its status is also shown. You should see the
archives you created in the previous sections here.

We begin to see how this page is created by looking at the route handler for this URL:

```ruby
get '/all' do
page = (params[:page] || "1").to_i
offset = (page - 1) * 5
broadcasts = settings.opentok.broadcasts.all(:offset => offset, :count => 5)

show_previous = page > 1 ? '/all?page=' + (page-1).to_s : nil
show_next = broadcasts.total > (offset + 5) ? '/all?page=' + (page+1).to_s : nil

erb :all, :locals => {
:broadcasts => broadcasts,
:show_previous => show_previous,
:show_next => show_next
}
end
```

This view is paginated so that we don't potentially show hundreds of rows on the table, which would
be difficult for the user to navigate. So this code starts by figuring out which page needs to be
shown, where each page is a set of 5 archives. The `page` number is read from the request's query
string parameters as a string and then converted into an Integer. The `offset`, which represents how
many archives are being skipped is always calculated as five times as many pages that are less than
the current page, which is `(page - 1) * 5`. Now there is enough information to ask for a list of
archives from OpenTok, which we do by calling the `archives.all()` method of the `opentok` instance.
The parameter is an optional Hash that contains the offset, the count (which is always 5 in this
view). If we are not at the first page, we can pass the view a string that contains the relative URL
for the previous page. Similarly, we can also include one for the next page. Now the application
renders the view using that information and the partial list of archives.

At this point the template file `views/history.erb` handles looping over the array of archives and
outputting the proper information for each column in the table. It also places a link to the
download and delete routes around the archive's name and its delete button, respectively.

### Changing the layout classes for streams

In the host page, if you click on either the host or a participant video, that video gets
Expand Down
15 changes: 15 additions & 0 deletions sample/Broadcast/broadcast_sample.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ class BroadcastSample < Sinatra::Base
}
end

get '/all' do
page = (params[:page] || "1").to_i
offset = (page - 1) * 5
broadcasts = settings.opentok.broadcasts.all(:offset => offset, :count => 5)

show_previous = page > 1 ? '/all?page=' + (page-1).to_s : nil
show_next = broadcasts.total > (offset + 5) ? '/all?page=' + (page+1).to_s : nil

erb :all, :locals => {
:broadcasts => broadcasts,
:show_previous => show_previous,
:show_next => show_next
}
end

post '/start' do
opts = {
:maxDuration => params.key?("maxDuration") ? params[:maxDuration] : 7200,
Expand Down
46 changes: 46 additions & 0 deletions sample/Broadcast/views/all.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<div class="container bump-me">

<div class="body-content">

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Broadcasts List</h3>
</div>
<div class="panel-body">
<% if broadcasts.count > 0 %>
<table class="table">
<thead>
<tr>
<th>Created</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<% for item in broadcasts %>

<tr data-item-id="<%= item.id %>">
<td><%= Time.at(item.created_at/1000).strftime("%B %e, %Y at %I:%M %p") %></td>
<td><%= item.status %></td>
</tr>

<% end %>
</tbody>
</table>
<% else %>
<p>
There are no broadcasts currently. Try making one in the <a href="/host">host view</a>.
</p>
<% end %>
</div>
<div class="panel-footer">
<% if show_previous %>
<a href="<%= show_previous %>" class="pull-left">&larr; Previous</a>
<% end %>
&nbsp;
<% if show_next %>
<a href="<%= show_next %>" class="pull-right">Next &rarr;</a>
<% end %>
</div>
</div>
</div>
</div>
17 changes: 16 additions & 1 deletion sample/Broadcast/views/index.erb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,23 @@
</div>

</div>
<div class="col-lg-6 col-offset-1">

<div class="panel panel-default">
<div class="panel-heading">List of Broadcasts</div>
<div class="panel-body">
<p>
Click through to List of Broadcasts to see examples of using the
Broadcasting REST API to list broadcasts showing status (started,
stopped, available) and created at timestamp.
</p>
</div>
<div class="panel-footer">
<a class="btn btn-success" href="all">List of Broadcasts</a>
</div>
</div>

</div>

</div>
</div>
</div>
36 changes: 36 additions & 0 deletions spec/opentok/broadcasts_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,40 @@
expect(response).not_to be_nil
end

xcontext "for many broadcasts" do
it "should return all broadcasts", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do
broadcast_list = broadcasts.all
expect(broadcast_list).to be_an_instance_of OpenTok::BroadcastList
expect(broadcast_list.total).to eq 6
expect(broadcast_list.count).to eq 6
end

it "should return broadcasts with an offset", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do
broadcast_list = broadcasts.all :offset => 3
expect(broadcast_list).to be_an_instance_of OpenTok::BroadcastList
expect(broadcast_list.total).to eq 3
expect(broadcast_list.count).to eq 3
end

it "should return count number of broadcasts", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do
broadcast_list = broadcasts.all :count => 2
expect(broadcast_list).to be_an_instance_of OpenTok::BroadcastList
expect(broadcast_list.count).to eq 2
expect(broadcast_list.count).to eq 2
end

it "should return part of the broadcasts when using offset and count", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do
broadcast_list = broadcasts.all :count => 4, :offset => 2
expect(broadcast_list).to be_an_instance_of OpenTok::BroadcastList
expect(broadcast_list.count).to eq 4
expect(broadcast_list.count).to eq 4
end

it "should return session broadcasts", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do
broadcast_list = broadcasts.all :sessionId => session_id
expect(broadcast_list).to be_an_instance_of OpenTok::BroadcastList
expect(broadcast_list.total).to eq 3
expect(broadcast_list.count).to eq 3
end
end
end

0 comments on commit 32dd5cc

Please sign in to comment.