Skip to content
Snippets Groups Projects
Commit c24228be authored by Jonas Zohren's avatar Jonas Zohren
Browse files

Test uploading presentations and fix some stuff

parent 4b2f097f
Branches
No related tags found
No related merge requests found
Pipeline #6736 passed with warnings
<script>
import AttachRoomPanel from './components/AttachRoomPanel.svelte';
import ChatBroadcastPanel from './components/ChatBroadcastPanel.svelte';
import RoomTiles from './components/RoomTiles.svelte'
import BulkCreatePanel from './components/BulkCreatePanel.svelte'
import RoomTiles from './components/RoomTiles.svelte';
import BulkCreatePanel from './components/BulkCreatePanel.svelte';
import UploadPresentationPanel from './components/UploadPresentationPanel.svelte';
import { rooms } from './stores.js';
</script>
......@@ -12,8 +13,9 @@
<div class="columns">
<div class="column is-one-quarter" id="sidebar">
<AttachRoomPanel/>
<ChatBroadcastPanel/>
<BulkCreatePanel/>
<ChatBroadcastPanel/>
<BulkCreatePanel/>
<UploadPresentationPanel/>
</div>
<div class="column" id="main-content">
<RoomTiles rooms={$rooms}/>
......
<script>
let prefix = "";
let amount;
async function handleBulkCreate() {
alert('Not yet implemented!')
}
</script>
<nav class="panel">
<p class="panel-heading">
......@@ -18,9 +22,9 @@
<input class="input" type="text" placeholder="Amount" bind:value={amount} />
</p>
<p class="control">
<a class="button is-success is-outlined">
<button class="button is-success is-outlined" on:click={handleBulkCreate}>
Create
</a>
</button>
</p>
</div>
<br />
......
......@@ -6,7 +6,7 @@
export let url;
export let name = '???';
export let userCount = -1;
export let users = [];
export const users = [];
function handleDetachClick() {
roomsToDetachFrom.update((rooms) => [...rooms, uid]);
......@@ -29,7 +29,7 @@
</div>
<footer class="card-footer">
<span href="#" class="card-footer-item">{userCount} 👤</span>
<a href="#" on:click={handleDetachClick} class="card-footer-item">Detach</a>
<button on:click={handleDetachClick} class="card-footer-item">Detach</button>
<a href={url} class="card-footer-item">Join</a>
</footer>
</div>
\ No newline at end of file
<script>
import { API_BASE_URL } from '../stores.js';
</script>
<nav class="panel">
<p class="panel-heading">
Upload presentation
</p>
<div class="panel-block">
<form action="{API_BASE_URL}/uploadPresentation" method="post" enctype="multipart/form-data">
<p class="control">
<input type="file" name="presentation" multiple="" max="10" accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.rtf,.odt,.ods,.odp,.odg,.odc,.odi,.jpg,.jpeg,.png"/>
</p>
<p class="control">
<input type="submit"/>
</p>
</form>
<br />
</div>
<div class="panel-block">
<button type="submit" class="button is-link is-outlined is-fullwidth" disabled={false} on:click={() => {}}>
Send to attached rooms
</button>
</div>
</nav>
const puppeteer = require("puppeteer");
const sleep = require("sleep-promise");
module.exports.createFreshPage = async function createFreshPage() {
const browser = await puppeteer.launch({
headless: HEADLESS,
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);
// Set displayname for program
await page.type("input.join-form", displayName);
// Join and load room
await page.click("button#room-join");
//await sleep(3000);
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);
};
......@@ -7,8 +7,8 @@ const chromiumPath =
const botDisplayName = "Puppet";
const bbbUrl = "https://bbb.fachschaften.org";
const roomUrl = "https://bbb.fachschaften.org/b/jon-kmr-9gk";
const username = "tudo-fsinfo-fsr-bot";
const password = "S4VKuhkASUWsTgL8";
const username = "username";
const password = "password";
(async () => {
const browser = await puppeteer.launch({
......
......@@ -33,6 +33,11 @@
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
"integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g=="
},
"append-field": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY="
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
......@@ -113,6 +118,38 @@
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"busboy": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
"requires": {
"dicer": "0.2.5",
"readable-stream": "1.1.x"
},
"dependencies": {
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
......@@ -128,6 +165,51 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
},
"dependencies": {
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
......@@ -158,6 +240,11 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
......@@ -190,6 +277,33 @@
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.781568.tgz",
"integrity": "sha512-9Uqnzy6m6zEStluH9iyJ3iHyaQziFnMnLeC8vK0eN6smiJmIx7+yB64d67C2lH/LZra+5cGscJAJsNXO+MdPMg=="
},
"dicer": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"requires": {
"readable-stream": "1.1.x",
"streamsearch": "0.1.2"
},
"dependencies": {
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -433,6 +547,11 @@
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
......@@ -482,6 +601,19 @@
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": {
"minimist": "^1.2.5"
}
},
"mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
......@@ -492,6 +624,21 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"multer": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz",
"integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==",
"requires": {
"append-field": "^1.0.0",
"busboy": "^0.2.11",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.1",
"object-assign": "^4.1.1",
"on-finished": "^2.3.0",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
}
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
......@@ -572,6 +719,17 @@
"find-up": "^4.0.0"
}
},
"prettier": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
"integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
"dev": true
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
......@@ -741,6 +899,11 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"streamsearch": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
......@@ -791,6 +954,11 @@
"mime-types": "~2.1.24"
}
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"unbzip2-stream": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
......@@ -830,6 +998,11 @@
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
......
......@@ -5,12 +5,15 @@
"main": "index..js",
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"cors": "^2.8.5",
"express": "^4.17.1",
"multer": "^1.4.2",
"puppeteer": "^5.2.1",
"sleep-promise": "^8.0.1"
},
"devDependencies": {},
"devDependencies": {
"prettier": "^2.1.2"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
......
const puppeteer = require("puppeteer");
const sleep = require("sleep-promise");
const { clearInterval } = require("timers");
const fs = require("fs");
const bbb = require("./bbb.js");
const HEADLESS =
process.env.HEADLESS !== undefined ? process.env.HEADLESS : true;
......@@ -49,9 +49,18 @@ async function handleAttachToRoom({
stateRoomUrl = roomUrl;
try {
// Attach browser to room
const page = await createFreshPage();
const authenticatedPage = await signIn(roomUrl, username, password, page);
const pageInRoom = await joinRoom(authenticatedPage, roomUrl, displayName);
const page = await bbb.createFreshPage();
const authenticatedPage = await bbb.signIn(
roomUrl,
username,
password,
page
);
const pageInRoom = await bbb.joinRoom(
authenticatedPage,
roomUrl,
displayName
);
roomPage = pageInRoom;
// Set up periodic screenshotting
......@@ -81,7 +90,7 @@ async function handleAttachToRoom({
async function handleTakeScreenshot(pathToSaveTo) {
try {
await screenShotPresentationArea(roomPage, pathToSaveTo);
await bbb.screenShotPresentationArea(roomPage, pathToSaveTo);
} catch (error) {
console.warn("Unable to take screenshot of room", stateRoomUrl);
}
......@@ -90,9 +99,9 @@ async function handleTakeScreenshot(pathToSaveTo) {
async function handleGetRoomInfo() {
try {
const promises = [
getUserCount(roomPage),
getUserList(roomPage),
getRoomName(roomPage),
bbb.getUserCount(roomPage),
bbb.getUserList(roomPage),
bbb.getRoomName(roomPage),
];
const userCount = await promises[0];
const userList = await promises[1];
......@@ -115,7 +124,7 @@ async function handleSendMessage({ content }) {
data: "Received content to send to chat: " + content,
});
try {
await sendChatMessage(roomPage, content);
await bbb.sendChatMessage(roomPage, content);
process.send({ eventName: "sendMessageSuccess", data: null });
} catch (error) {
console.error(error);
......@@ -134,134 +143,3 @@ async function handleDetach() {
await sleep(100);
process.exit(0);
}
// ----------------------------
// Utility functions
// ----------------------------
async function createFreshPage() {
const browser = await puppeteer.launch({
headless: HEADLESS,
defaultViewport: {
width: 1200,
height: 600,
isLandscape: true,
},
});
const context = await browser.createIncognitoBrowserContext();
return context.newPage();
}
async function joinRoom(page, roomUrl, displayName = "Puppet") {
await page.goto(roomUrl);
console.log("joinRoom > Gone to start page for", roomUrl);
// Set displayname for program
await page.type("input.join-form", displayName);
// Join and load room
await page.click("button#room-join");
//await sleep(3000);
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;
}
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");
}
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;
}
async function screenShotPresentationArea(authenticatedPage, path) {
const presentationAreaHandle = await authenticatedPage.$("div#container");
presentationAreaHandle.screenshot({ path, type: "jpeg", quality: 33 });
}
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]
);
}
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;
}
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);
}
......@@ -4,6 +4,7 @@ const cors = require("cors");
const path = require("path");
const cp = require("child_process");
const fs = require("fs");
const multer = require("multer");
const sleep = require("sleep-promise");
const PORT = process.env.PORT || 3000;
......@@ -83,6 +84,12 @@ const app = express();
app.use(express.static("public"));
app.use(bodyParser.json());
app.use(cors());
const fileUpload = multer({
dest: "uploads/",
limits: {
fileSize: 30 * 1000 * 1000, // ~= 30 MB
},
});
app.get("/api/preview/:roomUid", (req, res) => {
res.setHeader("Cache-Control", "max-age=2");
......@@ -156,6 +163,16 @@ app.post("/api/bulkcreate", async (req, res) => {
const { prefix, amount } = req.body;
});
app.post(
"/api/uploadPresentation",
fileUpload.array("presentation", 10),
async (req, res, next) => {
console.debug(req.files);
res.status(200).send({}).end();
return;
}
);
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment