@duncte123/obs-websocket-js
Version:
Fork of obs ws v4 so I can create a bridge to v5
98 lines (83 loc) • 3.24 kB
JavaScript
const Socket = require('./Socket');
const Status = require('./Status');
const debug = require('debug')('obs-websocket-js:Core');
let requestCounter = 0;
function generateMessageId() {
return String(requestCounter++);
}
class OBSWebSocket extends Socket {
/**
* Generic Socket request method. Returns a promise.
* Generates a messageId internally and will override any passed in the args.
* Note that the requestType here is pre-marshaling and currently must match exactly what the websocket plugin is expecting.
*
* @param {String} requestType obs-websocket plugin expected request type.
* @param {Object} [args={}] request arguments.
* @return {Promise} Promise, passes the plugin response object.
*/
send(requestType, args = {}) {
args = args || {};
return new Promise((resolve, reject) => {
const messageId = generateMessageId();
let rejectReason;
if (!requestType) {
rejectReason = Status.REQUEST_TYPE_NOT_SPECIFIED;
}
if (args && (typeof args !== 'object' || args === null || Array.isArray(args))) {
rejectReason = Status.ARGS_NOT_OBJECT;
}
if (!this._connected) {
rejectReason = Status.NOT_CONNECTED;
}
// Assign a temporary event listener for this particular messageId to uniquely identify the response.
this.once(`obs:internal:message:id-${messageId}`, (err, data) => {
if (err) {
debug('[send:reject] %o', err);
reject(err);
} else {
debug('[send:resolve] %o', data);
resolve(data);
}
});
// If we don't have a reason to fail fast, send the request to the socket.
if (!rejectReason) {
args['request-type'] = requestType;
args['message-id'] = messageId;
// Submit the request to the websocket.
debug('[send] %s %s %o', messageId, requestType, args);
try {
this._socket.send(JSON.stringify(args));
} catch (_) {
// TODO: Consider inspecting the exception thrown to gleam some relevant info and pass that on.
rejectReason = Status.SOCKET_EXCEPTION;
}
}
// If the socket call was unsuccessful or bypassed, simulate its resolution.
if (rejectReason) {
this.emit(`obs:internal:message:id-${messageId}`, rejectReason);
}
});
}
/**
* Generic Socket request method. Handles callbacks.
* Internally calls `send` (which is promise-based). See `send`'s docs for more details.
*
* @param {String} requestType obs-websocket plugin expected request type.
* @param {Object} [args={}] request arguments.
* @param {Function} callback Optional. callback(err, data)
*/
sendCallback(requestType, args = {}, callback) { // eslint-disable-line default-param-last
// Allow the `args` argument to be omitted.
if (callback === undefined && typeof args === 'function') {
callback = args;
args = {};
}
// Perform the actual request, using `send`.
this.send(requestType, args).then((...response) => {
callback(null, ...response);
}).catch(error => {
callback(error);
});
}
}
module.exports = OBSWebSocket;