bigbluebot
bigbluebot copied to clipboard
bigbluebot - Installation step to use with greenlight
OK I did it ! To reproduce
-
create a CT from an OpenVZ server with ubuntu 18.04 LTS template ( or a lxd container ? ) in a moderate server ( Intel(R) Xeon(R) CPU X5690 @ 3.47GHz / 16G RAM )
-
create bigbluebutton user and customize it
adduser bigbluebutton
vim /home/bigbluebutton/.bashrc
...
HISTTIMEFORMAT="%F %T : "
HISTSIZE=1000000
HISTFILESIZE=1000000
...
export LANG="en_US.UTF-8"
cd /opt/bigbluebutton/bbb-bot
-
create sub dir
mkdir -p /opt/bigbluebutton/bbb-bot
-
change rights
chown -R bigbluebutton:bigbluebutton /opt/bigbluebutton/bbb-bot
chmod 1770 /opt/bigbluebutton/bbb-bot
- you need to install the mandatory packages
apt-get update
apt-get remove nodejs --purge
apt-get autoremove
apt-get -y install curl dirmngr apt-transport-https lsb-release ca-certificates
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
apt-get -y install nodejs
apt-get install -y gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget gcc g++ make libnss3 libxcb-dri3-0 libxcb-dri3-dev libdrm-common libdrm-dev libgbm1 libgbm-dev wget gnupg yarn xauth x11-apps firefox language-pack-en language-pack-fr
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome-unstable.list
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
apt-get update
apt-get install -y google-chrome-unstable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf --no-install-recommends
- you need to configure openssh daemon ( in case you use X display over ssh like me )
vim /etc/ssh/sshd_config
ListenAddress 0.0.0.0
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding yes
X11UseLocalhost no
PrintMotd no
AcceptEnv LANG LC_*
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp /usr/lib/openssh/sftp-server
PermitRootLogin yes
systemctl restart sshd.service
- modify the LANG
update-locale LANG=en_US.UTF-8
systemctl set-environment LANG=en_US.UTF-8
- clone the repo
su - bigbluebutton
git clone git://github.com/mconf/bigbluebot.git /opt/bigbluebutton/bbb-bot/
- modify the "name" in /opt/bigbluebutton/bbb-bot/package.json to bbbbot
{
"name": "bigbluebot",
"version": "1.3.6",
to
{
"name": "bbbbot",
"version": "1.3.6",
- install the librairies
su - bigbluebutton
npm i --save-dev bufferutil
npm i --save-dev utf-8-validate
npm i bigbluebot
- create start script
vim /opt/bigbluebutton/bbb-bot/run.js
const bigbluebot = require('bigbluebot')
let actions = async page => {
await bigbluebot.audio.modal.listen(page)
}
bigbluebot.run(actions)
chmod 555 /opt/bigbluebutton/bbb-bot/run.js
chown bigbluebutton:bigbluebutton /opt/bigbluebutton/bbb-bot/run.js
- Now you have to modify the code to adapt the use with greenlight !
vim /opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/api.js
modify
let query = '';
if (list.length > 0) query = list.join('&');
return query;
};
by
let query = '';
if (list.length > 0) query = list.join('&');
let userdata = '&userdata-bbb_auto_join_audio=true&userdata-bbb_enable_video=true&userdata-bbb_listen_only_mode=true&userdata-bbb_force_listen_only=true&userdata-bbb_skip_check_audio=true';
let fullquery = query + userdata;
return fullquery;
};
and modify ( I just want to join the room. I don't want to create it. I will create it manually using greenlight interface ).
const getURL = (action, params) => {
const query = buildQuery(params);
const checksum = calculateChecksum(action, query);
const host = config.url.host;
const api = config.api.path;
const url = `${host}/${api}/${action}?${query}&checksum=${checksum}`;
return url;
};
by
const getURL = (action, params) => {
const query = buildQuery(params);
const checksum = calculateChecksum(action, query);
const host = config.url.host;
const api = config.api.path;
//const url = `${host}/${api}/${action}?${query}&checksum=${checksum}`;
const url = `${host}/${api}/join?${query}&checksum=${checksum}`;
return url;
};
vim /opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/pool.js
modify
const args = [
`--lang=${browser.lang}`,
`--disable-dev-shm-usage`,
`--no-user-gesture-required`,
`--use-fake-ui-for-media-stream`,
`--use-fake-device-for-media-stream`,
];
by
const args = [
`--lang=${browser.lang}`,
`--disable-dev-shm-usage`,
`--no-user-gesture-required`,
//`--use-fake-ui-for-media-stream`,
//`--use-fake-device-for-media-stream`,
];
vim /opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/config/config.json
modify
{
"url": {
"host": null,
"locale": "html5client/locale?locale",
"demo": "demo/demoHTML5.jsp?action=create",
"user": {
"param": "username"
},
"moderator": {
"param": "isModerator",
"value": true
},
by
{
"url": {
"host": null,
"locale": "html5client/locale?locale",
"demo": "join",
"user": {
"param": "fullName"
},
"moderator": {
"param": "isModerator",
"value": false
},
and modify ( for this part, it depends if you want to play with the bots or not with the chrome browser )
"browser": {
"headless": true,
"endpoint": null,
"token": null,
"path": null,
"lang": "EN",
"window": {
"width": 1280,
"height": 720
},
by
"browser": {
"headless": false,
"endpoint": null,
"token": null,
"path": null,
"lang": "EN",
"window": {
"width": 1280,
"height": 720
},
and to finish, modify
"timeout": {
"selector": 60000
},
by
},
"timeout": {
"selector": 1800000
},
- Create you .env config file
cp /opt/bigbluebutton/bbb-bot/.env.template /opt/bigbluebutton/bbb-bot/.env
vim /opt/bigbluebutton/bbb-bot/.env
# BigBlueButton hostname
BIGBLUEBOT_HOST=https://hostname.domain
# Room name the bot should join
BIGBLUEBOT_ROOM=${roomid of your conf}
# Set the passwords if the room name is the ID of an existing room.
# Very important point !
# Each time you create a room with greenlight, greenlight set the ATTENDEE password and the MODERATOR password. These values are stored in the database
# To find it: Launch this SQL request
# select * from $(user_database_schema).rooms where bbb_id='${roomid_of_your_conf}';
# The fields are "moderator_pw" or "attendee_pw". It depends what you need.
BIGBLUEBOT_ATTENDEE_PW=${attendee_pw_of_roomid}
# BIGBLUEBOT_MODERATOR_PW=
# BigBlueButton secret
# bbb-conf --secret on the BBB server
BIGBLUEBOT_SECRET=${bbb_server_secret}
# Number of bots to spawn
BIGBLUEBOT_BOTS=50
# Time between bots to join (ms)
BIGBLUEBOT_WAIT=5000
# Bot life span (ms)
# Test during 30 min = 30x60x1000 = 1800000
BIGBLUEBOT_LIFE=1800000
# Use an external browser
#BIGBLUEBOT_BROWSER=/usr/bin/google-chrome
# Number of browser processes
# the number of the tab opened in the same chrome browser
BIGBLUEBOT_POOL=50
# Use endpoint browser websocket
#BIGBLUEBOT_ENDPOINT=
# Use endpoint authentication token
# BIGBLUEBOT_TOKEN=
# Log level
BIGBLUEBOT_LOG=debug
- Try it
Launch the meeting with the greenlight interface
and
ssh -X [email protected]
cd /opt/bigbluebutton/bbb-bot/
node run.js
Enjoy !
@pedrobmarin
I hope you will appreciate the work ;) I have a question In the BBB server log, I can see that the first connexion of bigbluebot is bad because it doesn't send the username on format "fullName=" and the password on format "password="
x.x.x.x - - [29/Sep/2020:14:39:20 +0200] "GET /bigbluebutton/api/join?attendeePW=xxxxxx&meetingID=yyyyyyy&moderatorPW=mp&record=true&userdata-bbb_auto_join_audio=true&userdata-bbb_enable_video=true&userdata-bbb_listen_only_mode=true&userdata-bbb_force_listen_only=true&userdata-bbb_skip_check_audio=true&checksum=zzzzzzzzz HTTP/1.1" 302 0 "-" "axios/0.20.0"
x.x.x.x - - [29/Sep/2020:14:39:20 +0200] "GET /?errors=[%7B%22message%22:%22You%20must%20specify%20a%20name%20for%20the%20attendee%20who%20will%20be%20joining%20the%20meeting.%22,%22key%22:%22missingParamFullName%22%7D] HTTP/1.1" 301 194 "-" "axios/0.20.0"
x.x.x.x - - [29/Sep/2020:14:39:20 +0200] "GET /html5client/locale?locale=EN HTTP/1.1" 200 43434 "-" "axios/0.20.0"
x.x.x.x - - [29/Sep/2020:14:39:30 +0200] "GET /bigbluebutton/api/join?fullName=Geovanny%20Johnson&meetingID=yyyyyyyy&password=xxxxxxxxxx&userdata-bbb_auto_join_audio=true&userdata-bbb_enable_video=true&userdata-bbb_listen_only_mode=true&userdata-bbb_force_listen_only=true&userdata-bbb_skip_check_audio=true&checksum=zzzzzzzzzzzzz HTTP/1.1" 302 0 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.0 Safari/537.36"
Is there any method to force the second connexion directly ?
@aguerson thanks for taking the time to map things up with Greenlight.
When dispatching the bots with your API secret configured the fist call the library will do is a create to initialize a room for the bots to join. Looks like something you modified is replacing the create
action for a join
and this could explain the missing fullName
and password
.
Yes I saw in the file "/opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/api.js" something like two orders "getCreateURL" and "getJoinURL" and at the end of the file, I found
module.exports = {
getCreateURL,
getJoinURL,
};
Is there any method to disable the getCreateUR call ?
If I put a comment here
module.exports = {
//getCreateURL,
getJoinURL,
};
I get this
(node:7110) UnhandledPromiseRejectionWarning: TypeError: api.getCreateURL is not a function
at Object.create (/opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/util.js:112:21)
at Object.run (/opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/run.js:21:32)
at Object.<anonymous> (/opt/bigbluebutton/bbb-bot/run.js:7:12)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
at Module.load (internal/modules/cjs/loader.js:985:32)
at Function.Module._load (internal/modules/cjs/loader.js:878:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
(node:7110) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:7110) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I am not a js expert :'(
OK, I am not a expert, but node is a really good tool ;) It said me to use "/opt/bigbluebutton/bbb-bot$ node --unhandled-rejections=strict run.js" And now I get this
/opt/bigbluebutton/bbb-bot$ node --unhandled-rejections=strict run.js
INFO 2020-09-29T13:26:57.530Z Bots: 1
INFO 2020-09-29T13:26:57.532Z Life: 1800 seconds
INFO 2020-09-29T13:26:57.532Z Creating room
/opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/util.js:112
const url = api.getCreateURL();
^
TypeError: api.getCreateURL is not a function
at Object.create (/opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/util.js:112:21)
at Object.run (/opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/run.js:21:32)
at Object.<anonymous> (/opt/bigbluebutton/bbb-bot/run.js:7:12)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
at Module.load (internal/modules/cjs/loader.js:985:32)
at Function.Module._load (internal/modules/cjs/loader.js:878:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
Maybe I will find my solution in the file "/opt/bigbluebutton/bbb-bot/node_modules/bigbluebot/lib/util.js"
Comment this up https://github.com/mconf/bigbluebot/blob/ad75134558848ff0b9c9d76d61dd29f66e878e16/lib/run.js#L20-L23
I try ;)
Good ! It works I replaced
const run = async actions => {
if (!dependencies()) return null;
logger.info(`Bots: ${pool.size * pool.population}`);
logger.info(`Life: ${bot.life / 1000} seconds`);
if (api.secret) {
const success = await util.create();
if (!success) return null;
}
const locale = await util.locale();
for (let i = 0; i < pool.size; i++) {
pool.browsers.acquire().then(async browser => {
by
const run = async actions => {
if (!dependencies()) return null;
logger.info(`Bots: ${pool.size * pool.population}`);
logger.info(`Life: ${bot.life / 1000} seconds`);
//if (api.secret) {
// const success = await util.create();
// if (!success) return null;
//}
const locale = await util.locale();
for (let i = 0; i < pool.size; i++) {
pool.browsers.acquire().then(async browser => {
@pedrobmarin thanks again ! No more errors ;)
You can close the issue or use it as guideline ;)
Nice, this is helpful, thank you @aguerson :wave:
Any ideas?
~/bbb-bot> node run.js
INFO 2020-12-02T14:54:52.360Z Bots: 1
INFO 2020-12-02T14:54:52.361Z Life: 60 seconds
INFO 2020-12-02T14:54:52.361Z Creating meeting
(node:17588) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'secret' of undefined
at calculateChecksum (/home/user/node_modules/bigbluebot/lib/api.js:46:26)
at getURL (/home/user/node_modules/bigbluebot/lib/api.js:36:20)
at Object.getCreateURL (/home/user/node_modules/bigbluebot/lib/api.js:60:10)
at Object.create (/home/user/node_modules/bigbluebot/lib/util.js:136:33)
at Object.run (/home/user/node_modules/bigbluebot/lib/run.js:29:32)
at Object.<anonymous> (/home/user/bbb-bot/run.js:16:12)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
(node:17588) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:17588) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.