Skip to content
Snippets Groups Projects
bbb.js 6.17 KiB
Newer Older
  • Learn to ignore specific revisions
  • const puppeteer = require("puppeteer");
    const sleep = require("sleep-promise");
    
    module.exports.createFreshPage = async function createFreshPage() {
      const browser = await puppeteer.launch({
    
    Jonas Zohren's avatar
    Jonas Zohren committed
        headless: true,
    
        defaultViewport: {
          width: 1200,
          height: 600,
          isLandscape: true,
        },
      });
      const context = await browser.createIncognitoBrowserContext();
      return context.newPage();
    };
    
    module.exports.joinRoom = async function joinRoom(
      page,
      roomUrl,
      displayName = "Puppet"
    ) {
      await page.goto(roomUrl);
      console.log("joinRoom > Gone to start page for", roomUrl);
    
    
      try {
        // Set displayname for program
        await page.type("input.join-form", displayName);
      } catch (error) {
    
    Jonas Zohren's avatar
    Jonas Zohren committed
        console.warn("could not set displayname");
    
      try {
        // Join and load room
        await page.click("button#room-join");
      } catch (error) {
    
    Jonas Zohren's avatar
    Jonas Zohren committed
        await page.click('input[value="Join"]');
    
    
      const dismissButton = await page.waitForSelector(
        'button[aria-describedBy="modalDismissDescription"]'
      );
      console.log("joinRoom > Joined room");
      // Click audio choice panel away
      await dismissButton.click();
    
      console.log("joinRoom > clicked audio choice away.");
      return page;
    };
    
    module.exports.sendChatMessage = async function sendChatMessage(
      page,
      messageText
    ) {
      const chatInputHandle = await page.$("textarea#message-input");
      const chatSendButtonHandle = await page.$(
        'form > div > button[type="submit"]'
      );
    
      // Send a text message
      await chatInputHandle.type(messageText);
      await chatSendButtonHandle.click();
      console.log("sendChatMessage > sent Message");
    };
    
    module.exports.signIn = async function signIn(
      bbbUrl,
      username,
      password,
      page = null
    ) {
      // Create page if not done already
      if (page === null) {
        page = await createFreshPage();
      }
    
      await page.goto(bbbUrl);
    
      await page.waitForSelector("a.sign-in-button");
      const signInButton = await page.$("a.sign-in-button");
      if (signInButton === null) {
        console.log(
          "SignIn > Can't find sign-in button: User is probably already authenticated."
        );
        return page;
      }
    
      await page.click("a.sign-in-button");
      await page.waitForNavigation();
      console.log("SignIn > NAVIGATED TO LOGIN PAGE");
    
      await page.type("input#session_username", username);
      await page.type("input#session_password", password);
      await page.click("input.signin-button");
      console.log("SignIn > entered credentials");
    
      await page.waitForNavigation();
      console.log("SignIn > Probably logged in.");
    
      return page;
    };
    
    module.exports.screenShotPresentationArea = async function screenShotPresentationArea(
      authenticatedPage,
      path
    ) {
      const presentationAreaHandle = await authenticatedPage.$("div#container");
      presentationAreaHandle.screenshot({ path, type: "jpeg", quality: 33 });
    };
    
    module.exports.getUserCount = async function getUserCount(authenticatedPage) {
      const selector = 'div[role="complementary"] > div > div > h2';
      const h2Handle = (await authenticatedPage.$$(selector))[2];
      return h2Handle.evaluate(
        (node) => node.innerText.split("(")[1].split(")")[0]
      );
    };
    
    module.exports.getUserList = async function getUserList(authenticatedPage) {
      const users = [];
    
      const selector = 'div[class*="userItemContents"]';
      const userHandles = await authenticatedPage.$$(selector);
      for (const userHandle of userHandles) {
        const avatarHandle = await userHandle.$('div[class*="avatar"]');
        const classes = (await avatarHandle.evaluate((node) => node.className))
          .split(" ")
          .map((wholeClass) => wholeClass.split("--")[0])
          .filter((name) => name !== "avatar");
        const userNameHandle = await userHandle.$(
          'span[class*="userNameMain"] > span'
        );
        const userName = await userNameHandle.evaluate((node) => node.innerText);
    
        users.push({
          classes,
          name: userName,
        });
      }
      return users;
    };
    
    module.exports.getRoomName = async function getRoomName(authenticatedPage) {
      const roomNameHandle = await authenticatedPage.$(
        'h1[class*="presentationTitle"]'
      );
      if (roomNameHandle === null) {
        process.send({ eventName: "sessionClosed", data: null });
        await sleep(100);
        process.exit(0);
      }
      return await roomNameHandle.evaluate((node) => node.innerText);
    };
    
    module.exports.createRoom = async function createRoom(
      authenticatedPage,
      roomSettings
    ) {
      const pageUrl = await authenticatedPage.url();
      const urlparts = pageUrl.split("/");
      const url = urlparts[0] + "//" + urlparts[2];
      const authenticityTokenHandle = await authenticatedPage.$(
        'input[name="authenticity_token"]'
      );
      const authenticityToken = await authenticityTokenHandle.evaluate(
        (node) => node.value
      );
    
      await authenticatedPage.evaluate(
        async (url, authenticityToken, roomSettings) => {
          function urlencodeFormData(fd) {
            var s = "";
            function encode(s) {
              return encodeURIComponent(s).replace(/%20/g, "+");
            }
            for (var pair of fd.entries()) {
              if (typeof pair[1] == "string") {
                s += (s ? "&" : "") + encode(pair[0]) + "=" + encode(pair[1]);
              }
            }
            return s;
          }
    
          // Prepare form data
          const form = new FormData();
          form.set("utf8", "");
          form.set("authenticity_token", authenticityToken);
          for (const key of Object.keys(roomSettings)) {
            // Maybe fix this, because the POST format is weird
            if (typeof roomSettings[key] === "boolean") {
              form.append("room[" + key + "]", 0);
              if (roomSettings[key]) {
                form.append("room[" + key + "]", 1);
              }
            } else {
              form.set("room[" + key + "]", roomSettings[key]);
            }
          }
          form.set("room[auto_join]", "0");
          form.set("commit", "Create+Room");
    
          try {
            // Send request to create room
            const response = await fetch(url, {
              method: "POST",
              headers: {
                "Content-Type": "application/x-www-form-urlencoded",
              },
              redirect: "follow", // manual, *follow, error
              body: urlencodeFormData(form),
            });
            return response;
          } catch (error) {
            return error;
          }
        },
        url + "/b",
        authenticityToken,
        roomSettings
      );
    
      await authenticatedPage.goto(url);
    };