opentok 0.1.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -2
  3. data/.travis.yml +6 -0
  4. data/.yardopts +1 -0
  5. data/CONTRIBUTING.md +47 -0
  6. data/DEVELOPING.md +91 -0
  7. data/LICENSE +19 -5
  8. data/README.md +170 -53
  9. data/Rakefile +10 -5
  10. data/doc/OpenTok.html +411 -0
  11. data/doc/OpenTok/Archive.html +1320 -0
  12. data/doc/OpenTok/ArchiveList.html +216 -0
  13. data/doc/OpenTok/Archives.html +1028 -0
  14. data/doc/OpenTok/Client.html +695 -0
  15. data/doc/OpenTok/OpenTok.html +1046 -0
  16. data/doc/OpenTok/OpenTokArchiveError.html +142 -0
  17. data/doc/OpenTok/OpenTokAuthenticationError.html +143 -0
  18. data/doc/OpenTok/OpenTokError.html +138 -0
  19. data/doc/OpenTok/Session.html +665 -0
  20. data/doc/OpenTok/TokenGenerator.html +204 -0
  21. data/doc/OpenTok/TokenGenerator/ClassMethods.html +187 -0
  22. data/doc/README.md +15 -0
  23. data/doc/_index.html +182 -0
  24. data/doc/class_list.html +54 -0
  25. data/doc/css/common.css +1 -0
  26. data/doc/css/full_list.css +57 -0
  27. data/doc/css/style.css +339 -0
  28. data/doc/file.README.html +87 -0
  29. data/doc/file_list.html +56 -0
  30. data/doc/frames.html +26 -0
  31. data/doc/index.html +87 -0
  32. data/doc/js/app.js +219 -0
  33. data/doc/js/full_list.js +178 -0
  34. data/doc/js/jquery.js +4 -0
  35. data/doc/method_list.html +227 -0
  36. data/doc/top-level-namespace.html +112 -0
  37. data/lib/opentok.rb +3 -14
  38. data/lib/opentok/archive.rb +92 -0
  39. data/lib/opentok/archive_list.rb +17 -0
  40. data/lib/opentok/archives.rb +120 -0
  41. data/lib/opentok/client.rb +125 -0
  42. data/lib/opentok/constants.rb +5 -0
  43. data/lib/opentok/exceptions.rb +10 -0
  44. data/lib/opentok/opentok.rb +174 -0
  45. data/lib/opentok/session.rb +76 -0
  46. data/lib/opentok/token_generator.rb +101 -0
  47. data/lib/opentok/version.rb +4 -0
  48. data/opentok.gemspec +29 -22
  49. data/sample/Archiving/Gemfile +4 -0
  50. data/sample/Archiving/README.md +212 -0
  51. data/sample/Archiving/archiving_sample.rb +80 -0
  52. data/sample/Archiving/public/css/sample.css +22 -0
  53. data/sample/Archiving/public/img/archiving-off.png +0 -0
  54. data/sample/Archiving/public/img/archiving-on-idle.png +0 -0
  55. data/sample/Archiving/public/img/archiving-on-message.png +0 -0
  56. data/sample/Archiving/public/js/host.js +37 -0
  57. data/sample/Archiving/public/js/participant.js +13 -0
  58. data/sample/Archiving/views/history.erb +65 -0
  59. data/sample/Archiving/views/host.erb +69 -0
  60. data/sample/Archiving/views/index.erb +48 -0
  61. data/sample/Archiving/views/layout.erb +29 -0
  62. data/sample/Archiving/views/participant.erb +55 -0
  63. data/sample/HelloWorld/Gemfile +4 -0
  64. data/sample/HelloWorld/README.md +123 -0
  65. data/sample/HelloWorld/hello_world.rb +27 -0
  66. data/sample/HelloWorld/public/js/helloworld.js +32 -0
  67. data/sample/HelloWorld/views/index.erb +21 -0
  68. data/spec/cassettes/OpenTok_Archives/should_create_archives.yml +48 -0
  69. data/spec/cassettes/OpenTok_Archives/should_create_named_archives.yml +49 -0
  70. data/spec/cassettes/OpenTok_Archives/should_delete_an_archive_by_id.yml +32 -0
  71. data/spec/cassettes/OpenTok_Archives/should_find_archives_by_id.yml +46 -0
  72. data/spec/cassettes/OpenTok_Archives/should_stop_archives.yml +48 -0
  73. data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_all_archives.yml +104 -0
  74. data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_archives_with_an_offset.yml +71 -0
  75. data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_count_number_of_archives.yml +60 -0
  76. data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_part_of_the_archives_when_using_offset_and_count.yml +82 -0
  77. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_default_sessions.yml +39 -0
  78. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions.yml +39 -0
  79. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_with_a_location_hint.yml +39 -0
  80. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions.yml +39 -0
  81. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_for_invalid_media_modes.yml +39 -0
  82. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_with_a_location_hint.yml +39 -0
  83. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_sessions_with_a_location_hint.yml +39 -0
  84. data/spec/matchers/token.rb +48 -0
  85. data/spec/opentok/archives_spec.rb +91 -0
  86. data/spec/opentok/opentok_spec.rb +144 -0
  87. data/spec/opentok/session_spec.rb +71 -0
  88. data/spec/shared/opentok_generates_tokens.rb +62 -0
  89. data/spec/shared/session_generates_tokens.rb +63 -0
  90. data/spec/spec_helper.rb +6 -7
  91. metadata +197 -59
  92. data/.rspec +0 -3
  93. data/CHANGES +0 -33
  94. data/doc/reference.md +0 -122
  95. data/lib/open_tok/archive.rb +0 -53
  96. data/lib/open_tok/archive_timeline_event.rb +0 -22
  97. data/lib/open_tok/archive_video_resource.rb +0 -28
  98. data/lib/open_tok/exception.rb +0 -50
  99. data/lib/open_tok/open_tok_sdk.rb +0 -198
  100. data/lib/open_tok/request.rb +0 -63
  101. data/lib/open_tok/role_constants.rb +0 -18
  102. data/lib/open_tok/session.rb +0 -25
  103. data/lib/open_tok/session_property_constants.rb +0 -30
  104. data/lib/open_tok/utils.rb +0 -10
  105. data/lib/open_tok/version.rb +0 -5
  106. data/sample/sample.rb +0 -26
  107. data/spec/cassettes/archives.yml +0 -83
  108. data/spec/cassettes/deleteArchive.yml +0 -91
  109. data/spec/cassettes/invalidSession.yml +0 -41
  110. data/spec/cassettes/session.yml +0 -46
  111. data/spec/cassettes/stitchArchive.yml +0 -42
  112. data/spec/opentok_exception_spec.rb +0 -38
  113. data/spec/opentok_spec.rb +0 -135
@@ -1,18 +1,7 @@
1
- =begin
2
- OpenTok Ruby Library
3
- http://www.tokbox.com/
4
-
5
- Copyright 2010 - 2012, TokBox, Inc.
6
-
7
- Last modified: 2012-08-28
8
- =end
9
-
10
- require 'rubygems'
1
+ require "opentok/version"
2
+ require "opentok/opentok"
11
3
 
4
+ # Namespace for classes and modules in the OpenTok 2.2 Ruby SDK.
12
5
  module OpenTok
13
6
 
14
- API_URL = 'http://api.opentok.com/hl'
15
-
16
- autoload :OpenTokSDK, 'open_tok/open_tok_sdk'
17
-
18
7
  end
@@ -0,0 +1,92 @@
1
+ require "active_support/inflector"
2
+
3
+ module OpenTok
4
+ # Represents an archive of an OpenTok session.
5
+ #
6
+ # @attr [int] created_at
7
+ # The time at which the archive was created, in milliseconds since the UNIX epoch.
8
+ #
9
+ # @attr [string] duration
10
+ # The duration of the archive, in milliseconds.
11
+ #
12
+ # @attr [string] id
13
+ # The archive ID.
14
+ #
15
+ # @attr [string] name
16
+ # The name of the archive. If no name was provided when the archive was created, this is set
17
+ # to null.
18
+ #
19
+ # @attr [string] partner_id
20
+ # The API key associated with the archive.
21
+ #
22
+ # @attr [string] reason
23
+ # For archives with the status "stopped", this can be set to "90 mins exceeded", "failure",
24
+ # "session ended", or "user initiated". For archives with the status "failed", this can be set
25
+ # to "system failure".
26
+ #
27
+ # @attr [string] session_id
28
+ # The session ID of the OpenTok session associated with this archive.
29
+ #
30
+ # @attr [float] size
31
+ # The size of the MP4 file. For archives that have not been generated, this value is set to 0.
32
+ #
33
+ # @attr [string] status
34
+ # The status of the archive, which can be one of the following:
35
+ #
36
+ # * "available" -- The archive is available for download from the OpenTok cloud.
37
+ # * "failed" -- The archive recording failed.
38
+ # * "started" -- The archive started and is in the process of being recorded.
39
+ # * "stopped" -- The archive stopped recording.
40
+ # * "uploaded" -- The archive is available for download from the the upload target
41
+ # S3 bucket.
42
+ #
43
+ # @attr [string] url
44
+ # The download URL of the available MP4 file. This is only set for an archive with the status set to
45
+ # "available"; for other archives, (including archives with the status "uploaded") this property is
46
+ # set to null. The download URL is obfuscated, and the file is only available from the URL for
47
+ # 10 minutes. To generate a new URL, call the Archive.listArchives() or OpenTok.getArchive() method.
48
+ class Archive
49
+
50
+ # @private
51
+ def initialize(interface, json)
52
+ @interface = interface
53
+ # TODO: validate json fits schema
54
+ @json = json
55
+ end
56
+
57
+ # A JSON encoded string representation of the archive
58
+ def to_json
59
+ @json.to_json
60
+ end
61
+
62
+ # Stops an OpenTok archive that is being recorded.
63
+ #
64
+ # Archives automatically stop recording after 90 minutes or when all clients have disconnected
65
+ # from the session being archived.
66
+ def stop
67
+ # TODO: validate returned json fits schema
68
+ @json = @interface.stop_by_id @json['id']
69
+ end
70
+
71
+ # Deletes an OpenTok archive.
72
+ #
73
+ # You can only delete an archive which has a status of "available" or "uploaded". Deleting an
74
+ # archive removes its record from the list of archives. For an "available" archive, it also
75
+ # removes the archive file, making it unavailable for download.
76
+ def delete
77
+ # TODO: validate returned json fits schema
78
+ @json = @interface.delete_by_id @json['id']
79
+ end
80
+
81
+ # @private ignore
82
+ def method_missing(method, *args, &block)
83
+ camelized_method = method.to_s.camelize(:lower)
84
+ if @json.has_key? camelized_method and args.empty?
85
+ # TODO: convert create_time method call to a Time object
86
+ @json[camelized_method]
87
+ else
88
+ super method, *args, &block
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,17 @@
1
+ require "opentok/archive"
2
+
3
+ module OpenTok
4
+ # A class for accessing an array of Archive objects.
5
+ class ArchiveList < Array
6
+
7
+ # The total number archives.
8
+ attr_reader :total
9
+
10
+ # @private
11
+ def initialize(interface, json)
12
+ @total = json['count']
13
+ super json['items'].map { |item| Archive.new interface, item }
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,120 @@
1
+ require "opentok/client"
2
+ require "opentok/archive"
3
+ require "opentok/archive_list"
4
+
5
+ module OpenTok
6
+ # A class for working with OpenTok 2.0 archives.
7
+ class Archives
8
+
9
+ # @private
10
+ def initialize(client)
11
+ @client = client
12
+ end
13
+
14
+ # Starts archiving an OpenTok 2.0 session.
15
+ #
16
+ # Clients must be actively connected to the OpenTok session for you to successfully start
17
+ # recording an archive.
18
+ #
19
+ # You can only record one archive at a time for a given session. You can only record archives
20
+ # of OpenTok server-enabled sessions; you cannot archive peer-to-peer sessions.
21
+ #
22
+ # @param [String] session_id The session ID of the OpenTok session to archive.
23
+ # @param [Hash] options A hash with the key 'name' or :name.
24
+ # @option options [String] :name This is the name of the archive. You can use this name
25
+ # to identify the archive. It is a property of the Archive object, and it is a property
26
+ # of archive-related events in the OpenTok.js library.
27
+ #
28
+ # @return [Archive] The Archive object, which includes properties defining the archive,
29
+ # including the archive ID.
30
+ #
31
+ # @raise [OpenTokArchiveError] The archive could not be started. The request was invalid or
32
+ # the session has no connected clients.
33
+ # @raise [OpenTokAuthenticationError] Authentication failed while starting an archive.
34
+ # Invalid API key.
35
+ # @raise [OpenTokArchiveError] The archive could not be started. The session ID does not exist.
36
+ # @raise [OpenTokArchiveError] The archive could not be started. The session could be
37
+ # peer-to-peer or the session is already being recorded.
38
+ # @raise [OpenTokArchiveError] The archive could not be started.
39
+ def create(session_id, options = {})
40
+ raise ArgumentError, "session_id not provided" if session_id.to_s.empty?
41
+ opts = Hash.new
42
+ opts[:name] = options[:name].to_s || options["name"].to_s
43
+ archive_json = @client.start_archive(session_id, opts)
44
+ Archive.new self, archive_json
45
+ end
46
+
47
+ # Gets an Archive object for the given archive ID.
48
+ #
49
+ # @param [String] archive_id The archive ID.
50
+ #
51
+ # @return [Archive] The Archive object.
52
+ # @raise [OpenTokArchiveError] The archive could not be retrieved. The archive ID is invalid.
53
+ # @raise [OpenTokAuthenticationError] Authentication failed while retrieving the archive.
54
+ # Invalid API key.
55
+ # @raise [OpenTokArchiveError] The archive could not be retrieved.
56
+ def find(archive_id)
57
+ raise ArgumentError, "archive_id not provided" if archive_id.to_s.empty?
58
+ archive_json = @client.get_archive(archive_id.to_s)
59
+ Archive.new self, archive_json
60
+ end
61
+
62
+ # Returns an ArchiveList, which is an array of archives that are completed and in-progress,
63
+ # for your API key.
64
+ #
65
+ # @param [Hash] options A hash with keys defining which range of archives to retrieve.
66
+ # @option options [integer] :offset Optional. The index offset of the first archive. 0 is offset
67
+ # of the most recently started archive. 1 is the offset of the archive that started prior to
68
+ # the most recent archive. If you do not specify an offset, 0 is used.
69
+ # @option options [integer] :count Optional. The number of archives to be returned. The maximum
70
+ # number of archives returned is 1000.
71
+ #
72
+ # @return [ArchiveList] An ArchiveList object, which is an array of Archive objects.
73
+ def all(options = {})
74
+ raise ArgumentError, "Limit is invalid" unless options[:count].nil? or (0..100).include? options[:count]
75
+ archive_list_json = @client.list_archives(options[:offset], options[:count])
76
+ ArchiveList.new self, archive_list_json
77
+ end
78
+
79
+ # Stops an OpenTok archive that is being recorded.
80
+ #
81
+ # Archives automatically stop recording after 90 minutes or when all clients have disconnected
82
+ # from the session being archived.
83
+ #
84
+ # @param [String] archive_id The archive ID of the archive you want to stop recording.
85
+ #
86
+ # @return [Archive] The Archive object corresponding to the archive being stopped.
87
+ #
88
+ # @raise [OpenTokArchiveError] The archive could not be stopped. The request was invalid.
89
+ # @raise [OpenTokAuthenticationError] Authentication failed while stopping an archive.
90
+ # @raise [OpenTokArchiveError] The archive could not be stopped. The archive ID does not exist.
91
+ # @raise [OpenTokArchiveError] The archive could not be stopped. The archive is not currently
92
+ # recording.
93
+ # @raise [OpenTokArchiveError] The archive could not be started.
94
+ def stop_by_id(archive_id)
95
+ raise ArgumentError, "archive_id not provided" if archive_id.to_s.empty?
96
+ archive_json = @client.stop_archive(archive_id)
97
+ Archive.new self, archive_json
98
+ end
99
+
100
+ # Deletes an OpenTok archive.
101
+ #
102
+ # You can only delete an archive which has a status of "available", "uploaded", or "deleted".
103
+ # Deleting an archive removes its record from the list of archives. For an "available" archive,
104
+ # it also removes the archive file, making it unavailable for download. For a "deleted"
105
+ # archive, the archive remains deleted.
106
+ #
107
+ # @param [String] archive_id The archive ID of the archive you want to delete.
108
+ #
109
+ # @raise [OpenTokAuthenticationError] Authentication failed or an invalid archive ID was given.
110
+ # @raise [OpenTokArchiveError] The archive could not be deleted. The status must be
111
+ # 'available', 'deleted', or 'uploaded'.
112
+ # @raise [OpenTokArchiveError] The archive could not be deleted.
113
+ def delete_by_id(archive_id)
114
+ raise ArgumentError, "archive_id not provided" if archive_id.to_s.empty?
115
+ response = @client.delete_archive(archive_id)
116
+ (200..300).include? response.code
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,125 @@
1
+ require "opentok/exceptions"
2
+
3
+ require "httparty"
4
+
5
+ module OpenTok
6
+ # @private For internal use by the SDK.
7
+ class Client
8
+ include HTTParty
9
+ # TODO: expose a setting for http debugging for developers
10
+ # debug_output $stdout
11
+
12
+ def initialize(api_key, api_secret, api_url)
13
+ self.class.base_uri api_url
14
+ self.class.headers({
15
+ "X-TB-PARTNER-AUTH" => "#{api_key}:#{api_secret}",
16
+ "User-Agent" => "OpenTok-Ruby-SDK/#{VERSION}"
17
+ })
18
+ @api_key = api_key
19
+ end
20
+
21
+ def create_session(opts)
22
+ response = self.class.post("/session/create", :body => opts)
23
+ case response.code
24
+ when (200..300)
25
+ response
26
+ when 403
27
+ raise OpenTokAuthenticationError, "Authentication failed while creating a session. API Key: #{@api_key}"
28
+ else
29
+ raise OpenTokError, "Failed to create session. Response code: #{response.code}"
30
+ end
31
+ end
32
+
33
+ def start_archive(session_id, opts)
34
+ body = { "sessionId" => session_id, "action" => "start" }
35
+ body["name"] = opts[:name] unless opts[:name].nil?
36
+ response = self.class.post("/v2/partner/#{@api_key}/archive", {
37
+ :body => body.to_json,
38
+ :headers => { "Content-Type" => "application/json" }
39
+ })
40
+ case response.code
41
+ when 200
42
+ response
43
+ when 400
44
+ raise OpenTokArchiveError, "The archive could not be started. The request was invalid or the session has no connected clients."
45
+ when 403
46
+ raise OpenTokAuthenticationError, "Authentication failed while starting an archive. API Key: #{@api_key}"
47
+ when 404
48
+ raise OpenTokArchiveError, "The archive could not be started. The Session ID does not exist: #{session_id}"
49
+ when 409
50
+ raise OpenTokArchiveError, "The archive could not be started. The session could be peer-to-peer or the session is already being recorded."
51
+ else
52
+ raise OpenTokArchiveError, "The archive could not be started"
53
+ end
54
+ end
55
+
56
+ def get_archive(archive_id)
57
+ response = self.class.get("/v2/partner/#{@api_key}/archive/#{archive_id}")
58
+ case response.code
59
+ when 200
60
+ response
61
+ when 400
62
+ raise OpenTokArchiveError, "The archive could not be retrieved. The Archive ID was invalid: #{archive_id}"
63
+ when 403
64
+ raise OpenTokAuthenticationError, "Authentication failed while retrieving an archive. API Key: #{@api_key}"
65
+ else
66
+ raise OpenTokArchiveError, "The archive could not be retrieved."
67
+ end
68
+ end
69
+
70
+ def list_archives(offset, count)
71
+ query = Hash.new
72
+ query[:offset] = offset unless offset.nil?
73
+ query[:count] = count unless count.nil?
74
+ response = self.class.get("/v2/partner/#{@api_key}/archive", {
75
+ :query => query.empty? ? nil : query
76
+ })
77
+ case response.code
78
+ when 200
79
+ response
80
+ when 403
81
+ raise OpenTokAuthenticationError, "Authentication failed while retrieving archives. API Key: #{@api_key}"
82
+ else
83
+ raise OpenTokArchiveError, "The archives could not be retrieved."
84
+ end
85
+ end
86
+
87
+ def stop_archive(archive_id)
88
+ response = self.class.post("/v2/partner/#{@api_key}/archive/#{archive_id}", {
89
+ :body => { "action" => "stop" }.to_json,
90
+ :headers => { "Content-Type" => "application/json" }
91
+ })
92
+ case response.code
93
+ when 200
94
+ response
95
+ when 400
96
+ raise OpenTokArchiveError, "The archive could not be stopped. The request was invalid."
97
+ when 403
98
+ raise OpenTokAuthenticationError, "Authentication failed while stopping an archive. API Key: #{@api_key}"
99
+ when 404
100
+ raise OpenTokArchiveError, "The archive could not be stopped. The Archive ID does not exist: #{archive_id}"
101
+ when 409
102
+ raise OpenTokArchiveError, "The archive could not be stopped. The archive is not currently recording."
103
+ else
104
+ raise OpenTokArchiveError, "The archive could not be started."
105
+ end
106
+ end
107
+
108
+ def delete_archive(archive_id)
109
+ response = self.class.delete("/v2/partner/#{@api_key}/archive/#{archive_id}", {
110
+ :headers => { "Content-Type" => "application/json" }
111
+ })
112
+ case response.code
113
+ when 204
114
+ response
115
+ when 403
116
+ raise OpenTokAuthenticationError, "Authentication failed or an invalid Archive ID was given while deleting an archive. API Key: #{@api_key}, Archive ID: #{archive_id}"
117
+ when 409
118
+ raise OpenTokArchiveError, "The archive could not be deleted. The status must be 'available', 'deleted', or 'uploaded'. Archive ID: #{archive_id}"
119
+ else
120
+ raise OpenTokArchiveError, "The archive could not be deleted."
121
+ end
122
+ end
123
+
124
+ end
125
+ end
@@ -0,0 +1,5 @@
1
+ module OpenTok
2
+ API_URL = "https://api.opentok.com"
3
+ TOKEN_SENTINEL = "T1=="
4
+ ROLES = { subscriber: "subscriber", publisher: "publisher", moderator: "moderator" }
5
+ end
@@ -0,0 +1,10 @@
1
+ module OpenTok
2
+
3
+ # Defines errors raised by methods of the OpenTok Ruby SDK.
4
+ class OpenTokError < StandardError; end
5
+ # Defines errors raised by archive-related methods of the OpenTok Ruby SDK.
6
+ class OpenTokArchiveError < OpenTokError; end
7
+ # Defines errors raised when you attempt an operation using an invalid OpenTok API key or secret.
8
+ class OpenTokAuthenticationError < OpenTokError; end
9
+
10
+ end
@@ -0,0 +1,174 @@
1
+ require "opentok/constants"
2
+ require "opentok/session"
3
+ require "opentok/client"
4
+ require "opentok/token_generator"
5
+ require "opentok/archives"
6
+
7
+ require "resolv"
8
+
9
+ module OpenTok
10
+ # Contains methods for creating OpenTok sessions, generating tokens, and working with archives.
11
+ #
12
+ # To create a new OpenTok object, call the OpenTok constructor with your OpenTok API key
13
+ # and the API secret from the OpenTok dashboard (https://dashboard.tokbox.com). Do not
14
+ # publicly share your API secret. You will use it with the OpenTok constructor (only on your web
15
+ # server) to create OpenTok sessions.
16
+ #
17
+ # @attr_reader [String] api_secret @private The OpenTok API secret.
18
+ # @attr_reader [String] api_key @private The OpenTok API key.
19
+ #
20
+ #
21
+ # @!method generate_token(options)
22
+ # Generates a token for a given session.
23
+ #
24
+ # @param [String] sessioin_id The session ID of the session to be accessed by the client using
25
+ # the token.
26
+ #
27
+ # @param [Hash] options A hash defining options for the token.
28
+ # @option options [String] :role The role for the token. Set this to one of the following
29
+ # values:
30
+ # * <code>:subscriber</code> -- A subscriber can only subscribe to streams.
31
+ #
32
+ # * <code>:publisher</code> -- A publisher can publish streams, subscribe to
33
+ # streams, and signal. (This is the default value if you do not specify a role.)
34
+ #
35
+ # * <code>:moderator</code> -- In addition to the privileges granted to a
36
+ # publisher, in clients using the OpenTok.js 2.2 library, a moderator can call the
37
+ # <code>forceUnpublish()</code> and <code>forceDisconnect()</code> method of the
38
+ # Session object.
39
+ # @option options [integer] :expire_time The expiration time, in seconds since the UNIX epoch.
40
+ # Pass in 0 to use the default expiration time of 24 hours after the token creation time.
41
+ # The maximum expiration time is 30 days after the creation time.
42
+ # @option options [String] :data A string containing connection metadata describing the
43
+ # end-user. For example, you can pass the user ID, name, or other data describing the
44
+ # end-user. The length of the string is limited to 1000 characters. This data cannot be
45
+ # updated once it is set.
46
+ # @return [String] The token string.
47
+ class OpenTok
48
+
49
+ include TokenGenerator
50
+ generates_tokens({
51
+ :api_key => ->(instance) { instance.api_key },
52
+ :api_secret => ->(instance) { instance.api_secret }
53
+ })
54
+
55
+ # @private
56
+ # don't want these to be mutable, may cause bugs related to inconsistency since these values are
57
+ # cached in objects that this can create
58
+ attr_reader :api_key, :api_secret, :api_url
59
+
60
+ ##
61
+ # Create a new OpenTok object.
62
+ #
63
+ # @param [String] api_key Your OpenTok API key. See the OpenTok dashboard
64
+ # (https://dashboard.tokbox.com).
65
+ # @param [String] api_secret Your OpenTok API key.
66
+ # @param [String] api_url Do not set this parameter. It is for internal use by TokBox.
67
+ def initialize(api_key, api_secret , api_url = ::OpenTok::API_URL)
68
+ @api_key = api_key.to_s()
69
+ @api_secret = api_secret
70
+ # TODO: do we really need a copy of this in the instance or should we overwrite the module
71
+ # constant so that other objects can access the same copy?
72
+ @api_url = api_url
73
+ end
74
+
75
+ # Creates a new OpenTok session and returns the session ID, which uniquely identifies
76
+ # the session.
77
+ #
78
+ # For example, when using the OpenTok JavaScript library, use the session ID when calling the
79
+ # OT.initSession()</a> method (to initialize an OpenTok session).
80
+ #
81
+ # OpenTok sessions do not expire. However, authentication tokens do expire (see the
82
+ # generateToken() method). Also note that sessions cannot explicitly be destroyed.
83
+ #
84
+ # A session ID string can be up to 255 characters long.
85
+ #
86
+ # Calling this method results in an OpenTokException in the event of an error.
87
+ # Check the error message for details.
88
+ #
89
+ # You can also create a session using the OpenTok REST API (see
90
+ # http://www.tokbox.com/opentok/api/#session_id_production) or the OpenTok dashboard
91
+ # (see https://dashboard.tokbox.com/projects).
92
+ #
93
+ # @param [Hash] opts (Optional) This hash defines options for the session.
94
+ #
95
+ # @option opts [String] :media_mode Determines whether the session will transmit streams the
96
+ # using OpenTok Media Router (<code>:routed</code>) or not (<code>:relayed</code>).
97
+ # By default, sessions use the OpenTok Media Router.
98
+ #
99
+ # With the <code>mediaMode</code> property set to <code>:routed</code>, the session
100
+ # will use the {http://tokbox.com/#multiparty OpenTok Media Router}.
101
+ # The OpenTok Media Router provides the following benefits:
102
+ #
103
+ # * The OpenTok Media Router can decrease bandwidth usage in multiparty sessions.
104
+ # (When the <code>mediaMode</code> property is set to <code>:relayed</code>,
105
+ # each client must send a separate audio-video stream to each client subscribing to
106
+ # it.)
107
+ # * The OpenTok Media Router can improve the quality of the user experience through
108
+ # {http://tokbox.com/#iqc Intelligent Quality Control}. With
109
+ # Intelligent Quality Control, if a client's connectivity degrades to a degree that
110
+ # it does not support video for a stream it's subscribing to, the video is dropped on
111
+ # that client (without affecting other clients), and the client receives audio only.
112
+ # If the client's connectivity improves, the video returns.
113
+ # * The OpenTok Media Router supports the {http://tokbox.com/platform/archiving archiving}
114
+ # feature, which lets you record, save, and retrieve OpenTok sessions.
115
+ #
116
+ # With the <code>mediaMode</code> property set to <code>:relayed</code>, the session
117
+ # will attempt to transmit streams directly between clients. If clients cannot connect due to
118
+ # firewall restrictions, the session uses the OpenTok TURN server to relay audio-video
119
+ # streams.
120
+ #
121
+ # You will be billed for streamed minutes if you use the OpenTok Media Router or if the
122
+ # session uses the OpenTok TURN server to relay streams. For information on pricing, see the
123
+ # {http://www.tokbox.com/pricing OpenTok pricing page}.
124
+ #
125
+ # @option opts [String] :location An IP address that the OpenTok servers will use to
126
+ # situate the session in its global network. If you do not set a location hint,
127
+ # the OpenTok servers will be based on the first client connecting to the session.
128
+ #
129
+ # @return [Session] The Session object. The session_id property of the object is the session ID.
130
+ def create_session(opts={})
131
+
132
+ # normalize opts so all keys are symbols and only include valid_opts
133
+ valid_opts = [ :media_mode, :location ]
134
+ opts = opts.inject({}) do |m,(k,v)|
135
+ if valid_opts.include? k.to_sym
136
+ m[k.to_sym] = v
137
+ end
138
+ m
139
+ end
140
+
141
+ # keep opts around for Session constructor, build REST params
142
+ params = opts.clone
143
+
144
+ # anything other than :relayed sets the REST param to "disabled", in which case we force
145
+ # opts to be :routed. if we were more strict we could raise an error when the value isn't
146
+ # either :relayed or :routed
147
+ if params.delete(:media_mode) == :relayed
148
+ params["p2p.preference"] = "enabled"
149
+ else
150
+ params["p2p.preference"] = "disabled"
151
+ opts[:media_mode] = :routed
152
+ end
153
+ # location is optional, but it has to be an IP address if specified at all
154
+ unless params[:location].nil?
155
+ raise "location must be an IPv4 address" unless params[:location] =~ Resolv::IPv4::Regex
156
+ end
157
+
158
+ response = client.create_session(params)
159
+ Session.new api_key, api_secret, response['sessions']['Session']['session_id'], opts
160
+ end
161
+
162
+ # An Archives object, which lets you work with OpenTok 2.0 archives.
163
+ def archives
164
+ @archives ||= Archives.new client
165
+ end
166
+
167
+ protected
168
+
169
+ def client
170
+ @client ||= Client.new api_key, api_secret, api_url
171
+ end
172
+
173
+ end
174
+ end