Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bigbluebot - Installation step to use with greenlight #14

Open
aguerson opened this issue Sep 29, 2020 · 10 comments
Open

bigbluebot - Installation step to use with greenlight #14

aguerson opened this issue Sep 29, 2020 · 10 comments

Comments

@aguerson
Copy link

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
Copy link
Author

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

@pedrobmarin
Copy link
Contributor

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

@aguerson
Copy link
Author

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
Copy link
Author

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"

@pedrobmarin
Copy link
Contributor

Comment this up

bigbluebot/lib/run.js

Lines 20 to 23 in ad75134

if (api.secret) {
const success = await util.create();
if (!success) return null;
}

@aguerson
Copy link
Author

I try ;)

@aguerson
Copy link
Author

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
Copy link
Author

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

@Mittler1
Copy link

Nice, this is helpful, thank you @aguerson 👋

@romale
Copy link

romale commented Dec 2, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants