[NEW] Beta support for Big Blue Button video conferencing system (#11837)

pull/11842/head
Rodrigo Nascimento 7 years ago committed by Diego Sampaio
parent 3a487f930f
commit b29af81993
  1. 1
      .meteor/packages
  2. 1
      .meteor/versions
  3. 1
      packages/rocketchat-authorization/server/startup.js
  4. 11
      packages/rocketchat-bigbluebutton/package.js
  5. 197
      packages/rocketchat-bigbluebutton/server/bigbluebutton-api.js
  6. 7
      packages/rocketchat-livestream/client/tabBar.js
  7. 2
      packages/rocketchat-livestream/client/views/liveStreamTab.js
  8. 12
      packages/rocketchat-livestream/server/functions/saveStreamingOptions.js
  9. 2
      packages/rocketchat-ui-sidenav/client/roomList.js
  10. 1
      packages/rocketchat-ui-sidenav/client/sidebarItem.html
  11. 3
      packages/rocketchat-ui-sidenav/client/sidebarItem.js
  12. 32
      packages/rocketchat-videobridge/client/tabBar.js
  13. 3
      packages/rocketchat-videobridge/client/views/bbbLiveView.html
  14. 16
      packages/rocketchat-videobridge/client/views/videoFlexTabBbb.html
  15. 63
      packages/rocketchat-videobridge/client/views/videoFlexTabBbb.js
  16. 6
      packages/rocketchat-videobridge/package.js
  17. 158
      packages/rocketchat-videobridge/server/methods/bbb.js
  18. 1
      packages/rocketchat-videobridge/server/methods/jitsiSetTimeout.js
  19. 178
      packages/rocketchat-videobridge/server/settings.js

@ -197,3 +197,4 @@ chatpal:search
rocketchat:lazy-load
tap:i18n
underscore
rocketchat:bigbluebutton

@ -133,6 +133,7 @@ rocketchat:assets@0.0.1
rocketchat:authorization@0.0.1
rocketchat:autolinker@0.0.1
rocketchat:autotranslate@0.0.1
rocketchat:bigbluebutton@0.0.1
rocketchat:bot-helpers@0.0.1
rocketchat:cas@1.0.0
rocketchat:channel-settings@0.0.1

@ -70,6 +70,7 @@ Meteor.startup(function() {
{ _id: 'preview-c-room', roles : ['admin', 'user', 'anonymous'] },
{ _id: 'view-outside-room', roles : ['admin', 'owner', 'moderator', 'user'] },
{ _id: 'view-broadcast-member-list', roles : ['admin', 'owner', 'moderator'] },
{ _id: 'call-management', roles : ['admin', 'owner', 'moderator'] },
];
for (const permission of permissions) {

@ -0,0 +1,11 @@
Package.describe({
name: 'rocketchat:bigbluebutton',
version: '0.0.1',
summary: 'Rocket.Chat big blue button implementation',
git: '',
});
Package.onUse(function(api) {
api.use('ecmascript');
api.mainModule('server/bigbluebutton-api.js', 'server');
});

@ -0,0 +1,197 @@
/* eslint-disable */
import crypto from 'crypto';
var BigBlueButtonApi, filterCustomParameters, include, noChecksumMethods, root,
__indexOf = [].indexOf || function (item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
BigBlueButtonApi = (function () {
function BigBlueButtonApi(url, salt, debug, opts) {
var _base;
if (debug == null) {
debug = false;
}
if (opts == null) {
opts = {};
}
this.url = url;
this.salt = salt;
this.debug = debug;
this.opts = opts;
if ((_base = this.opts).shaType == null) {
_base.shaType = 'sha1';
}
}
BigBlueButtonApi.prototype.availableApiCalls = function () {
return ['/', 'create', 'join', 'isMeetingRunning', 'getMeetingInfo', 'end', 'getMeetings', 'getDefaultConfigXML', 'setConfigXML', 'enter', 'configXML', 'signOut', 'getRecordings', 'publishRecordings', 'deleteRecordings', 'updateRecordings', 'hooks/create'];
};
BigBlueButtonApi.prototype.urlParamsFor = function (param) {
switch (param) {
case "create":
return [["meetingID", true], ["name", true], ["attendeePW", false], ["moderatorPW", false], ["welcome", false], ["dialNumber", false], ["voiceBridge", false], ["webVoice", false], ["logoutURL", false], ["maxParticipants", false], ["record", false], ["duration", false], ["moderatorOnlyMessage", false], ["autoStartRecording", false], ["allowStartStopRecording", false], [/meta_\w+/, false]];
case "join":
return [["fullName", true], ["meetingID", true], ["password", true], ["createTime", false], ["userID", false], ["webVoiceConf", false], ["configToken", false], ["avatarURL", false], ["redirect", false], ["clientURL", false]];
case "isMeetingRunning":
return [["meetingID", true]];
case "end":
return [["meetingID", true], ["password", true]];
case "getMeetingInfo":
return [["meetingID", true], ["password", true]];
case "getRecordings":
return [["meetingID", false], ["recordID", false], ["state", false], [/meta_\w+/, false]];
case "publishRecordings":
return [["recordID", true], ["publish", true]];
case "deleteRecordings":
return [["recordID", true]];
case "updateRecordings":
return [["recordID", true], [/meta_\w+/, false]];
case "hooks/create":
return [["callbackURL", false], ["meetingID", false]];
}
};
BigBlueButtonApi.prototype.filterParams = function (params, method) {
var filters, r;
filters = this.urlParamsFor(method);
if ((filters == null) || filters.length === 0) {
({});
} else {
r = include(params, function (key, value) {
var filter, _i, _len;
for (_i = 0, _len = filters.length; _i < _len; _i++) {
filter = filters[_i];
if (filter[0] instanceof RegExp) {
if (key.match(filter[0]) || key.match(/^custom_/)) {
return true;
}
} else {
if (key.match("^" + filter[0] + "$") || key.match(/^custom_/)) {
return true;
}
}
}
return false;
});
}
return filterCustomParameters(r);
};
BigBlueButtonApi.prototype.urlFor = function (method, params, filter) {
var checksum, key, keys, param, paramList, property, query, sep, url, _i, _len;
if (filter == null) {
filter = true;
}
if (this.debug) {
console.log("Generating URL for", method);
}
if (filter) {
params = this.filterParams(params, method);
} else {
params = filterCustomParameters(params);
}
url = this.url;
paramList = [];
if (params != null) {
keys = [];
for (property in params) {
keys.push(property);
}
keys = keys.sort();
for (_i = 0, _len = keys.length; _i < _len; _i++) {
key = keys[_i];
if (key != null) {
param = params[key];
}
if (param != null) {
paramList.push("" + (this.encodeForUrl(key)) + "=" + (this.encodeForUrl(param)));
}
}
if (paramList.length > 0) {
query = paramList.join("&");
}
} else {
query = '';
}
checksum = this.checksum(method, query);
if (paramList.length > 0) {
query = "" + method + "?" + query;
sep = '&';
} else {
if (method !== '/') {
query = method;
}
sep = '?';
}
if (__indexOf.call(noChecksumMethods(), method) < 0) {
query = "" + query + sep + "checksum=" + checksum;
}
return "" + url + "/" + query;
};
BigBlueButtonApi.prototype.checksum = function (method, query) {
var c, shaObj, str;
query || (query = "");
if (this.debug) {
console.log("- Calculating the checksum using: '" + method + "', '" + query + "', '" + this.salt + "'");
}
str = method + query + this.salt;
if (this.opts.shaType === 'sha256') {
shaObj = crypto.createHash('sha256', "TEXT")
} else {
shaObj = crypto.createHash('sha1', "TEXT")
}
shaObj.update(str);
c = shaObj.digest('hex');
if (this.debug) {
console.log("- Checksum calculated:", c);
}
return c;
};
BigBlueButtonApi.prototype.encodeForUrl = function (value) {
return encodeURIComponent(value).replace(/%20/g, '+').replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
};
BigBlueButtonApi.prototype.setMobileProtocol = function (url) {
return url.replace(/http[s]?\:\/\//, "bigbluebutton://");
};
return BigBlueButtonApi;
})();
include = function (input, _function) {
var key, value, _match, _obj;
_obj = new Object;
_match = null;
for (key in input) {
value = input[key];
if (_function.call(input, key, value)) {
_obj[key] = value;
}
}
return _obj;
};
export default BigBlueButtonApi;
filterCustomParameters = function (params) {
var key, v;
for (key in params) {
v = params[key];
if (key.match(/^custom_/)) {
params[key.replace(/^custom_/, "")] = v;
}
}
for (key in params) {
if (key.match(/^custom_/)) {
delete params[key];
}
}
return params;
};
noChecksumMethods = function () {
return ['setConfigXML', '/', 'enter', 'configXML', 'signOut'];
};

@ -2,7 +2,7 @@ Meteor.startup(function() {
Tracker.autorun(function() {
RocketChat.TabBar.removeButton('livestream');
if (RocketChat.settings.get('Livestream_enabled')) {
const live = RocketChat.models.Rooms.findOne({ _id: Session.get('openedRoom'), 'streamingOptions.id': { $exists :1 } }, { fields: { streamingOptions: 1 } });
const live = RocketChat.models.Rooms.findOne({ _id: Session.get('openedRoom'), 'streamingOptions.type': 'livestream', 'streamingOptions.id': { $exists :1 } }, { fields: { streamingOptions: 1 } });
RocketChat.TabBar.size = live ? 5 : 4;
return RocketChat.TabBar.addButton({
groups: ['channel', 'group'],
@ -11,10 +11,7 @@ Meteor.startup(function() {
icon: 'podcast',
template: 'liveStreamTab',
order: live ? -1 : 15,
class: () => {
const roomWithStream = RocketChat.models.Rooms.findOne({ _id: Session.get('openedRoom'), 'streamingOptions.id': { $exists :1 } }, { fields: { streamingOptions: 1 } }) || '';
return roomWithStream && 'live';
},
class: () => live && 'live',
});
}
});

@ -137,6 +137,7 @@ Template.liveStreamTab.events({
...optionsFromUrl(i.find('[name=streaming-source]').value),
isAudioOnly: i.find('[name=streaming-audio-only]').checked,
message: i.find('[name=streaming-message]').value,
type: 'livestream',
};
Meteor.call('saveRoomSettings', this.rid, 'streamingOptions', streamingOptions, function(err) {
@ -197,6 +198,7 @@ Template.liveStreamTab.events({
...optionsFromUrl(i.find('[name=streaming-source]').value),
isAudioOnly: i.find('[name=streaming-audio-only]').checked,
message: i.find('[name=streaming-message]').value,
type: 'livestream',
};
Meteor.call('saveRoomSettings', this.rid, 'streamingOptions', streamingOptions, function(err) {

@ -1,9 +1,17 @@
RocketChat.saveStreamingOptions = function(rid, streamingOptions) {
RocketChat.saveStreamingOptions = function(rid, options) {
if (!Match.test(rid, String)) {
throw new Meteor.Error('invalid-room', 'Invalid room', {
function: 'RocketChat.saveStreamingOptions',
});
}
return RocketChat.models.Rooms.setStreamingOptionsById(rid, streamingOptions);
check(options, {
type: Match.Optional(String),
url: Match.Optional(String),
thumbnail: Match.Optional(String),
isAudioOnly: Match.Optional(String),
message: Match.Optional(String),
});
RocketChat.models.Rooms.setStreamingOptionsById(rid, options);
};

@ -112,6 +112,7 @@ const mergeSubRoom = (subscription) => {
const room = RocketChat.models.Rooms.findOne(subscription.rid) || { _updatedAt: subscription.ts };
subscription.lastMessage = room.lastMessage;
subscription.lm = room._updatedAt;
subscription.streamingOptions = room.streamingOptions;
return Object.assign(subscription, getLowerCaseNames(subscription));
};
@ -127,6 +128,7 @@ const mergeRoomSub = (room) => {
$set: {
lastMessage: room.lastMessage,
lm: room._updatedAt,
streamingOptions: room.streamingOptions,
...getLowerCaseNames(room, sub.name, sub.fname),
},
});

@ -42,6 +42,7 @@
<span class="sidebar-item__me">({{_ "You"}})</span>
{{/if}}
</div>
<!-- {{#if streaming}} VIDEO {{/if}} -->
</div>
{{#if extended}}
{{#if lastMessageTs}}

@ -6,6 +6,9 @@ Template.sidebarItem.helpers({
args.pop();
return args.some((arg) => arg);
},
streaming() {
return Object.keys(this.streamingOptions).length;
},
isRoom() {
return this.rid || this._id;
},

@ -1,4 +1,36 @@
Meteor.startup(function() {
Tracker.autorun(function() {
if (!RocketChat.settings.get('bigbluebutton_Enabled')) {
return RocketChat.TabBar.removeButton('bbb_video');
}
const live = RocketChat.models.Rooms.findOne({ _id: Session.get('openedRoom'), 'streamingOptions.type': 'call' }, { fields: { streamingOptions: 1 } });
const groups = [];
if (RocketChat.settings.get('bigbluebutton_enable_d')) {
groups.push('direct');
}
if (RocketChat.settings.get('bigbluebutton_enable_p')) {
groups.push('group');
}
if (RocketChat.settings.get('bigbluebutton_enable_c')) {
groups.push('channel');
}
RocketChat.TabBar.addButton({
groups,
id: 'bbb_video',
i18nTitle: 'BBB Video Chat',
icon: 'video',
iconColor: 'red',
template: 'videoFlexTabBbb',
width: 600,
order: live ? -1 : 15,
class: () => live && 'live',
});
});
Tracker.autorun(function() {
if (RocketChat.settings.get('Jitsi_Enabled')) {
RocketChat.TabBar.addButton({

@ -0,0 +1,3 @@
<template name="bbbLiveView">
<iframe allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" allow="geolocation; microphone; camera" src="{{source}}" width="380" height="400" frameborder="0"></iframe>
</template>

@ -0,0 +1,16 @@
<template name="videoFlexTabBbb">
<div class="rc-user-info__flex rc-user-info__row">
{{#if live}}
<button type="button" class="rc-button rc-button--primary js-join-meeting">{{_ "Join Meeting"}}</button>
{{#if callManagement}}
<button type="button" class="rc-button rc-button--cancel js-end-meeting">{{_ "End Meeting"}}</button>
{{/if}}
{{else}}
{{#if callManagement}}
<button type="button" class="rc-button rc-button--primary js-join-meeting">{{_ "Start Meeting"}}</button>
{{else}}
<p>{{_ "You have no permission to start a call"}}</p>
{{/if}}
{{/if}}
</div>
</template>

@ -0,0 +1,63 @@
/* eslint new-cap: [2, {"capIsNewExceptions": ["MD5"]}] */
/* globals popout */
Template.videoFlexTabBbb.helpers({
openInNewWindow() {
if (Meteor.isCordova) {
return true;
} else {
return RocketChat.settings.get('Jitsi_Open_New_Window');
}
},
live() {
const isLive = RocketChat.models.Rooms.findOne({ _id: this.rid, 'streamingOptions.type': 'call' }, { fields: { streamingOptions: 1 } }) != null;
if (isLive === false && popout.context) {
popout.close();
}
return isLive;
},
callManagement() {
const type = RocketChat.models.Rooms.findOne({ _id: this.rid }).t;
return type === 'd' || RocketChat.authz.hasAllPermission('call-management') || RocketChat.authz.hasAllPermission('call-management', this.rid);
},
});
Template.videoFlexTabBbb.onCreated(function() {
this.tabBar = Template.currentData().tabBar;
});
Template.videoFlexTabBbb.events({
'click .js-join-meeting'(e) {
$(e.currentTarget).prop('disabled', true);
Meteor.call('bbbJoin', { rid: this.rid }, (err, result) => {
$(e.currentTarget).prop('disabled', false);
console.log(err, result);
if (result) {
popout.open({
content: 'bbbLiveView',
data: {
source: result.url,
streamingOptions: result,
canOpenExternal: true,
showVideoControls: false,
},
onCloseCallback: () => console.log('bye popout'),
});
}
});
// Get the link and open the iframe
},
'click .js-end-meeting'(e) {
$(e.currentTarget).prop('disabled', true);
Meteor.call('bbbEnd', { rid: this.rid }, (err, result) => {
// $(e.currentTarget).prop('disabled', false);
console.log(err, result);
});
// Get the link and open the iframe
},
});

@ -10,6 +10,7 @@ Package.onUse(function(api) {
'ecmascript',
'less',
'rocketchat:lib',
'rocketchat:bigbluebutton',
]);
api.use('templating', 'client');
@ -18,7 +19,11 @@ Package.onUse(function(api) {
api.addFiles('client/stylesheets/video.less', 'client');
api.addFiles('client/views/videoFlexTab.html', 'client');
api.addFiles('client/views/bbbLiveView.html', 'client');
api.addFiles('client/views/videoFlexTabBbb.html', 'client');
api.addFiles('client/views/videoFlexTab.js', 'client');
api.addFiles('client/views/videoFlexTabBbb.js', 'client');
api.addFiles('client/tabBar.js', 'client');
api.addFiles('client/actionLink.js', 'client');
@ -28,5 +33,6 @@ Package.onUse(function(api) {
api.addFiles('server/settings.js', 'server');
api.addFiles('server/models/Rooms.js', 'server');
api.addFiles('server/methods/jitsiSetTimeout.js', 'server');
api.addFiles('server/methods/bbb.js', 'server');
api.addFiles('server/actionLink.js', 'server');
});

@ -0,0 +1,158 @@
import BigBlueButtonApi from 'meteor/rocketchat:bigbluebutton';
import { HTTP } from 'meteor/http';
import xml2js from 'xml2js';
const parser = new xml2js.Parser({
explicitRoot: true,
});
const parseString = Meteor.wrapAsync(parser.parseString);
const getBBBAPI = () => {
const url = RocketChat.settings.get('bigbluebutton_server');
const secret = RocketChat.settings.get('bigbluebutton_sharedSecret');
const api = new BigBlueButtonApi(`${ url }/bigbluebutton/api`, secret);
return { api, url };
};
Meteor.methods({
bbbJoin({ rid }) {
if (!this.userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'bbbJoin' });
}
if (!Meteor.call('canAccessRoom', rid, this.userId)) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'bbbJoin' });
}
if (!RocketChat.settings.get('bigbluebutton_Enabled')) {
throw new Meteor.Error('error-not-allowed', 'Not Allowed', { method: 'bbbJoin' });
}
const { api, url } = getBBBAPI();
const meetingID = RocketChat.settings.get('uniqueID') + rid;
const room = RocketChat.models.Rooms.findOneById(rid);
const createUrl = api.urlFor('create', {
name: room.t === 'd' ? 'Direct' : room.name,
meetingID,
attendeePW: 'ap',
moderatorPW: 'mp',
welcome: '<br>Welcome to <b>%%CONFNAME%%</b>!',
meta_html5chat: false,
meta_html5navbar: false,
meta_html5autoswaplayout: true,
meta_html5autosharewebcam: false,
meta_html5hidepresentation: true,
});
const createResult = HTTP.get(createUrl);
const doc = parseString(createResult.content);
if (doc.response.returncode[0]) {
const user = RocketChat.models.Users.findOneById(this.userId);
const hookApi = api.urlFor('hooks/create', {
meetingID,
callbackURL: Meteor.absoluteUrl(`api/v1/videoconference.bbb.update/${ meetingID }`),
});
const hookResult = HTTP.get(hookApi);
if (hookResult.statusCode !== 200) {
// TODO improve error logging
console.log({ hookResult });
return;
}
RocketChat.saveStreamingOptions(rid, {
type: 'call',
});
return {
url: api.urlFor('join', {
password: 'mp', // mp if moderator ap if attendee
meetingID,
fullName: user.username,
userID: user._id,
avatarURL: Meteor.absoluteUrl(`avatar/${ user.username }`),
clientURL: `${ url }/html5client/join`,
}),
};
}
},
bbbEnd({ rid }) {
if (!this.userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'bbbEnd' });
}
if (!Meteor.call('canAccessRoom', rid, this.userId)) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'bbbEnd' });
}
if (!RocketChat.settings.get('bigbluebutton_Enabled')) {
throw new Meteor.Error('error-not-allowed', 'Not Allowed', { method: 'bbbEnd' });
}
const { api } = getBBBAPI();
const meetingID = RocketChat.settings.get('uniqueID') + rid;
const endApi = api.urlFor('end', {
meetingID,
password: 'mp', // mp if moderator ap if attendee
});
const endApiResult = HTTP.get(endApi);
if (endApiResult.statusCode !== 200) {
// TODO improve error logging
console.log({ endApiResult });
return;
}
const doc = parseString(endApiResult.content);
if (doc.response.returncode[0] === 'FAILED') {
RocketChat.saveStreamingOptions(rid, {});
}
},
});
RocketChat.API.v1.addRoute('videoconference.bbb.update/:id', { authRequired: false }, {
post() {
// TODO check checksum
const event = JSON.parse(this.bodyParams.event)[0];
const eventType = event.data.id;
const meetingID = event.data.attributes.meeting['external-meeting-id'];
const rid = meetingID.replace(RocketChat.settings.get('uniqueID'), '');
console.log(eventType, rid);
if (eventType === 'meeting-ended') {
RocketChat.saveStreamingOptions(rid, {});
}
// if (eventType === 'user-left') {
// const { api } = getBBBAPI();
// const getMeetingInfoApi = api.urlFor('getMeetingInfo', {
// meetingID
// });
// const getMeetingInfoResult = HTTP.get(getMeetingInfoApi);
// if (getMeetingInfoResult.statusCode !== 200) {
// // TODO improve error logging
// console.log({ getMeetingInfoResult });
// }
// const doc = parseString(getMeetingInfoResult.content);
// if (doc.response.returncode[0]) {
// const participantCount = parseInt(doc.response.participantCount[0]);
// console.log(participantCount);
// }
// }
},
});

@ -1,4 +1,3 @@
Meteor.methods({
'jitsi:updateTimeout': (rid) => {

@ -1,70 +1,132 @@
Meteor.startup(function() {
RocketChat.settings.addGroup('Video Conference', function() {
this.add('Jitsi_Enabled', false, {
type: 'boolean',
i18nLabel: 'Enabled',
alert: 'This Feature is currently in beta! Please report bugs to github.com/RocketChat/Rocket.Chat/issues',
public: true,
});
this.add('Jitsi_Domain', 'meet.jit.si', {
type: 'string',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Domain',
public: true,
});
this.section('BigBlueButton', function() {
this.add('Jitsi_URL_Room_Prefix', 'RocketChat', {
type: 'string',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'URL_room_prefix',
public: true,
});
this.add('bigbluebutton_Enabled', false, {
type: 'boolean',
i18nLabel: 'Enabled',
alert: 'This Feature is currently in beta! Please report bugs to github.com/RocketChat/Rocket.Chat/issues',
public: true,
});
this.add('Jitsi_SSL', true, {
type: 'boolean',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'SSL',
public: true,
});
this.add('bigbluebutton_server', '', {
type: 'string',
i18nLabel: 'Domain',
enableQuery: {
_id: 'bigbluebutton_Enabled',
value: true,
},
});
this.add('Jitsi_Open_New_Window', false, {
type: 'boolean',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Always_open_in_new_window',
public: true,
});
this.add('bigbluebutton_sharedSecret', '', {
type: 'string',
i18nLabel: 'Shared_Secret',
enableQuery: {
_id: 'bigbluebutton_Enabled',
value: true,
},
});
this.add('bigbluebutton_enable_d', true, {
type: 'boolean',
i18nLabel: 'WebRTC_Enable_Direct',
enableQuery: {
_id: 'bigbluebutton_Enabled',
value: true,
},
public: true,
});
this.add('bigbluebutton_enable_p', true, {
type: 'boolean',
i18nLabel: 'WebRTC_Enable_Private',
enableQuery: {
_id: 'bigbluebutton_Enabled',
value: true,
},
public: true,
});
this.add('bigbluebutton_enable_c', false, {
type: 'boolean',
i18nLabel: 'WebRTC_Enable_Channel',
enableQuery: {
_id: 'bigbluebutton_Enabled',
value: true,
},
public: true,
});
this.add('Jitsi_Enable_Channels', false, {
type: 'boolean',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Jitsi_Enable_Channels',
public: true,
});
this.add('Jitsi_Chrome_Extension', 'nocfbnnmjnndkbipkabodnheejiegccf', {
type: 'string',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Jitsi_Chrome_Extension',
public: true,
this.section('Jitsi', function() {
this.add('Jitsi_Enabled', false, {
type: 'boolean',
i18nLabel: 'Enabled',
alert: 'This Feature is currently in beta! Please report bugs to github.com/RocketChat/Rocket.Chat/issues',
public: true,
});
this.add('Jitsi_Domain', 'meet.jit.si', {
type: 'string',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Domain',
public: true,
});
this.add('Jitsi_URL_Room_Prefix', 'RocketChat', {
type: 'string',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'URL_room_prefix',
public: true,
});
this.add('Jitsi_SSL', true, {
type: 'boolean',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'SSL',
public: true,
});
this.add('Jitsi_Open_New_Window', false, {
type: 'boolean',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Always_open_in_new_window',
public: true,
});
this.add('Jitsi_Enable_Channels', false, {
type: 'boolean',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Jitsi_Enable_Channels',
public: true,
});
this.add('Jitsi_Chrome_Extension', 'nocfbnnmjnndkbipkabodnheejiegccf', {
type: 'string',
enableQuery: {
_id: 'Jitsi_Enabled',
value: true,
},
i18nLabel: 'Jitsi_Chrome_Extension',
public: true,
});
});
});
});

Loading…
Cancel
Save