From d5b9c82e1dfb06cfbe537117d4a5ddb595a59945 Mon Sep 17 00:00:00 2001 From: sualko Date: Thu, 17 Mar 2022 14:59:47 +0100 Subject: [PATCH] feat: add option to insert document to running meeting. Currently only available in debug mode, because BBB PHP API needs to be injected manually. --- appinfo/routes.php | 2 ++ lib/BigBlueButton/API.php | 11 +++++++++ lib/Controller/ServerController.php | 38 +++++++++++++++++++++++++++++ package.json | 1 + ts/Common/Api.ts | 18 +++++++++++--- ts/Nextcloud.d.ts | 2 ++ ts/filelist.ts | 35 +++++++++++++++++++++++--- yarn.lock | 27 ++++++++++++++++++++ 8 files changed, 128 insertions(+), 6 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index 8a9312a..2b70b37 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -8,6 +8,8 @@ return [ ], 'routes' => [ ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], + ['name' => 'server#isRunning', 'url' => '/server/{roomUid}/isRunning', 'verb' => 'GET'], + ['name' => 'server#insertDocument', 'url' => '/server/{roomUid}/insertDocument', 'verb' => 'POST'], ['name' => 'server#records', 'url' => '/server/{roomUid}/records', 'verb' => 'GET'], ['name' => 'server#check', 'url' => '/server/check', 'verb' => 'POST'], ['name' => 'server#version', 'url' => '/server/version', 'verb' => 'GET'], diff --git a/lib/BigBlueButton/API.php b/lib/BigBlueButton/API.php index 378b2e4..2176ca3 100644 --- a/lib/BigBlueButton/API.php +++ b/lib/BigBlueButton/API.php @@ -7,6 +7,7 @@ use BigBlueButton\Core\Record; use BigBlueButton\Parameters\CreateMeetingParameters; use BigBlueButton\Parameters\DeleteRecordingsParameters; use BigBlueButton\Parameters\GetRecordingsParameters; +use BigBlueButton\Parameters\InsertDocumentParameters; use BigBlueButton\Parameters\IsMeetingRunningParameters; use BigBlueButton\Parameters\JoinMeetingParameters; use OCA\BigBlueButton\AppInfo\Application; @@ -320,4 +321,14 @@ class API { return $response->success() && $response->isRunning(); } + + public function insertDocument(Room $room, string $url, string $filename): bool { + $insertDocumentParams = new InsertDocumentParameters($room->getUid()); + + $insertDocumentParams->addPresentation($url, $filename, null, null); + + $response = $this->getServer()->insertDocument($insertDocumentParams); + + return $response->success(); + } } diff --git a/lib/Controller/ServerController.php b/lib/Controller/ServerController.php index 3ffc0d3..fd1eaf5 100644 --- a/lib/Controller/ServerController.php +++ b/lib/Controller/ServerController.php @@ -40,6 +40,44 @@ class ServerController extends Controller { $this->userId = $UserId; } + /** + * @NoAdminRequired + */ + public function isRunning(string $roomUid): DataResponse { + $room = $this->service->findByUid($roomUid); + + if ($room === null) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + + if (!$this->permission->isUser($room, $this->userId)) { + return new DataResponse([], Http::STATUS_FORBIDDEN); + } + + $isRunning = $this->server->isRunning($room); + + return new DataResponse($isRunning); + } + + /** + * @NoAdminRequired + */ + public function insertDocument(string $roomUid, string $url, string $filename): DataResponse { + $room = $this->service->findByUid($roomUid); + + if ($room === null) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + + if (!$this->permission->isModerator($room, $this->userId)) { + return new DataResponse([], Http::STATUS_FORBIDDEN); + } + + $success = $this->server->insertDocument($room, $url, $filename); + + return new DataResponse($success); + } + /** * @NoAdminRequired */ diff --git a/package.json b/package.json index 85bbda1..99ed369 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@commitlint/config-conventional": "^16.2.1", "@commitlint/travis-cli": "^16.2.3", "@nextcloud/axios": "^1.3.2", + "@nextcloud/dialogs": "^3.1.2", "@nextcloud/router": "^2.0.0", "@octokit/rest": "^18.0.4", "archiver": "^5.0.0", diff --git a/ts/Common/Api.ts b/ts/Common/Api.ts index fa6bf1c..6a2c278 100644 --- a/ts/Common/Api.ts +++ b/ts/Common/Api.ts @@ -133,6 +133,18 @@ class Api { return response.data; } + public async isRunning(uid: string): Promise { + const response = await axios.get(this.getUrl(`server/${uid}/isRunning`)); + + return response.data; + } + + public async insertDocument(uid: string, url: string, filename: string): Promise { + const response = await axios.post(this.getUrl(`server/${uid}/insertDocument`), { url, filename }); + + return response.data; + } + public getRoomUrl(room: Room, forModerator = false) { const shortener = document.getElementById('bbb-root')?.getAttribute('data-shortener') || ''; const token = (forModerator && room.moderatorToken) ? `${room.uid}/${room.moderatorToken}` : room.uid; @@ -258,9 +270,9 @@ class Api { groups: [], circles: [], exact: { - users: response.data.ocs.data.exact.users, - groups: response.data.ocs.data.exact.groups, - circles: response.data.ocs.data.exact.circles || [], + users: response.data.ocs.data.exact.users, + groups: response.data.ocs.data.exact.groups, + circles: response.data.ocs.data.exact.circles || [], }, }; } diff --git a/ts/Nextcloud.d.ts b/ts/Nextcloud.d.ts index 20cff3c..aca254a 100644 --- a/ts/Nextcloud.d.ts +++ b/ts/Nextcloud.d.ts @@ -73,6 +73,8 @@ declare namespace OC { const PERMISSION_SHARE = 16; const PERMISSION_ALL = 31; + const debug: boolean; + const currentUser: string; function getCurrentUser(): {uid: string; displayName: string} diff --git a/ts/filelist.ts b/ts/filelist.ts index 4846e0f..c0d2572 100644 --- a/ts/filelist.ts +++ b/ts/filelist.ts @@ -1,5 +1,7 @@ import axios from '@nextcloud/axios'; import { generateOcsUrl, generateUrl } from '@nextcloud/router'; +import { showSuccess, showWarning, showError } from '@nextcloud/dialogs'; +import '@nextcloud/dialogs/styles/toast'; import { api } from './Common/Api'; type OC_Dialogs_Message = (content: string, title: string, dialogType: 'notice' | 'alert' | 'warn' | 'none', buttons?: number, callback?: () => void, modal?: boolean, allowHtml?: boolean) => Promise; @@ -38,8 +40,7 @@ async function createDirectShare(fileId: number): Promise { return createResponse.data?.ocs?.data?.url; } -async function share(fileId: number, filename: string, roomUid: string) { - const shareUrl = await createDirectShare(fileId); +async function createRoomWithFile(shareUrl: string, filename: string, roomUid: string) { const joinUrl = generateUrl('/apps/bbb/b/{uid}?u={url}&filename={filename}', { uid: roomUid, url: shareUrl, @@ -49,6 +50,31 @@ async function share(fileId: number, filename: string, roomUid: string) { window.open(joinUrl, '_blank', 'noopener,noreferrer'); } +function insertDocumentToRoom(shareUrl: string, filename: string, roomUid: string) { + return api.insertDocument(roomUid, shareUrl, filename); +} + +async function sendFile(fileId: number, filename: string, roomUid: string) { + const shareUrl = await createDirectShare(fileId); + const isRunning = await api.isRunning(roomUid); + + if (isRunning) { + try { + const success = await insertDocumentToRoom(shareUrl, filename, roomUid); + + if (success) { + showSuccess(t('bbb', 'The file "{filename}" was uploaded to your room.', { filename })); + } else { + showWarning(t('bbb', 'The file "{filename}" could not be uploaded to your room.', { filename })); + } + } catch { + showError(t('bbb', 'The file "{filename}" could not be uploaded to your room. Maybe your BigBlueButton server does not support this action.', { filename })); + } + } else { + createRoomWithFile(shareUrl, filename, roomUid); + } +} + async function openDialog(fileId: number, filename: string) { const initContent = '
'; const title = t('bbb', 'Send file to BBB'); @@ -65,13 +91,16 @@ async function openDialog(fileId: number, filename: string) { const row = $(''); const button = $('