bigbluebot icon indicating copy to clipboard operation
bigbluebot copied to clipboard

bigbluebot - Installation step to use with greenlight

Open aguerson opened this issue 4 years ago • 10 comments

OK I did it ! To reproduce

  1. 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 )

  2. 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
  1. create sub dir mkdir -p /opt/bigbluebutton/bbb-bot

  2. change rights

chown -R bigbluebutton:bigbluebutton /opt/bigbluebutton/bbb-bot
chmod 1770 /opt/bigbluebutton/bbb-bot
  1. 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
  1. 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

  1. modify the LANG
update-locale LANG=en_US.UTF-8
systemctl set-environment LANG=en_US.UTF-8
  1. clone the repo
su - bigbluebutton
git clone git://github.com/mconf/bigbluebot.git /opt/bigbluebutton/bbb-bot/
  1. 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",

  1. install the librairies
su - bigbluebutton

npm i --save-dev bufferutil

npm i --save-dev utf-8-validate

npm i bigbluebot

  1. 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
  1. 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
  },
  1. 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
  1. Try it

Launch the meeting with the greenlight interface

and

ssh -X [email protected]

cd /opt/bigbluebutton/bbb-bot/

node run.js

Enjoy !

aguerson avatar Sep 29 '20 12:09 aguerson

@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 avatar Sep 29 '20 12:09 aguerson

@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.

pedrobmarin avatar Sep 29 '20 13:09 pedrobmarin

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 :'(

aguerson avatar Sep 29 '20 13:09 aguerson

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"

aguerson avatar Sep 29 '20 13:09 aguerson

Comment this up https://github.com/mconf/bigbluebot/blob/ad75134558848ff0b9c9d76d61dd29f66e878e16/lib/run.js#L20-L23

pedrobmarin avatar Sep 29 '20 13:09 pedrobmarin

I try ;)

aguerson avatar Sep 29 '20 13:09 aguerson

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 ;)

aguerson avatar Sep 29 '20 13:09 aguerson

You can close the issue or use it as guideline ;)

aguerson avatar Sep 29 '20 13:09 aguerson

Nice, this is helpful, thank you @aguerson :wave:

Mittler1 avatar Sep 30 '20 10:09 Mittler1

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.

romale avatar Dec 02 '20 14:12 romale