Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

opentok

Package Overview
Dependencies
Maintainers
3
Versions
54
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

opentok - npm Package Compare versions

Comparing version 1.0.2 to 2.2.0

.npmignore

695

lib/opentok.js

@@ -1,295 +0,488 @@

var https = require('https')
, querystring = require('querystring')
, crypto = require('crypto')
/*
* OpenTok server-side SDK
*/
// tokbox constants:
, TOKEN_SENTINEL = "T1=="
, API_HOST = "api.opentok.com"
, SESSION_API_ENDPOINT = "/hl/session/create"
, GET_MANIFEST = "/archive/getmanifest/"
, GET_URL = "/hl/archive/url/";
// Dependencies
var net = require('net'),
querystring = require('querystring'),
crypto = require('crypto'),
_ = require('lodash'),
Client = require('./client'),
Session = require('./session'),
archiving = require('./archiving'),
package = require ('../package.json')
errors = require('./errors');
var RoleConstants = exports.RoleConstants = {
SUBSCRIBER: "subscriber",
PUBLISHER: "publisher",
MODERATOR: "moderator"
}
// Internal Constants
var TOKEN_SENTINEL = "T1==";
// JS constants
var JSObject = "object"
, JSFunction = "function"
, JSString = "string"
, JSNumber = "number"
/**
* Contains methods for creating OpenTok sessions, generating tokens, and working with archives.
* <p>
* To create a new OpenTok object, call the OpenTok constructor with your OpenTok API key
* and the API secret from <a href="https://dashboard.tokbox.com">the OpenTok dashboard</a>.
* Do not publicly share your API secret. You will use it with the OpenTok constructor
* (only on your web server) to create OpenTok sessions.
* <p>
* Be sure to include the entire OpenTok Node.js SDK on your web server.
*
* @class OpenTok
*
* @param apiKey {String} Your OpenTok API key. (See the
* <a href="https://dashboard.tokbox.com">OpenTok dashboard</a> page.)
* @param apiSecret {String} Your OpenTok API secret. (See the
* <a href="https://dashboard.tokbox.com">OpenTok dashboard</a> page.)
*/
var OpenTok = function(apiKey, apiSecret, env) {
// we're loose about calling this constructor with `new`, we got your back
if (!(this instanceof OpenTok)) return new OpenTok(apiKey, apiSecret, env);
// OpenTokSession constructor (only used internally)
var OpenTokSession = function(sessionId){
this.sessionId = sessionId
}
// OpenTokSDK constructor
var OpenTokSDK = exports.OpenTokSDK = function(partnerId, partnerSecret){
if(partnerId && partnerSecret){
this.partnerId = partnerId;
this.partnerSecret = partnerSecret;
this.api_url = API_HOST;
}else{
return new Error("Invalid Key or Secret");
// validate arguments: apiKey := Number|String, apiSecret := String
if (!(_.isNumber(apiKey) || _.isString(apiKey)) || !_.isString(apiSecret)) {
return new Error('Invalid arguments when initializing OpenTok:');
}
}
OpenTokSDK.OpenTokArchive = function(sdkObject){
var self = this;
this.resources = [];
this.addVideoResource = function(res){
self.resources.push(res);
};
this.downloadArchiveURL=function(vid, callback){
var options = {
host: sdkObject.api_url,
path: GET_URL+sdkObject.archiveId+"/"+vid,
method: 'GET',
headers: {
'x-tb-token-auth':sdkObject.token
}
};
var req = https.request(options, function(res){
var chunks = '';
res.setEncoding('utf8')
res.on('data', function(chunk){
chunks += chunk
})
res.on('end', function(){
callback(chunks);
})
})
req.end()
};
};
OpenTokSDK.OpenTokArchiveVideoResource = function(vid,length,name){
this.vid = vid;
this.length = length;
this.name = name;
this.getId = function(){
return vid;
};
};
OpenTokSDK.prototype.getArchiveManifest = function(archiveId, token, callback){
this.get_archive_manifest( archiveId, token, callback );
}
// apiKey argument can be a Number, but we will internally store it as a String
if (_.isNumber(apiKey)) apiKey = apiKey.toString();
OpenTokSDK.prototype.get_archive_manifest = function(archiveId, token, callback){
this.token = token;
this.archiveId = archiveId;
var self = this;
var parseResponse = function(chunks){
var response = new OpenTokSDK.OpenTokArchive(self);
var start = chunks.match('<resources>')
, end = chunks.match('</resources>')
var videoTags = null
if(start && end){
videoTags = chunks.substr(start.index + 12, (end.index - start.index - 12))
attr = videoTags.split('"');
if(attr.length>5){
vid = attr[1]
length = attr[3]
name = attr[5]
resource = new OpenTokSDK.OpenTokArchiveVideoResource(vid, length, name);
response.addVideoResource(resource);
}
}
callback(response);
this.client = new Client({ apiKey: apiKey, apiSecret: apiSecret });
this.apiKey = apiKey;
this.apiSecret = apiSecret;
// TODO: this is a pretty obvious seam, the integration could be more smooth
var archiveConfig = {
apiEndpoint: 'https://api.opentok.com',
apiKey: apiKey,
apiSecret: apiSecret
};
var options = {
host: this.api_url,
path: GET_MANIFEST+archiveId,
method: 'GET',
headers: {
'x-tb-token-auth':token
}
// env can be either an object with a bunch of DI options, or a simple string for the apiUrl
if (_.isString(env)) {
this.client.config({ apiUrl: env });
archiveConfig.apiEndpoint = env;
}
var req = https.request(options, function(res){
var chunks = '';
res.setEncoding('utf8')
res.on('data', function(chunk){
chunks += chunk
})
res.on('end', function(){
parseResponse(chunks);
})
})
req.end()
/**
* Starts archiving an OpenTok 2.0 session.
* <p>
* Clients must be actively connected to the OpenTok session for you to successfully start
* recording an archive.
* <p>
* You can only record one archive at a time for a given session. You can only record archives
* of sessions that uses the OpenTok Media Router; you cannot archive peer-to-peer sessions.
*
* @param sessionId The session ID of the OpenTok session to archive.
*
* @param options {Object} An optional options object with one property &mdash; <code>name</code>
* (a String). This is the name of the archive. You can use this name to identify the archive.
* It is a property of the Archive object, and it is a property of archive-related events in the
* OpenTok client libraries.
*
* @param callback {Function} The function to call upon completing the operation. Two arguments
* are passed to the function:
*
* <ul>
*
* <li>
* <code>error</code> &mdash; An error object (if the call to the method fails).
* </li>
*
* <li>
* <code>archive</code> &mdash; The Archive object. This object includes properties defining
* the archive, including the archive ID.
* </li>
*
* </ul>
*
* @method #startArchive
* @memberof OpenTok
*/
this.startArchive = archiving.startArchive.bind(null, archiveConfig);
/**
* Stops an OpenTok archive that is being recorded.
* <p>
* Archives automatically stop recording after 90 minutes or when all clients have disconnected
* from the session being archived.
*
* @param archiveId {String} The archive ID of the archive you want to stop recording.
* @return The Archive object corresponding to the archive being STOPPED.
*
* @param callback {Function} The function to call upon completing the operation. Two arguments
* are passed to the function:
*
* <ul>
*
* <li>
* <code>error</code> &mdash; An error object (if the call to the method fails).
* </li>
*
* <li>
* <code>archive</code> &mdash; The Archive object.
* </li>
*
* </ul>
*
* @method #stopArchive
* @memberof OpenTok
*/
this.stopArchive = archiving.stopArchive.bind(null, archiveConfig);
/**
* Gets an {@link Archive} object for the given archive ID.
*
* @param archiveId The archive ID.
*
* @return The {@link Archive} object.
*
* @method #getArchive
* @memberof OpenTok
*/
this.getArchive = archiving.getArchive.bind(null, archiveConfig);
/**
* Deletes an OpenTok archive.
* <p>
* You can only delete an archive which has a status of "available" or "uploaded". Deleting an
* archive removes its record from the list of archives. For an "available" archive, it also
* removes the archive file, making it unavailable for download.
*
* @param {String} archiveId The archive ID of the archive you want to delete.
*
* @param callback {Function} The function to call upon completing the operation. On successfully
* deleting the archive, the function is called with no arguments passed in. On failure, an error
* object is passed into the function.
*
* @method #deleteArchive
* @memberof OpenTok
*/
this.deleteArchive = archiving.deleteArchive.bind(null, archiveConfig);
/**
* Retrieves a List of {@link Archive} objects, representing archives that are both
* both completed and in-progress, for your API key.
*
* @param options {Object} An options parameter with two properties:
*
* <ul>
*
* <li>
* <code>count</code> &mdash; The index offset of the first archive. 0 is offset of the most
* recently started archive. 1 is the offset of the archive that started prior to the most
* recent archive. This limit is 1000 archives.
* </li>
*
* <li>
* <code>offset</code> &mdash; The offset for the first archive to list (starting with the
* first archive recorded as offset 0).
* </li>
*
* </ul>
*
* <p>If you don't pass in an <code>options</code> argument, the method returns up to 1000 archives
* starting with the first archive recorded.
*
* @param callback {Function} The function to call upon completing the operation. Two arguments
* are passed to the function:
*
* <ul>
*
* <li>
* <code>error</code> &mdash; An error object (if the call to the method fails).
* </li>
*
* <li>
* <code>archives</code> &mdash; An array of Archive objects.
* </li>
*
* </ul>
*
* @method #listArchives
* @memberof OpenTok
*/
this.listArchives = archiving.listArchives.bind(null, archiveConfig);
}
OpenTokSDK.prototype.generate_token = function(ops){
ops = ops || {};
/**
* Creates a new OpenTok session and returns the session ID, which uniquely identifies
* the session.
* <p>
* For example, when using the OpenTok.js library, use the session ID when calling the
* <a href="http://tokbox.com/opentok/libraries/client/js/reference/OT.html#initSession">
* OT.initSession()</a> method (to initialize an OpenTok session).
* <p>
* OpenTok sessions do not expire. However, authentication tokens do expire (see the
* generateToken(String, TokenOptions) method). Also note that sessions cannot
* explicitly be destroyed.
* <p>
* A session ID string can be up to 255 characters long.
*
* You can also create a session using the
* <a href="http://www.tokbox.com/opentok/api/#session_id_production">OpenTok REST API</a>
* or the <a href="https://dashboard.tokbox.com/projects">OpenTok dashboard</a>.
*
* @return A session ID for the new session. For example, when using the OpenTok.js library, use
* this session ID when calling the <code>OT.initSession()</code> method.
*
* @param {Object} options
* This object defines options for the session, including the following properties (both of which
* are optional):
*
* <ul>
*
* <li><code>location</code> (String) &mdash;
* An IP address that the OpenTok servers will use to situate the session in the global
* OpenTok network. If you do not set a location hint, the OpenTok servers will be based on
* the first client connecting to the session.
* </li>
*
* <li><code>mediaMode</code> (String) &mdash;
* Determines whether the session will transmit streams using the OpenTok Media Router
* (<code>"routed"</code>) or not (<code>"relayed"</code>). By default, sessions use
* the OpenTok Media Router.
* <p>
* The <a href="http://tokbox.com/#multiparty" target="_top"> OpenTok Media Router</a>
* provides the following benefits:
*
* <ul>
* <li>The OpenTok Media Router can decrease bandwidth usage in multiparty sessions.
* (When the <code>mediaMode</code> parameter is set to <code>"relayed"</code>,
* each client must send a separate audio-video stream to each client subscribing to
* it.)</li>
* <li>The OpenTok Media Router can improve the quality of the user experience through
* <a href="http://tokbox.com/#iqc" target="_top">Intelligent Quality Control</a>. With
* Intelligent Quality Control, if a client's connectivity degrades to a degree that
* it does not support video for a stream it's subscribing to, the video is dropped on
* that client (without affecting other clients), and the client receives audio only.
* If the client's connectivity improves, the video returns.</li>
* <li>The OpenTok Media Router supports the
* <a href="http://tokbox.com/platform/archiving" target="_top">archiving</a>
* feature, which lets you record, save, and retrieve OpenTok sessions.</li>
* </ul>
*
* <p>
* With the <code>mediaMode</code> parameter set to <code>"relayed"</code>, the session
* will attempt to transmit streams directly between clients. If clients cannot connect due to
* firewall restrictions, the session uses the OpenTok TURN server to relay audio-video
* streams.
* <p>
* You will be billed for streamed minutes if you use the OpenTok Media Router or if the
* session uses the OpenTok TURN server to relay streams. For information on pricing, see the
* <a href="http://www.tokbox.com/pricing" target="_top">OpenTok pricing page</a>.
*
* @param {Function} callback
* The function that is called when the operation completes. This function is passed two arguments:
*
* <ul>
* <li>
* <code>sessionId</code> &mdash; On sucess, this parameter is set to the session ID of
* the session. Otherwise it is set to null.
* </li>
* <li>
* <code>error</code> &mdash; On failiure, this parameter is set to an error object.
* Check the error message for details.
* </li>
* </ul>
*/
OpenTok.prototype.createSession = function(opts, callback) {
var backupOpts;
// At some point in this packages existence, three different forms of Session ID were used
// Fallback to default (last session created using this OpenTokSDK instance)
var sessionId = ops.session_id || ops.sessionId || ops.session || this.sessionId;
if( !sessionId || sessionId == "" ){
throw new Error("Null or empty session ID is not valid");
if (_.isFunction(opts)) {
// shift arguments if the opts is left out
callback = opts;
opts = {};
} else if (!_.isFunction(callback)) {
// one of the args has to be a function, or we bail
return new Error('Invalid arguments when calling createSession, must provide a callback');
}
// validate partner id
var subSessionId = sessionId.substring(2);
subSessionId = subSessionId.replace(/-/g, "+").replace(/_/g, "/");
var decodedSessionId = new Buffer(subSessionId, "base64").toString("ascii").split("~");
for(var i = 0; i < decodedSessionId.length; i++){
if (decodedSessionId && decodedSessionId.length > 1){
break
}
subSessionId = subSessionId + "=";
// whitelist the keys allowed
_.pick(_.defaults(opts, { "mediaMode" : "routed" }), "mediaMode", "location");
if ( opts.mediaMode !== "routed" && opts.mediaMode !== "relayed" ) {
opts.mediaMode = "routed";
}
if (decodedSessionId[1] != this.partnerId){
throw new Error("An invalid session ID was passed");
if ( "location" in opts && !net.isIPv4(opts.location) ) {
return process.nextTick(function() { callback(new Error('Invalid arguments when calling createSession, ' +
'location must be an IPv4 address'))});
}
// rename mediaMode -> p2p.preference
backupOpts = _.clone(opts);
var mediaModeToParam = {
"routed" : "disabled",
"relayed" : "enabled"
};
opts["p2p.preference"] = mediaModeToParam[opts["mediaMode"]];
delete opts["mediaMode"];
var createTime = OpenTokSDK.prototype._getUTCDate()
, sig
, tokenString
, tokenParams
, tokenBuffer
, dataString
, dataParams = {
session_id: sessionId,
create_time: createTime,
nonce: Math.floor(Math.random()*999999),
role: RoleConstants.PUBLISHER // will be overriden below if passed in
};
this.client.createSession(opts, function(err, json) {
if (err) return callback(new Error('Failed to createSession. '+err));
callback(null, new Session(this, json.sessions.Session.session_id, backupOpts));
});
};
// pass through any other tokbox parameters:
for(var op in ops){
if(ops.hasOwnProperty(op)){
dataParams[op] = ops[op]
}
}
/**
* Creates a token for connecting to an OpenTok session. In order to authenticate a user
* connecting to an OpenTok session, the client passes a token when connecting to the session.
* <p>
* For testing, you can also use the <a href="https://dashboard.tokbox.com/projects">OpenTok
* dashboard</a> page to generate test tokens.
*
* @param sessionId The session ID corresponding to the session to which the user will connect.
*
* @param options An object that defines options for the token (each of which is optional):
*
* <ul>
* <li><code>role</code> (String) &mdash; The role for the token. Each role defines a set of
* permissions granted to the token:
*
* <ul>
* <li> <code>'subscriber'</code> &mdash; A subscriber can only subscribe to streams.</li>
*
* <li> <code>'publisher'</code> &mdash; A publisher can publish streams, subscribe to
* streams, and signal. (This is the default value if you do not specify a role.)</li>
*
* <li> <code>'moderator'</code> &mdash; In addition to the privileges granted to a
* publisher, in clients using the OpenTok.js 2.2 library, a moderator can call the
* <code>forceUnpublish()</code> and <code>forceDisconnect()</code> method of the
* Session object.</li>
* </ul>
*
* </li>
*
* <li><code>expireTime</code> (Number) &mdash; The expiration time for the token, in seconds
* since the UNIX epoch. The maximum expiration time is 30 days after the creation time.
* The default expiration time of 24 hours after the token creation time.
* </li>
*
* <li><code>data</code> (String) &mdash; A string containing connection metadata describing the
* end-user.For example, you can pass the user ID, name, or other data describing the end-user.
* The length of the string is limited to 1000 characters. This data cannot be updated once it
* is set.
* </li>
* </ul>
*
* @return The token string.
*/
OpenTok.prototype.generateToken = function(sessionId, opts) {
var decoded, tokenData;
dataString = querystring.stringify(dataParams)
sig = this._signString(dataString, this.partnerSecret)
tokenParams = ["partner_id=",this.partnerId,"&sig=",sig,":",dataString].join("")
tokenBuffer = new Buffer(tokenParams,"utf8");
return TOKEN_SENTINEL + tokenBuffer.toString('base64');
}
if (!opts) opts = {};
if ( !_.isString(sessionId) ) return null;
OpenTokSDK.prototype.generateToken = function(ops){
return this.generate_token(ops);
}
// validate the sessionId belongs to the apiKey of this OpenTok instance
decoded = decodeSessionId(sessionId);
if ( !decoded || decoded.apiKey !== this.apiKey) return null;
OpenTokSDK.prototype.create_session = function(ipPassthru, properties, callback){
var sessionId
, params = {
partner_id: this.partnerId,
};
// combine defaults, opts, and whitelisted property names to create tokenData
if (_.isNumber(opts.expireTime) || _.isString(opts.expireTime)) opts.expire_time = opts.expireTime;
if (opts.data) opts.connection_data = opts.data;
tokenData = _.pick(_.defaults(opts, {
session_id: sessionId,
create_time: Math.round(new Date().getTime() / 1000),
expire_time: Math.round(new Date().getTime() / 1000) + (60*60*24), // 1 day
nonce: Math.random(),
role: 'publisher'
}), 'session_id', 'create_time', 'nonce', 'role', 'expire_time', 'connection_data');
// No user specified parameter
if( typeof(ipPassthru) == JSFunction ){
callback = ipPassthru;
ipPassthru = null;
properties = null;
// validate tokenData
if (!_.contains(['publisher', 'subscriber', 'moderator'], tokenData.role)) return null;
if (!_.isNumber(tokenData.expire_time)) return null;
if (tokenData.connection_data &&
(tokenData.connection_data.length > 1024 || !_.isString(tokenData.connection_data))) {
return null;
}
// location is passed in only
if( typeof(ipPassthru) == JSString && typeof(properties) == JSFunction ){
callback = properties;
properties = null;
}
// property is passed in only
if( typeof(ipPassthru) == JSObject && typeof(properties) == JSFunction ){
callback = properties;
properties = ipPassthru;
ipPassthru = null;
}
// property and location passed in, do nothing
for(var p in properties){
params[p] = properties[p]
}
var self = this;
sessionId = this._doRequest(params, function(err, chunks){
if (err) return this._handleError({ action: 'createSession', location: ipPassthru, props: params, cause: err}, callback);
return encodeToken(tokenData, this.apiKey, this.apiSecret);
}
var start = chunks.match('<session_id>')
, end = chunks.match('</session_id>')
, sessionId;
if(start && end){
self.sessionId = chunks.substr(start.index + 12, (end.index - start.index - 12))
}
callback(null, self.sessionId)
});
/*
* decodes a sessionId into the metadata that it contains
* @param {string} sessionId
* @returns {?SessionInfo} sessionInfo
*/
function decodeSessionId(sessionId) {
var fields, sessionInfo;
// remove sentinal (e.g. '1_', '2_')
sessionId = sessionId.substring(2);
// replace invalid base64 chars
sessionId = sessionId.replace(/-/g, "+").replace(/_/g, "/");
// base64 decode
sessionId = new Buffer(sessionId, "base64").toString("ascii");
// separate fields
fields = sessionId.split("~");
return {
apiKey: fields[1],
location: fields[2],
create_time: new Date(fields[3])
};
}
OpenTokSDK.prototype.createSession = function(ipPassthru, properties, callback){
this.create_session(ipPassthru, properties, callback);
/*
* encodes token data into a valid token
* @param {Object} data
* @param {string} apiKey
* @param {string} apiSecret
* @returns {string} token
*/
function encodeToken(data, apiKey, apiSecret) {
var dataString = querystring.stringify(data),
sig = signString(dataString, apiSecret),
decoded = new Buffer("partner_id="+apiKey+"&sig="+sig+":"+dataString, 'utf8');
return TOKEN_SENTINEL + decoded.toString('base64');
}
OpenTokSDK.prototype._signString = function(string, secret){
var hmac = crypto.createHmac('sha1',secret)
hmac.update(string)
return hmac.digest('hex')
/*
* sign a string
* @param {string} unsigned
* @param {string} key
* @returns {string} signed
*/
function signString(unsigned, key) {
var hmac = crypto.createHmac('sha1', key);
hmac.update(unsigned);
return hmac.digest('hex');
}
OpenTokSDK.prototype._doRequest = function(params, callback){
var dataString = querystring.stringify(params);
/*
* handles the result of a session creation
* @callback OpenTok~createSessionCallback
* @param {?Error} err
* @param {string} sessionId
*/
var options = {
host: this.api_url,
path: SESSION_API_ENDPOINT,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': dataString.length,
'X-TB-PARTNER-AUTH': this.partnerId + ":" + this.partnerSecret
}
}
/*
* handles the result of a REST request
* @callback OpenTok~doRequestCallback
* @param {?Error} err
* @param {string} responseXml
*/
var req = https.request(options, function(res){
var chunks = '';
/*
* is interested in an error, can be a super-type of OpenTok~createSessionCallback
* @callback OpenTok~doRequestCallback
* @param {?Error} err
* @param {...*} arguments
*/
res.setEncoding('utf8')
/**
* @typedef SessionInfo
* @type {Object}
* @property {string} apiKey The API Key that created the session
* @property {number} location The location hint used when creating the session
* @property {Date] create_time The time at which the session was created
*/
res.on('data', function(chunk){
chunks += chunk
})
res.on('end', function(){
callback(null, chunks);
})
})
req.write(dataString)
req.on('error', function(e) {
callback(e);
});
req.end()
}
/*
* Sends errors to callback functions in pretty, readable messages
* External Interface
*/
OpenTokSDK.prototype._handleError = function(details, cb) {
var message;
// Construct message according the the action (or method) that is triggering the error
if (details.action === 'createSession') {
message = 'Failed to create new OpenTok Session using location: ' + details.location + ', properties: ' + JSON.stringify(details.props) + '.';
}
module.exports = OpenTok;
// When there is an underlying error that caused this one, give some details about it
if (details.cause) {
message += 'This error was caused by another error: "' + details.cause.message + '".';
for(var key in errors) {
if(errors.hasOwnProperty(key)) {
OpenTok[key] = errors[key];
}
return cb(new Error(message));
};
OpenTokSDK.prototype._getUTCDate = function(){
var D= new Date();
return Date.UTC(D.getUTCFullYear(), D.getUTCMonth(), D.getUTCDate(), D.getUTCHours(),
D.getUTCMinutes(), D.getUTCSeconds()).toString().substr(0,10)
}
{
"name": "opentok",
"description": "OpenTokSDK for node.js",
"version": "1.0.2",
"homepage": "https://github.com/opentok/opentok",
"repository": "https://github.com/opentok/opentok.git",
"description": "OpenTok server-side SDK",
"version": "2.2.0",
"homepage": "http://opentok.github.io/opentok-node",
"repository": {
"type": "git",
"url": "https://github.com/opentok/opentok-node.git"
},
"bugs": {
"url": "https://github.com/opentok/opentok-node/issues",
"email": "support@tokbox.com"
},
"license": "MIT",
"contributors": [

@@ -15,19 +23,33 @@ {

"name": "Song Zheng",
"email": "song@tokbox.com"
"email": "song@tokbox.com",
"url": "http://songz.me"
},
{
"name": "Ankur Oberoi",
"email": "aoberoi@gmail.com"
"email": "aoberoi@gmail.com",
"url": "http://aoberoi.me"
}
],
"main": "./lib/opentok",
"directories": {
"lib": "lib"
"main": "lib/opentok.js",
"scripts": {
"test": "grunt"
},
"engines": {
"node": "*"
"node": ">=0.10.0"
},
"devDependencies": {
"jasmine-node" : "1.0.x"
"async": "^0.2.10",
"chai": "^1.9.1",
"grunt": "^0.4.4",
"grunt-jasmine-node": "^0.2.1",
"grunt-jsdoc": "^0.5.4",
"grunt-mocha-test": "^0.10.0",
"nock": "^0.27.2"
},
"dependencies": {
"xmljson": "~0.2.0",
"underscore": "~1.5.2",
"request": "^2.34.0",
"lodash": "^2.4.1"
}
}

@@ -1,197 +0,222 @@

<div align="center">
<a href="http://tokbox.com/">
<img src="https://swww.tokbox.com/img/img_www_platform_devices.jpg" style="margin: 0 auto;" alt="Open Tok" />
</a>
</div>
# OpenTok Node SDK
# OpenTokSDK for Node.js
[![Build Status](https://travis-ci.org/opentok/opentok-node.png)](https://travis-ci.org/opentok/opentok-node)
OpenTok is a free set of APIs from TokBox that enables websites to weave live group video communication into their online experience. With OpenTok you have the freedom and flexibility to create the most engaging web experience for your users. OpenTok is currently available as a JavaScript and ActionScript 3.0 library. Check out <http://www.tokbox.com/> and <http://www.tokbox.com/opentok/tools/js/gettingstarted> for more information.
The OpenTok Node SDK lets you generate
[sessions](http://www.tokbox.com/opentok/tutorials/create-session/) and
[tokens](http://www.tokbox.com/opentok/tutorials/create-token/) for
[OpenTok](http://www.tokbox.com/) applications, and
[archive](http://www.tokbox.com/platform/archiving) OpenTok 2.0 sessions.
This is the OpenTok NodeJS Module.
If you are updating from a previous version of this SDK, see
[Important changes in v2.2](#important-changes-in-v22).
* [Installation](#installation)
* [How to use](#how-to-use)
* [Require the opentok module](#require-the-opentok-module)
* [API key and API secret](#api-key-and-api-secret)
* [OpenTokSDK](#opentoksdk)
* [Creating Sessions](#creating-sessions)
* [Generating Token](#generating-token)
* [Downloading Archive Videos](#downloading-archive-videos)
* [Get Archive Manifest](#get-archive-manifest)
* [Get video ID](#get-video-id)
* [Get Download URL](#get-download-url)
* [Example](#example)
* [Want to contribute?](#want-to-contribute)
# Installation using npm (recommended):
npm helps manage dependencies for node projects. Find more info here: <http://npmjs.org>
## Installation
Run this command to install the package and adding it to your `package.json`:
To install using npm, add OpenTok to `package.json` and run `npm install`:
```javascript
"dependencies" : {
"opentok" : "1.0.x",
...
}
```
$ npm install opentok --save
```
To install as a regular npm package just type `npm install opentok`
# Usage
## How to use
## Initializing
### Require the `opentok` module
Import the module to get a constructor function for an OpenTok object, then call it with `new` to
initantiate it with your own API Key and API Secret.
Add the following code to the top of any file using the `opentok` module:
```javascript
var OpenTok = require('opentok'),
opentok = new OpenTok(apiKey, apiSecret);
```
var OpenTok = require('opentok');
## Creating Sessions
### API key and API secret
To create an OpenTok Session, use the `opentok.createSession(properties, callback)` method. The
`properties` parameter is an optional object used to specify whether the session uses the OpenTok
Media Router and to specify a location hint. The callback has the signature
`function(error, session)`. The `session` returned in the callback is an instance of Session.
Session objects have a `sessionId` property that is useful to be saved to a persistent store
(such as a database).
Create an account at [TokBox](http://tokbox.com), and sign into your [Dashboard](https://dashboard.tokbox.com) for an API Key and Secret.
### OpenTokSDK
In order to use any of the server side functions, you must first create an `OpenTokSDK` object with your developer credentials.
You must pass in your *API key* and *API secret*.
```javascript
var key = ''; // Replace with your API key
var secret = ''; // Replace with your API secret
var opentok = new OpenTok.OpenTokSDK(key, secret);
```
// Just a plain Session
opentok.createSession(function(err, session) {
if (err) return console.log(err);
### Creating Sessions
Use your `OpenTokSDK` object to create a `session_id`.
`createSession` takes 2-3 parameters:
// save the sessionId
db.save('session', session.sessionId, done);
});
#### Parameters
| Name | Description | Type | Optional |
| ---------- | ------------------------------------------------ | ------ | -------- |
| location | Give OpenTok a hint of where the clients connecting will be located by specifiying an IP (e.g. '127.0.0.1') | string | yes |
| properties | Additional session options | object | yes |
| properties['p2p.preference'] | set to 'enabled' or 'disabled' | string | yes |
| callback | This is a function that handles the server response after session has been created. The result sessionId is a string. | fn(err, sessionId) | no |
// A The session will attempt to transmit streams directly between clients.
// If clients cannot connect, the session uses the OpenTok TURN server:
opentok.createSession({mediaMode:"relayed"}, function(err, session) {
if (err) return console.log(err);
// save the sessionId
db.save('session', session.sessionId, done);
});
Example: P2P disabled (default)
// A Session with a location hint
opentok.createSession({location:'12.34.56.78'}, function(err, session) {
if (err) return console.log(err);
```javascript
var location = '127.0.0.1'; // use an IP or 'localhost'
var sessionId = '';
opentok.createSession(location, function(err, sessionId){
if (err) return throw new Error("session creation failed");
// Do things with sessionId
// save the sessionId
db.save('session', session.sessionId, done);
});
```
## Generating Tokens
Example: P2P enabled
Once a Session is created, you can start generating Tokens for clients to use when connecting to it.
You can generate a token by calling the `opentok.generateToken(sessionId, options)` method. Another
way is to call the `session.generateToken(options)` method of a Session object. The `options`
parameter is an optional object used to set the role, expire time, and connection data of the Token.
```javascript
var location = '127.0.0.1'; // use an IP of 'localhost'
var sessionId = '';
opentok.createSession(location, {'p2p.preference':'enabled'}, function(err, sessionId){
if (err) return throw new Error("session creation failed");
// Do things with sessionId
// Generate a Token from just a sessionId (fetched from a database)
token = opentok.generateToken(sessionId);
// Genrate a Token from a session object (returned from createSession)
token = session.generateToken();
// Set some options in a Token
token = session.generateToken({
role : 'moderator',
expireTime : (new Date().getTime() / 1000)+(7 * 24 * 60 * 60), // in one week
data : 'name=Johnny'
});
```
### Generating Token
With the generated session_id and an OpenTokSDK object, you can start generating tokens for each user.
`generateToken` takes in an object with 1-4 properties, and RETURNS a token as a string:
## Working with archives
#### Parameters
You can start the recording of an OpenTok Session using the `opentok.startArchive(sessionId,
options, callback)` method. The `options` parameter is an optional object used to set the name of
the Archive. The callback has the signature `function(err, archive)`. The `archive` returned in
the callback is an instance of `Archive`. Note that you can only start an archive on a Session with
connected clients.
| Name | Description | Type | Optional |
| --------------- | -------------------------------------------------------------------------------------------------------------------- |:------:|:--------:|
| session_id | This token is tied to the session it is generated with | string | no |
| role | opentok.RoleConstants.{SUBSCRIBER&#124;PUBLISHER&#124;MODERATOR}. Publisher role used when omitted. | string | yes |
| expire_time | Time when token will expire in unix timestamp. | int | yes |
| connection_data | Stores static metadata to pass to other users connected to the session. (eg. names, user id, etc) | string | yes |
```javascript
opentok.startArchive(sessionId, { name: 'Important Presentation' }, function(err, archive) {
if (err) return console.log(err);
Example:
<pre>
var token = opentok.generateToken({session_id:session_id, role:OpenTok.RoleConstants.PUBLISHER, connection_data:"userId:42"});
</pre>
// The id property is useful to save off into a database
console.log("new archive:" + archive.id);
});
```
### Downloading Archive Videos
To Download archived video, you must have an Archive ID (from the client), and a moderator token. For more information see <http://www.tokbox.com/opentok/api/tools/documentation/api/server_side_libraries.html#download_archive>.
You can stop the recording of a started Archive using the `opentok.stopArchive(archiveId, callback)`
method. You can also do this using the `archive.stop(callback)` method an `Archive` instance. The
callback has a signature `function(err, archive)`. The `archive` returned in the callback is an
instance of `Archive`.
#### Quick Overview of the javascript library: <http://www.tokbox.com/opentok/api/tools/js/documentation/api/Session.html#createArchive>
1. Create an event listener on `archiveCreated` event: `session.addEventListener('archiveCreated', archiveCreatedHandler);`
2. Create an archive: `archive = session.createArchive(...);`
3. When archive is successfully created `archiveCreatedHandler` would be triggered. An Archive object containing `archiveId` property is passed into your function. Save this in your database, this archiveId is what you use to reference the archive for playbacks and download videos
4. After your archive has been created, you can start recording videos into it by calling `session.startRecording(archive)`
Optionally, you can also use the standalone archiving, which means that each archive would have only 1 video: <http://www.tokbox.com/opentok/api/tools/js/documentation/api/RecorderManager.html>
```javascript
opentok.stopArchive(archiveId, function(err, archive) {
if (err) return console.log(err);
### Get Archive Manifest
With your **moderator token** and a OpenTokSDK object, you can generate a OpenTokArchive object, which contains information for all videos in the Archive
`OpenTokSDK.getArchiveManifest()` takes in 3 parameters: **archiveId** and **moderator token**, and a callback function
console.log("Stopped archive:" + archive.id);
});
archive.stop(function(err, archive) {
if (err) return console.log(err);
});
```
#### Parameters
| Name | Description | Type | Optional |
| --------------- | ------------------------------------------------------------ | ------------- | -------- |
| archive_id | Get this from the client that created the archive. | string | no |
| token | Get this from the client or the generate_token method. | string | no |
| handler | This function is triggered after it receives the Archive Manifest. The parameter is an `OpenTokArchive` object. The *resources* property of this object is array of `OpenTokArchiveVideoResource` objects, and each `OpenTokArchiveVideoResource` object represents a video in the archive. | fn(tbarchive) | no |
To get an `Archive` instance (and all the information about it) from an `archiveId`, use the
`opentok.getArchive(archiveId, callback)` method. The callback has a function signature
`function(err, archive)`. You can inspect the properties of the archive for more details.
```javascript
opentok.getArchive(archiveId, function(err, archive) {
if (err) return console.log(err);
Example: (opentok is an OpentokSDK object)
console.log(archive);
});
```
To delete an Archive, you can call the `opentok.deleteArchive(archiveId, callback)` method or the
`delete(callback)` method of an `Archive` instance. The callback has a signature `function(err)`.
```javascript
var token = 'moderator_token';
var archiveId = '5f74aee5-ab3f-421b-b124-ed2a698ee939'; // Obtained from Javascript Library
// Delete an Archive from an archiveId (fetched from database)
opentok.deleteArchive(archiveId, function(err) {
if (err) console.log(err);
});
opentok.getArchiveManifest(archiveId, token, function(tbarchive){
var otArchive = tbarchive;
// Delete an Archive from an Archive instance (returned from archives.create, archives.find)
archive.delete(function(err) {
if (err) console.log(err);
});
```
### Get video ID
`OpenTokArchive.resources` is an array of `OpenTokArchiveVideoResource` objects. OpenTokArchiveVideoResource has a `getId()` method that returns the videoId as a string.
You can also get a list of all the Archives you've created (up to 1000) with your API Key. This is
done using the `opentok.listArchives(options, callback)` method. The parameter `options` is an
optional object used to specify an `offset` and `count` to help you paginate through the results.
The callback has a signature `function(err, archives, totalCount)`. The `archives` returned from
the callback is an array of `Archive` instances. The `totalCount` returned from the callback is
the total number of archives your API Key has generated.
Example:
```javascript
opentok.getArchiveManifest(archiveId, token, function(tbarchive){
var vidID = tbarchive.resources[0].getId();
opentok.listArchives({offset:100, count:50}, function(error, archives, totalCount) {
if (error) return console.log("error:", error);
console.log(totalCount + " archives");
for (var i = 0; i < archives.length; i++) {
console.log(archives[i].id);
}
});
```
### Get Download URL
`OpenTokArchive` objects have a `downloadArchiveURL(video_id, handler)` method that will return a URL string for downloading the video in the archive. Video files are FLV format.
# Samples
There are two sample applications included in this repository. To get going as fast as possible, clone the whole
repository and follow the Walkthroughs:
#### Parameters
* [HelloWorld](sample/HelloWorld/README.md)
* [Archiving](sample/Archiving/README.md)
| Name | Description | Type | Optional |
| --------------- |------------------------------------------------------------- | ------------- | -------- |
| video_id | The Video ID returned from OpenTokArchiveVideoResource.getId() | string | no |
| handler | This function is triggered after it receives the URL for video. The result is a URL string. | [fn(url)] | no |
# Documentation
Example:
Reference documentation is available at <http://www.tokbox.com/opentok/libraries/server/node/reference/index.html> and in the
docs directory of the SDK.
```javascript
var url = '';
otArchive.downloadArchiveURL(vidID, function(resp){
url = resp;
});
```
# Requirements
You need an OpenTok API key and API secret, which you can obtain at <https://dashboard.tokbox.com>.
## Example
The OpenTok Node SDK requires node 0.10 or higher.
Check out the basic working example in examples/app.js
# Release Notes
### When done, update package.json version number and publish npm
See the [Releases](https://github.com/opentok/opentok-node/releases) page for details
about each release.
npm publish
## Important changes in v2.2
## Want to contribute?
### To run test suite:
jasmine-node --coffee spec/
This version of the SDK includes support for working with OpenTok 2.0 archives. (This API does not
work with OpenTok 1.0 archives.)
The `create_session()` has changed to take one parameter: an `options` object that has `location`
and `mediaMode` properties. The `mediaMode` property replaces the `properties.p2p.preference`
parameter in the previous version of the SDK.
The `generateToken()` has changed to take two parameters: the session ID and an `options` object that has `role`, `expireTime` and `data` properties.
See the reference documentation
<http://www.tokbox.com/opentok/libraries/server/node/reference/index.html> and in the
docs directory of the SDK.
# Development and Contributing
Interested in contributing? We :heart: pull requests! See the [Development](DEVELOPING.md) and
[Contribution](CONTRIBUTING.md) guidelines.
# Support
See <http://tokbox.com/opentok/support/> for all our support options.
Find a bug? File it on the [Issues](https://github.com/opentok/opentok-node/issues) page. Hint:
test cases are really helpful!

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc