Merge branch 'v2.7.x-release' into bbb-wake-locke

This commit is contained in:
Anton Georgiev 2023-07-14 07:50:04 -04:00 committed by GitHub
commit 45215ed88f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
565 changed files with 14409 additions and 5405 deletions

View File

@ -43,6 +43,8 @@ jobs:
- run: ./build/setup.sh bbb-record-core
- run: ./build/setup.sh bbb-web
- run: ./build/setup.sh bbb-webrtc-sfu
- run: ./build/setup.sh bbb-webrtc-recorder
- run: ./build/setup.sh bbb-transcription-controller
- run: ./build/setup.sh bigbluebutton
- run: tar cvf artifacts.tar artifacts/
- name: Archive packages
@ -120,8 +122,8 @@ jobs:
- name: Install BBB
run: |
sudo sh -c '
cd /root/ && wget -q https://ubuntu.bigbluebutton.org/bbb-install-2.6.sh -O bbb-install.sh
cat bbb-install.sh | sed "s|> /etc/apt/sources.list.d/bigbluebutton.list||g" | bash -s -- -v focal-26-dev -s bbb-ci.test -j -d /certs/
cd /root/ && wget -q https://raw.githubusercontent.com/bigbluebutton/bbb-install/v2.7.x-release/bbb-install.sh -O bbb-install.sh
cat bbb-install.sh | sed "s|> /etc/apt/sources.list.d/bigbluebutton.list||g" | bash -s -- -v focal-27-dev -s bbb-ci.test -j -d /certs/
bbb-conf --salt bbbci
echo "NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/bbb-dev/bbb-dev-ca.crt" >> /usr/share/meteor/bundle/bbb-html5-with-roles.conf
sed -i "s/\"minify\": true,/\"minify\": false,/" /usr/share/etherpad-lite/settings.json
@ -182,6 +184,7 @@ jobs:
cp /etc/bigbluebutton/bigbluebutton-release configs/bigbluebutton-release
cp /etc/bigbluebutton/turn-stun-servers.xml configs/turn-stun-servers.xml
cp /usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml configs/bbb-webrtc-sfu-default.yml
cp /etc/bbb-webrtc-recorder/bbb-webrtc-recorder.yml configs/bbb-webrtc-recorder-default.yml
cp /usr/share/bigbluebutton/nginx/sip.nginx configs/nginx_sip.nginx
cp /etc/hosts /configs/hosts
chmod a+r -R configs
@ -197,4 +200,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: bbb-logs
path: ./bbb-logs.tar.gz
path: ./bbb-logs.tar.gz

View File

@ -7,6 +7,7 @@ on:
- 'develop'
paths:
- 'docs/**'
- '.github/**'
# Do not build the docs concurrently
concurrency:

View File

@ -12,7 +12,7 @@ stages:
# define which docker image to use for builds
default:
image: gitlab.senfcall.de:5050/senfcall-public/docker-bbb-build:v2022-12-29-grails-524
image: bigbluebutton/bbb-build:bbb27-2023-06-13-java17
# This stage uses git to find out since when each package has been unmodified.
# it then checks an API endpoint on the package server to find out for which of
@ -47,11 +47,13 @@ get_external_dependencies:
- bbb-etherpad
- bbb-webhooks
- bbb-webrtc-sfu
- bbb-webrtc-recorder
- freeswitch
- bbb-pads
- bbb-playback
- bbb-transcription-controller
expire_in: 1h 30min
# template job for build step
.build_job:
stage: build
@ -170,6 +172,16 @@ bbb-webrtc-sfu-build:
script:
- build/setup-inside-docker.sh bbb-webrtc-sfu
bbb-webrtc-recorder-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-webrtc-recorder
bbb-transcription-controller-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-transcription-controller
bigbluebutton-build:
extends: .build_job
script:
@ -180,12 +192,12 @@ push_packages:
stage: push packages
script: build/push_packages.sh
resource_group: push_packages
# uncomment the lines below if you want one final
# "artifacts" dir with all packages (increases runtime, fills up space on gitlab server)
# uncomment the lines below if you want one final
# "artifacts" dir with all packages (increases runtime, fills up space on gitlab server)
#artifacts:
# paths:
# - artifacts/*
# expire_in: 2 days

View File

@ -18,7 +18,7 @@ val compileSettings = Seq(
"-Xlint",
"-Ywarn-dead-code",
"-language:_",
"-target:11",
"-release:17",
"-encoding", "UTF-8"
),
javacOptions ++= List(
@ -76,4 +76,4 @@ daemonGroup in Linux := group
javaOptions in Universal ++= Seq("-J-Xms130m", "-J-Xmx256m", "-Dconfig.file=/etc/bigbluebutton/bbb-apps-akka.conf", "-Dlogback.configurationFile=conf/logback.xml")
debianPackageDependencies in Debian ++= Seq("java11-runtime-headless", "bash")
debianPackageDependencies in Debian ++= Seq("java17-runtime-headless", "bash")

View File

@ -27,7 +27,8 @@ object BreakoutModel {
case class BreakoutModel(
startedOn: Option[Long],
durationInSeconds: Int,
rooms: Map[String, BreakoutRoom2x]
rooms: Map[String, BreakoutRoom2x],
sendInviteToModerators: Boolean,
) {
def find(id: String): Option[BreakoutRoom2x] = {

View File

@ -91,6 +91,14 @@ object ScreenshareModel {
def getHasAudio(status: ScreenshareModel): Boolean = {
status.hasAudio
}
def setContentType(status: ScreenshareModel, contentType: String): Unit = {
status.contentType = contentType
}
def getContentType(status: ScreenshareModel): String = {
status.contentType
}
}
class ScreenshareModel {
@ -103,4 +111,5 @@ class ScreenshareModel {
private var screenshareConf: String = ""
private var timestamp: String = ""
private var hasAudio = false
private var contentType = "camera"
}

View File

@ -0,0 +1,100 @@
package org.bigbluebutton.core.apps
object TimerModel {
def createTimer(
model: TimerModel,
stopwatch: Boolean = true,
time: Int = 0,
accumulated: Int = 0,
track: String = "",
): Unit = {
model.stopwatch = stopwatch
model.time = time
model.accumulated = accumulated
model.track = track
}
def reset(model: TimerModel, stopwatch: Boolean, time: Int, accumulated: Int, startedAt: Long, track: String) : Unit = {
model.stopwatch = stopwatch
model.time = time
model.accumulated = accumulated
model.startedAt = startedAt
model.track = track
model.endedAt = 0
}
def setIsActive(model: TimerModel, active: Boolean): Unit = {
model.isActive = active
}
def getIsACtive(model: TimerModel): Boolean = {
model.isActive
}
def setStartedAt(model: TimerModel, timestamp: Long): Unit = {
model.startedAt = timestamp
}
def getStartedAt(model: TimerModel): Long = {
model.startedAt
}
def setAccumulated(model: TimerModel, accumulated: Int): Unit = {
model.accumulated = accumulated
}
def getAccumulated(model: TimerModel): Int = {
model.accumulated
}
def setRunning(model: TimerModel, running: Boolean): Unit = {
model.running = running
}
def getRunning(model: TimerModel): Boolean = {
model.running
}
def setStopwatch(model: TimerModel, stopwatch: Boolean): Unit = {
model.stopwatch = stopwatch
}
def getStopwatch(model: TimerModel): Boolean = {
model.stopwatch
}
def setTrack(model: TimerModel, track: String): Unit = {
model.track = track
}
def getTrack(model: TimerModel): String = {
model.track
}
def setTime(model: TimerModel, time: Int): Unit = {
model.time = time
}
def getTime(model: TimerModel): Int = {
model.time
}
def setEndedAt(model: TimerModel, timestamp: Long): Unit = {
model.endedAt = timestamp
}
def getEndedAt(model: TimerModel): Long = {
model.endedAt
}
}
class TimerModel {
private var startedAt: Long = 0
private var endedAt: Long = 0
private var accumulated: Int = 0
private var running: Boolean = false
private var time: Int = 0
private var stopwatch: Boolean = true
private var track: String = ""
private var isActive: Boolean = false
}

View File

@ -11,11 +11,11 @@ trait UpdateTranscriptPubMsgHdlr {
def handle(msg: UpdateTranscriptPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
val meetingId = liveMeeting.props.meetingProp.intId
def broadcastEvent(userId: String, transcriptId: String, transcript: String, locale: String): Unit = {
def broadcastEvent(userId: String, transcriptId: String, transcript: String, locale: String, result: Boolean): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, "nodeJSapp")
val envelope = BbbCoreEnvelope(TranscriptUpdatedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(TranscriptUpdatedEvtMsg.NAME, meetingId, userId)
val body = TranscriptUpdatedEvtMsgBody(transcriptId, transcript, locale)
val body = TranscriptUpdatedEvtMsgBody(transcriptId, transcript, locale, result)
val event = TranscriptUpdatedEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
@ -67,7 +67,8 @@ trait UpdateTranscriptPubMsgHdlr {
msg.header.userId,
msg.body.transcriptId,
transcript,
msg.body.locale
msg.body.locale,
msg.body.result,
)
}
}

View File

@ -35,12 +35,12 @@ trait BreakoutRoomCreatedMsgHdlr {
}
}
def buildBreakoutRoomsListEvtMsg(meetingId: String, rooms: Vector[BreakoutRoomInfo], roomsReady: Boolean): BbbCommonEnvCoreMsg = {
def buildBreakoutRoomsListEvtMsg(meetingId: String, rooms: Vector[BreakoutRoomInfo], roomsReady: Boolean, sendInviteToModerators: Boolean): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(BreakoutRoomsListEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(BreakoutRoomsListEvtMsg.NAME, meetingId, "not-used")
val body = BreakoutRoomsListEvtMsgBody(meetingId, rooms, roomsReady)
val body = BreakoutRoomsListEvtMsgBody(meetingId, rooms, roomsReady, sendInviteToModerators)
val event = BreakoutRoomsListEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
@ -57,7 +57,7 @@ trait BreakoutRoomCreatedMsgHdlr {
log.info("Sending breakout rooms list to {} with containing {} room(s)", liveMeeting.props.meetingProp.intId, breakoutRooms.length)
val msgEvent = buildBreakoutRoomsListEvtMsg(liveMeeting.props.meetingProp.intId, breakoutRooms, true)
val msgEvent = buildBreakoutRoomsListEvtMsg(liveMeeting.props.meetingProp.intId, breakoutRooms, true, breakoutModel.sendInviteToModerators)
outGW.send(msgEvent)
breakoutModel

View File

@ -11,14 +11,14 @@ trait BreakoutRoomsListMsgHdlr {
def handleBreakoutRoomsListMsg(msg: BreakoutRoomsListMsg, state: MeetingState2x): MeetingState2x = {
def broadcastEvent(rooms: Vector[BreakoutRoomInfo], roomsReady: Boolean): Unit = {
def broadcastEvent(rooms: Vector[BreakoutRoomInfo], roomsReady: Boolean, sendInviteToModerators: Boolean): Unit = {
log.info("Sending breakout rooms list to {} with containing {} room(s)", props.meetingProp.intId, rooms.length)
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, props.meetingProp.intId, msg.header.userId)
val envelope = BbbCoreEnvelope(BreakoutRoomsListEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(BreakoutRoomsListEvtMsg.NAME, props.meetingProp.intId, msg.header.userId)
val body = BreakoutRoomsListEvtMsgBody(msg.body.meetingId, rooms, roomsReady)
val body = BreakoutRoomsListEvtMsgBody(msg.body.meetingId, rooms, roomsReady, sendInviteToModerators)
val event = BreakoutRoomsListEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
outGW.send(msgEvent)
@ -31,7 +31,7 @@ trait BreakoutRoomsListMsgHdlr {
new BreakoutRoomInfo(r.name, r.externalId, r.id, r.sequence, r.shortName, r.isDefaultName, r.freeJoin, Map(), r.captureNotes, r.captureSlides)
}
val ready = breakoutModel.hasAllStarted()
broadcastEvent(rooms, ready)
broadcastEvent(rooms, ready, breakoutModel.sendInviteToModerators)
}
state

View File

@ -84,7 +84,7 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
outGW.send(event)
}
val breakoutModel = new BreakoutModel(None, msg.body.durationInMinutes * 60, rooms)
val breakoutModel = new BreakoutModel(None, msg.body.durationInMinutes * 60, rooms, msg.body.sendInviteToModerators)
state.update(Some(breakoutModel))
}

View File

@ -8,10 +8,11 @@ import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.util.RandomStringGenerator
import org.bigbluebutton.core.models.{ PresentationPod, PresentationPage, PresentationInPod }
import org.bigbluebutton.core.models.{ PresentationInPod, PresentationPage, PresentationPod }
import java.io.File
trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait {
trait MakePresentationDownloadReqMsgHdlr extends RightsManagementTrait {
this: PresentationPodHdlrs =>
object JobTypes {
@ -40,20 +41,20 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait {
BbbCommonEnvCoreMsg(envelope, event)
}
def buildNewPresAnnFileAvailable(fileURI: String, presId: String): NewPresAnnFileAvailableMsg = {
val header = BbbClientMsgHeader(NewPresAnnFileAvailableMsg.NAME, "not-used", "not-used")
val body = NewPresAnnFileAvailableMsgBody(fileURI, presId)
def buildNewPresFileAvailable(fileURI: String, presId: String, typeOfExport: String): NewPresFileAvailableMsg = {
val header = BbbClientMsgHeader(NewPresFileAvailableMsg.NAME, "not-used", "not-used")
val body = NewPresFileAvailableMsgBody(fileURI, presId, typeOfExport)
NewPresAnnFileAvailableMsg(header, body)
NewPresFileAvailableMsg(header, body)
}
def buildBroadcastNewPresAnnFileAvailable(newPresAnnFileAvailableMsg: NewPresAnnFileAvailableMsg, liveMeeting: LiveMeeting): BbbCommonEnvCoreMsg = {
def buildBroadcastNewPresFileAvailable(newPresFileAvailableMsg: NewPresFileAvailableMsg, liveMeeting: LiveMeeting): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, "not-used")
val envelope = BbbCoreEnvelope(PresentationPageConvertedEventMsg.NAME, routing)
val header = BbbClientMsgHeader(NewPresAnnFileAvailableEvtMsg.NAME, liveMeeting.props.meetingProp.intId, "not-used")
val body = NewPresAnnFileAvailableEvtMsgBody(fileURI = newPresAnnFileAvailableMsg.body.fileURI, presId = newPresAnnFileAvailableMsg.body.presId)
val event = NewPresAnnFileAvailableEvtMsg(header, body)
val header = BbbClientMsgHeader(NewPresFileAvailableEvtMsg.NAME, liveMeeting.props.meetingProp.intId, "not-used")
val body = NewPresFileAvailableEvtMsgBody(fileURI = newPresFileAvailableMsg.body.fileURI, presId = newPresFileAvailableMsg.body.presId,
typeOfExport = newPresFileAvailableMsg.body.typeOfExport)
val event = NewPresFileAvailableEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
@ -112,7 +113,7 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait {
}
}
def handle(m: MakePresentationWithAnnotationDownloadReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
def handle(m: MakePresentationDownloadReqMsg, state: MeetingState2x, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
val meetingId = liveMeeting.props.meetingProp.intId
val userId = m.header.userId
@ -145,9 +146,9 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait {
val exportJob: ExportJob = new ExportJob(jobId, JobTypes.DOWNLOAD, "annotated_slides", presId, presLocation, allPages, pagesRange, meetingId, "");
val storeAnnotationPages: List[PresentationPageForExport] = getPresentationPagesForExport(pagesRange, pageCount, presId, currentPres, liveMeeting);
val annotationCount: Int = storeAnnotationPages.map(_.annotations.size).sum
val isOriginalPresentationType = m.body.typeOfExport == "Original"
if (annotationCount > 0) {
if (!isOriginalPresentationType) {
// Send Export Job to Redis
val job = buildStoreExportJobInRedisSysMsg(exportJob, liveMeeting)
bus.outGW.send(job)
@ -157,13 +158,14 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait {
bus.outGW.send(buildStoreAnnotationsInRedisSysMsg(annotations, liveMeeting))
} else {
// Return existing uploaded file directly
val filename = currentPres.get.name
val convertedFileName = currentPres.get.filenameConverted
val filename = if (convertedFileName == "") currentPres.get.name else convertedFileName
val presFilenameExt = filename.split("\\.").last
PresentationSender.broadcastSetPresentationDownloadableEvtMsg(bus, meetingId, "DEFAULT_PRESENTATION_POD", "not-used", presId, true, filename)
val fileURI = List("bigbluebutton", "presentation", "download", meetingId, s"${presId}?presFilename=${presId}.${presFilenameExt}").mkString(File.separator, File.separator, "")
val event = buildNewPresAnnFileAvailable(fileURI, presId)
val fileURI = List("bigbluebutton", "presentation", "download", meetingId, s"${presId}?presFilename=${presId}.${presFilenameExt}&filename=${filename}").mkString("", File.separator, "")
val event = buildNewPresFileAvailable(fileURI, presId, m.body.typeOfExport)
handle(event, liveMeeting, bus)
}
@ -221,9 +223,9 @@ trait PresentationWithAnnotationsMsgHdlr extends RightsManagementTrait {
}
}
def handle(m: NewPresAnnFileAvailableMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.info("Received NewPresAnnFileAvailableMsg meetingId={} presId={} fileUrl={}", liveMeeting.props.meetingProp.intId, m.body.presId, m.body.fileURI)
bus.outGW.send(buildBroadcastNewPresAnnFileAvailable(m, liveMeeting))
def handle(m: NewPresFileAvailableMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.info("Received NewPresFileAvailableMsg meetingId={} presId={} fileUrl={}", liveMeeting.props.meetingProp.intId, m.body.presId, m.body.fileURI)
bus.outGW.send(buildBroadcastNewPresFileAvailable(m, liveMeeting))
}
def handle(m: CaptureSharedNotesReqInternalMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {

View File

@ -3,6 +3,7 @@ package org.bigbluebutton.core.apps.presentationpod
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.models.PresentationInPod
import org.bigbluebutton.core.running.LiveMeeting
trait PresentationConversionCompletedSysPubMsgHdlr {
@ -22,8 +23,7 @@ trait PresentationConversionCompletedSysPubMsgHdlr {
pres <- pod.getPresentation(msg.body.presentation.id)
} yield {
val presVO = PresentationPodsApp.translatePresentationToPresentationVO(pres, temporaryPresentationId,
msg.body.presentation.isInitialPresentation)
msg.body.presentation.isInitialPresentation, msg.body.presentation.filenameConverted)
PresentationSender.broadcastPresentationConversionCompletedEvtMsg(
bus,
meetingId,
@ -31,7 +31,7 @@ trait PresentationConversionCompletedSysPubMsgHdlr {
msg.header.userId,
msg.body.messageKey,
msg.body.code,
presVO
presVO,
)
PresentationSender.broadcastSetPresentationDownloadableEvtMsg(
bus,
@ -43,8 +43,10 @@ trait PresentationConversionCompletedSysPubMsgHdlr {
pres.name
)
val presWithConvertedName = PresentationInPod(pres.id, pres.name, pres.current, pres.pages,
pres.downloadable, pres.removable, msg.body.presentation.filenameConverted)
var pods = state.presentationPodManager.addPod(pod)
pods = pods.addPresentationToPod(pod.id, pres)
pods = pods.addPresentationToPod(pod.id, presWithConvertedName)
state.update(pods)
}

View File

@ -19,7 +19,7 @@ class PresentationPodHdlrs(implicit val context: ActorContext)
with PresentationPageCountErrorPubMsgHdlr
with PresentationUploadedFileTooLargeErrorPubMsgHdlr
with PresentationUploadTokenReqMsgHdlr
with PresentationWithAnnotationsMsgHdlr
with MakePresentationDownloadReqMsgHdlr
with ResizeAndMovePagePubMsgHdlr
with SyncGetPresentationPodsMsgHdlr
with RemovePresentationPodPubMsgHdlr

View File

@ -58,7 +58,7 @@ object PresentationPodsApp {
}
PresentationVO(p.id, "", p.name, p.current,
pages.toVector, p.downloadable, p.removable, false)
pages.toVector, p.downloadable, p.removable, false, "")
}
PresentationPodVO(pod.id, pod.currentPresenter, presentationVOs.toVector)
@ -74,7 +74,7 @@ object PresentationPodsApp {
}
def translatePresentationToPresentationVO(pres: PresentationInPod, temporaryPresentationId: String,
isInitialPresentation: Boolean): PresentationVO = {
isInitialPresentation: Boolean, filenameConverted: String): PresentationVO = {
val pages = pres.pages.values.map { page =>
PageVO(
id = page.id,
@ -89,8 +89,8 @@ object PresentationPodsApp {
heightRatio = page.heightRatio
)
}
PresentationVO(pres.id, temporaryPresentationId, pres.name, pres.current, pages.toVector, pres.downloadable, pres.removable,
isInitialPresentation)
PresentationVO(pres.id, temporaryPresentationId, pres.name, pres.current, pages.toVector, pres.downloadable,
pres.removable, isInitialPresentation, filenameConverted)
}
def setCurrentPresentationInPod(state: MeetingState2x, podId: String, nextCurrentPresId: String): Option[PresentationPod] = {

View File

@ -11,7 +11,7 @@ object PresentationSender {
podId: String, userId: String,
presentationId: String,
downloadable: Boolean,
presFilename: String
presFilename: String,
): Unit = {
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
@ -30,7 +30,7 @@ object PresentationSender {
bus: MessageBus,
meetingId: String,
podId: String, userId: String, messageKey: String,
code: String, presentation: PresentationVO
code: String, presentation: PresentationVO,
): Unit = {
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,

View File

@ -17,11 +17,8 @@ trait GetScreenBroadcastPermissionReqMsgHdlr {
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
} yield {
if (props.meetingProp.disabledFeatures.contains("screenshare")) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "Screen sharing is disabled for this meeting."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
} else if (permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
if (permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL,
liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to share the screen."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)

View File

@ -26,9 +26,10 @@ trait GetScreenshareStatusReqMsgHdlr {
val vidHeight = ScreenshareModel.getScreenshareVideoHeight(liveMeeting.screenshareModel)
val timestamp = ScreenshareModel.getTimestamp(liveMeeting.screenshareModel)
val hasAudio = ScreenshareModel.getHasAudio(liveMeeting.screenshareModel)
val contentType = ScreenshareModel.getContentType(liveMeeting.screenshareModel)
val body = ScreenshareRtmpBroadcastStartedEvtMsgBody(voiceConf, screenshareConf,
stream, vidWidth, vidHeight, timestamp, hasAudio)
stream, vidWidth, vidHeight, timestamp, hasAudio, contentType)
val event = ScreenshareRtmpBroadcastStartedEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}

View File

@ -10,7 +10,7 @@ trait ScreenshareRtmpBroadcastStartedVoiceConfEvtMsgHdlr {
def handle(msg: ScreenshareRtmpBroadcastStartedVoiceConfEvtMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
def broadcastEvent(voiceConf: String, screenshareConf: String, stream: String, vidWidth: Int, vidHeight: Int,
timestamp: String, hasAudio: Boolean): BbbCommonEnvCoreMsg = {
timestamp: String, hasAudio: Boolean, contentType: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
@ -23,7 +23,7 @@ trait ScreenshareRtmpBroadcastStartedVoiceConfEvtMsgHdlr {
)
val body = ScreenshareRtmpBroadcastStartedEvtMsgBody(voiceConf, screenshareConf,
stream, vidWidth, vidHeight, timestamp, hasAudio)
stream, vidWidth, vidHeight, timestamp, hasAudio, contentType)
val event = ScreenshareRtmpBroadcastStartedEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
@ -32,28 +32,39 @@ trait ScreenshareRtmpBroadcastStartedVoiceConfEvtMsgHdlr {
ScreenshareModel.isBroadcastingRTMP(liveMeeting.screenshareModel) +
" URL:" + ScreenshareModel.getRTMPBroadcastingUrl(liveMeeting.screenshareModel))
// only valid if not broadcasting yet
if (!ScreenshareModel.isBroadcastingRTMP(liveMeeting.screenshareModel)) {
// Stop external video if it's running
ExternalVideoModel.stop(bus.outGW, liveMeeting)
ScreenshareModel.setRTMPBroadcastingUrl(liveMeeting.screenshareModel, msg.body.stream)
ScreenshareModel.broadcastingRTMPStarted(liveMeeting.screenshareModel)
ScreenshareModel.setScreenshareVideoWidth(liveMeeting.screenshareModel, msg.body.vidWidth)
ScreenshareModel.setScreenshareVideoHeight(liveMeeting.screenshareModel, msg.body.vidHeight)
ScreenshareModel.setVoiceConf(liveMeeting.screenshareModel, msg.body.voiceConf)
ScreenshareModel.setScreenshareConf(liveMeeting.screenshareModel, msg.body.screenshareConf)
ScreenshareModel.setTimestamp(liveMeeting.screenshareModel, msg.body.timestamp)
ScreenshareModel.setHasAudio(liveMeeting.screenshareModel, msg.body.hasAudio)
log.info("START broadcast ALLOWED when isBroadcastingRTMP=false")
// Notify viewers in the meeting that there's an rtmp stream to view
val msgEvent = broadcastEvent(msg.body.voiceConf, msg.body.screenshareConf, msg.body.stream,
msg.body.vidWidth, msg.body.vidHeight, msg.body.timestamp, msg.body.hasAudio)
bus.outGW.send(msgEvent)
if (msg.body.contentType == "camera" && liveMeeting.props.meetingProp.disabledFeatures.contains("cameraAsContent")) {
log.error(
"Camera as a content is disabled for meeting {}, meetingID = {}",
liveMeeting.props.meetingProp.name, liveMeeting.props.meetingProp.intId
)
} else if (msg.body.contentType == "screenshare" && liveMeeting.props.meetingProp.disabledFeatures.contains("screenshare")) {
val meetingId = liveMeeting.props.meetingProp.intId
log.error("Screen sharing is disabled for this meeting, meetingID = {}", meetingId)
} else {
log.info("START broadcast NOT ALLOWED when isBroadcastingRTMP=true")
// only valid if not broadcasting yet
if (!ScreenshareModel.isBroadcastingRTMP(liveMeeting.screenshareModel)) {
// Stop external video if it's running
ExternalVideoModel.stop(bus.outGW, liveMeeting)
ScreenshareModel.setRTMPBroadcastingUrl(liveMeeting.screenshareModel, msg.body.stream)
ScreenshareModel.broadcastingRTMPStarted(liveMeeting.screenshareModel)
ScreenshareModel.setScreenshareVideoWidth(liveMeeting.screenshareModel, msg.body.vidWidth)
ScreenshareModel.setScreenshareVideoHeight(liveMeeting.screenshareModel, msg.body.vidHeight)
ScreenshareModel.setVoiceConf(liveMeeting.screenshareModel, msg.body.voiceConf)
ScreenshareModel.setScreenshareConf(liveMeeting.screenshareModel, msg.body.screenshareConf)
ScreenshareModel.setTimestamp(liveMeeting.screenshareModel, msg.body.timestamp)
ScreenshareModel.setHasAudio(liveMeeting.screenshareModel, msg.body.hasAudio)
ScreenshareModel.setContentType(liveMeeting.screenshareModel, msg.body.contentType)
log.info("START broadcast ALLOWED when isBroadcastingRTMP=false")
// Notify viewers in the meeting that there's an rtmp stream to view
val msgEvent = broadcastEvent(msg.body.voiceConf, msg.body.screenshareConf, msg.body.stream,
msg.body.vidWidth, msg.body.vidHeight, msg.body.timestamp, msg.body.hasAudio, msg.body.contentType)
bus.outGW.send(msgEvent)
} else {
log.info("START broadcast NOT ALLOWED when isBroadcastingRTMP=true")
}
}
}

View File

@ -27,7 +27,8 @@ trait SyncGetScreenshareInfoRespMsgHdlr {
ScreenshareModel.getScreenshareVideoWidth(liveMeeting.screenshareModel),
ScreenshareModel.getScreenshareVideoHeight(liveMeeting.screenshareModel),
ScreenshareModel.getTimestamp(liveMeeting.screenshareModel),
ScreenshareModel.getHasAudio(liveMeeting.screenshareModel)
ScreenshareModel.getHasAudio(liveMeeting.screenshareModel),
ScreenshareModel.getContentType(liveMeeting.screenshareModel)
)
val event = SyncGetScreenshareInfoRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)

View File

@ -0,0 +1,50 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait ActivateTimerReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: ActivateTimerReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received ActivateTimerReqMsg {}", ActivateTimerReqMsg)
def broadcastEvent(
stopwatch: Boolean,
running: Boolean,
time: Int,
accumulated: Int,
track: String
): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(ActivateTimerRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
ActivateTimerRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = ActivateTimerRespMsgBody(msg.header.userId, stopwatch, running, time, accumulated, track)
val event = ActivateTimerRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
val isTimerFeatureEnabled: Boolean = !liveMeeting.props.meetingProp.disabledFeatures.contains("timer")
if (!isTimerFeatureEnabled) {
log.error("Timer feature is disabled for meeting {}, meetingId={}", liveMeeting.props.meetingProp.name,
liveMeeting.props.meetingProp.intId)
} else {
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to activate timer"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
TimerModel.reset(liveMeeting.timerModel, msg.body.stopwatch, msg.body.time, msg.body.accumulated, msg.body.timestamp, msg.body.track)
TimerModel.setIsActive(liveMeeting.timerModel, true)
broadcastEvent(msg.body.stopwatch, msg.body.running, msg.body.time, msg.body.accumulated, msg.body.track)
}
}
}
}

View File

@ -0,0 +1,15 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait CreateTimerPubMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: CreateTimerPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received CreateTimerPubMsg {}", CreateTimerPubMsg)
TimerModel.createTimer(liveMeeting.timerModel, msg.body.stopwatch, msg.body.time, msg.body.accumulated, msg.body.track)
}
}

View File

@ -0,0 +1,36 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait DeactivateTimerReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: DeactivateTimerReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received deactivateTimerReqMsg {}", DeactivateTimerReqMsg)
def broadcastEvent(): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(DeactivateTimerRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
DeactivateTimerRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = DeactivateTimerRespMsgBody(msg.header.userId)
val event = DeactivateTimerRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to deactivate timer"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
TimerModel.setIsActive(liveMeeting.timerModel, false);
broadcastEvent()
}
}
}

View File

@ -0,0 +1,35 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait ResetTimerReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: ResetTimerReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received resetTimerReqMsg {}", ResetTimerReqMsg)
def broadcastEvent(): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(ResetTimerRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
ResetTimerRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = ResetTimerRespMsgBody(msg.header.userId)
val event = ResetTimerRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to reset timer"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
broadcastEvent()
}
}
}

View File

@ -0,0 +1,38 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait SetTimerReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: SetTimerReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received setTimerReqMsg {}", SetTimerReqMsg)
def broadcastEvent(
time: Int
): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(SetTimerRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
SetTimerRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = SetTimerRespMsgBody(msg.header.userId, time)
val event = SetTimerRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to set timer"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
TimerModel.setTime(liveMeeting.timerModel, msg.body.time)
broadcastEvent(msg.body.time)
}
}
}

View File

@ -0,0 +1,38 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait SetTrackReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: SetTrackReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received setTrackReqMsg {}", SetTrackReqMsg)
def broadcastEvent(
track: String
): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(SetTrackRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
SetTrackRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = SetTrackRespMsgBody(msg.header.userId, track)
val event = SetTrackRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to set track"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
TimerModel.setTrack(liveMeeting.timerModel, msg.body.track)
broadcastEvent(msg.body.track)
}
}
}

View File

@ -0,0 +1,37 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait StartTimerReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: StartTimerReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received startTimerReqMsg {}", StartTimerReqMsg)
def broadcastEvent(): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(StartTimerRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
StartTimerRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = StartTimerRespMsgBody(msg.header.userId)
val event = StartTimerRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to start timer"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
TimerModel.setStartedAt(liveMeeting.timerModel, System.currentTimeMillis())
TimerModel.setRunning(liveMeeting.timerModel, true)
broadcastEvent()
}
}
}

View File

@ -0,0 +1,40 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait StopTimerReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: StopTimerReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received stopTimerReqMsg {}", StopTimerReqMsg)
def broadcastEvent(
accumulated: Int
): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(StopTimerRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
StopTimerRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = StopTimerRespMsgBody(msg.header.userId, accumulated)
val event = StopTimerRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
msg.header.userId != "nodeJSapp") {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to stop timer"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
TimerModel.setAccumulated(liveMeeting.timerModel, msg.body.accumulated)
TimerModel.setRunning(liveMeeting.timerModel, false)
broadcastEvent(msg.body.accumulated)
}
}
}

View File

@ -0,0 +1,42 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait SwitchTimerReqMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: SwitchTimerReqMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received switchTimerReqMsg {}", SwitchTimerReqMsg)
def broadcastEvent(
stopwatch: Boolean
): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(SwitchTimerRespMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
SwitchTimerRespMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = SwitchTimerRespMsgBody(msg.header.userId, stopwatch)
val event = SwitchTimerRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) &&
permissionFailed(PermissionCheck.GUEST_LEVEL, PermissionCheck.PRESENTER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "You need to be the presenter or moderator to switch timer"
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
if (TimerModel.getStopwatch(liveMeeting.timerModel) != msg.body.stopwatch) {
TimerModel.setStopwatch(liveMeeting.timerModel, msg.body.stopwatch)
broadcastEvent(msg.body.stopwatch)
} else {
log.debug("Timer is already in this stopwatch mode");
}
}
}
}

View File

@ -0,0 +1,19 @@
package org.bigbluebutton.core.apps.timer
import akka.actor.ActorContext
import akka.event.Logging
class TimerApp2x(implicit val context: ActorContext)
extends CreateTimerPubMsgHdlr
with ActivateTimerReqMsgHdlr
with DeactivateTimerReqMsgHdlr
with StartTimerReqMsgHdlr
with StopTimerReqMsgHdlr
with SwitchTimerReqMsgHdlr
with SetTimerReqMsgHdlr
with ResetTimerReqMsgHdlr
with SetTrackReqMsgHdlr
with TimerEndedPubMsgHdlr {
val log = Logging(context.system, getClass)
}

View File

@ -0,0 +1,29 @@
package org.bigbluebutton.core.apps.timer
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core.apps.{ TimerModel, PermissionCheck, RightsManagementTrait }
trait TimerEndedPubMsgHdlr extends RightsManagementTrait {
this: TimerApp2x =>
def handle(msg: TimerEndedPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
log.debug("Received timerEndedPubMsg {}", TimerEndedPubMsg)
def broadcastEvent(): Unit = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(TimerEndedEvtMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(
TimerEndedEvtMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = TimerEndedEvtMsgBody()
val event = TimerEndedEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}
TimerModel.setEndedAt(liveMeeting.timerModel, System.currentTimeMillis())
broadcastEvent()
}
}

View File

@ -31,7 +31,8 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait {
hideUserList = msg.body.hideUserList,
lockOnJoin = msg.body.lockOnJoin,
lockOnJoinConfigurable = msg.body.lockOnJoinConfigurable,
hideViewersCursor = msg.body.hideViewersCursor
hideViewersCursor = msg.body.hideViewersCursor,
hideViewersAnnotation = msg.body.hideViewersAnnotation
)
if (!MeetingStatus2x.permissionsEqual(liveMeeting.status, settings) || !MeetingStatus2x.permisionsInitialized(liveMeeting.status)) {
@ -224,6 +225,7 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait {
lockOnJoin = settings.lockOnJoin,
lockOnJoinConfigurable = settings.lockOnJoinConfigurable,
hideViewersCursor = settings.hideViewersCursor,
hideViewersAnnotation = settings.hideViewersAnnotation,
msg.body.setBy
)
val header = BbbClientMsgHeader(

View File

@ -0,0 +1,50 @@
package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.apps.RightsManagementTrait
import org.bigbluebutton.core.models.{ UserState, Users2x }
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core2.message.senders.MsgBuilder
trait ChangeUserAwayReqMsgHdlr extends RightsManagementTrait {
this: UsersApp =>
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleChangeUserAwayReqMsg(msg: ChangeUserAwayReqMsg): Unit = {
log.info("handleChangeUserAwayReqMsg: away={} userId={}", msg.body.away, msg.body.userId)
def broadcast(user: UserState, away: Boolean): Unit = {
val routingChange = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, user.intId
)
val envelopeChange = BbbCoreEnvelope(UserAwayChangedEvtMsg.NAME, routingChange)
val headerChange = BbbClientMsgHeader(UserAwayChangedEvtMsg.NAME, liveMeeting.props.meetingProp.intId,
user.intId)
val bodyChange = UserAwayChangedEvtMsgBody(user.intId, away)
val eventChange = UserAwayChangedEvtMsg(headerChange, bodyChange)
val msgEventChange = BbbCommonEnvCoreMsg(envelopeChange, eventChange)
outGW.send(msgEventChange)
}
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
newUserState <- Users2x.setUserAway(liveMeeting.users2x, user.intId, msg.body.away)
} yield {
if (msg.body.away && user.emoji == "") {
Users2x.setEmojiStatus(liveMeeting.users2x, msg.body.userId, "away")
outGW.send(MsgBuilder.buildUserEmojiChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.userId, "away"))
}
if (msg.body.away == false && user.emoji == "away") {
Users2x.setEmojiStatus(liveMeeting.users2x, msg.body.userId, "none")
outGW.send(MsgBuilder.buildUserEmojiChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.userId, "none"))
}
broadcast(newUserState, msg.body.away)
}
}
}

View File

@ -4,6 +4,7 @@ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.models.Users2x
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
import org.bigbluebutton.core2.message.senders.MsgBuilder
trait ChangeUserEmojiCmdMsgHdlr extends RightsManagementTrait {
this: BaseMeetingActor =>
@ -37,7 +38,18 @@ trait ChangeUserEmojiCmdMsgHdlr extends RightsManagementTrait {
for {
uvo <- Users2x.setEmojiStatus(liveMeeting.users2x, msg.body.userId, msg.body.emoji)
} yield {
sendUserEmojiChangedEvtMsg(outGW, liveMeeting.props.meetingProp.intId, msg.body.userId, msg.body.emoji)
outGW.send(MsgBuilder.buildUserEmojiChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.userId, msg.body.emoji))
if (initialEmojiState == "raiseHand" || nextEmojiState == "raiseHand") {
Users2x.setUserRaiseHand(liveMeeting.users2x, msg.body.userId, msg.body.emoji == "raiseHand")
outGW.send(MsgBuilder.buildUserRaiseHandChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.userId, msg.body.emoji == "raiseHand"))
}
if (initialEmojiState == "away" || nextEmojiState == "away") {
Users2x.setUserAway(liveMeeting.users2x, msg.body.userId, msg.body.emoji == "away")
outGW.send(MsgBuilder.buildUserAwayChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.userId, msg.body.emoji == "away"))
}
}
} else {
val meetingId = liveMeeting.props.meetingProp.intId
@ -46,13 +58,4 @@ trait ChangeUserEmojiCmdMsgHdlr extends RightsManagementTrait {
}
}
def sendUserEmojiChangedEvtMsg(outGW: OutMsgRouter, meetingId: String, userId: String, emoji: String): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
val envelope = BbbCoreEnvelope(UserEmojiChangedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserEmojiChangedEvtMsg.NAME, meetingId, userId)
val body = UserEmojiChangedEvtMsgBody(userId, emoji)
val event = UserEmojiChangedEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
outGW.send(msgEvent)
}
}

View File

@ -0,0 +1,74 @@
package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
import org.bigbluebutton.core.models.{ UserState, Users2x }
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core2.message.senders.MsgBuilder
trait ChangeUserRaiseHandReqMsgHdlr extends RightsManagementTrait {
this: UsersApp =>
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleChangeUserRaiseHandReqMsg(msg: ChangeUserRaiseHandReqMsg): Unit = {
log.info("handleChangeUserRaiseHandReqMsg: raiseHand={} userId={}", msg.body.raiseHand, msg.body.userId)
def broadcast(user: UserState, raiseHand: Boolean): Unit = {
val routingChange = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, user.intId
)
val envelopeChange = BbbCoreEnvelope(UserRaiseHandChangedEvtMsg.NAME, routingChange)
val headerChange = BbbClientMsgHeader(UserRaiseHandChangedEvtMsg.NAME, liveMeeting.props.meetingProp.intId,
user.intId)
val bodyChange = UserRaiseHandChangedEvtMsgBody(user.intId, raiseHand)
val eventChange = UserRaiseHandChangedEvtMsg(headerChange, bodyChange)
val msgEventChange = BbbCommonEnvCoreMsg(envelopeChange, eventChange)
outGW.send(msgEventChange)
}
val isUserSettingOwnProps = (msg.header.userId == msg.body.userId)
val isUserModerator = !permissionFailed(
PermissionCheck.MOD_LEVEL,
PermissionCheck.VIEWER_LEVEL,
liveMeeting.users2x,
msg.header.userId
)
val isUserPresenter = !permissionFailed(
PermissionCheck.VIEWER_LEVEL,
PermissionCheck.PRESENTER_LEVEL,
liveMeeting.users2x,
msg.header.userId
)
if (isUserSettingOwnProps || isUserModerator || isUserPresenter) {
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
newUserState <- Users2x.setUserRaiseHand(liveMeeting.users2x, user.intId, msg.body.raiseHand)
} yield {
if (msg.body.raiseHand && user.emoji == "") {
Users2x.setEmojiStatus(liveMeeting.users2x, msg.body.userId, "raiseHand")
outGW.send(MsgBuilder.buildUserEmojiChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.userId, "raiseHand"))
}
if (msg.body.raiseHand == false && user.emoji == "raiseHand") {
Users2x.setEmojiStatus(liveMeeting.users2x, msg.body.userId, "none")
outGW.send(MsgBuilder.buildUserEmojiChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.userId, "none"))
}
broadcast(newUserState, msg.body.raiseHand)
}
} else {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to change user raiseHand prop."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
}
}
}

View File

@ -0,0 +1,41 @@
package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.apps.RightsManagementTrait
import org.bigbluebutton.core.models.{ UserState, Users2x }
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
trait ChangeUserReactionEmojiReqMsgHdlr extends RightsManagementTrait {
this: UsersApp =>
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleChangeUserReactionEmojiReqMsg(msg: ChangeUserReactionEmojiReqMsg): Unit = {
log.info("handleChangeUserReactionEmojiReqMsg: reactionEmoji={} userId={}", msg.body.reactionEmoji, msg.body.userId)
def broadcast(user: UserState, reactionEmoji: String): Unit = {
val routingChange = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, user.intId
)
val envelopeChange = BbbCoreEnvelope(UserReactionEmojiChangedEvtMsg.NAME, routingChange)
val headerChange = BbbClientMsgHeader(UserReactionEmojiChangedEvtMsg.NAME, liveMeeting.props.meetingProp.intId,
user.intId)
val bodyChange = UserReactionEmojiChangedEvtMsgBody(user.intId, reactionEmoji)
val eventChange = UserReactionEmojiChangedEvtMsg(headerChange, bodyChange)
val msgEventChange = BbbCommonEnvCoreMsg(envelopeChange, eventChange)
outGW.send(msgEventChange)
}
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
newUserState <- Users2x.setReactionEmoji(liveMeeting.users2x, user.intId, msg.body.reactionEmoji)
} yield {
if (user.reactionEmoji != msg.body.reactionEmoji) {
broadcast(newUserState, msg.body.reactionEmoji)
}
}
}
}

View File

@ -0,0 +1,47 @@
package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.models.Users2x
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
trait ClearAllUsersEmojiCmdMsgHdlr extends RightsManagementTrait {
this: BaseMeetingActor =>
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleClearAllUsersEmojiCmdMsg(msg: ClearAllUsersEmojiCmdMsg) {
val isUserModerator = !permissionFailed(
PermissionCheck.MOD_LEVEL,
PermissionCheck.VIEWER_LEVEL,
liveMeeting.users2x,
msg.header.userId
)
if (isUserModerator) {
for {
user <- Users2x.findAll(liveMeeting.users2x)
} yield {
Users2x.setEmojiStatus(liveMeeting.users2x, user.intId, "none")
Users2x.setUserAway(liveMeeting.users2x, user.intId, false)
Users2x.setUserRaiseHand(liveMeeting.users2x, user.intId, false)
}
sendClearedAllUsersEmojiEvtMsg(outGW, liveMeeting.props.meetingProp.intId, msg.header.userId)
} else {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to clear users reactions."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
}
}
def sendClearedAllUsersEmojiEvtMsg(outGW: OutMsgRouter, meetingId: String, userId: String): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
val envelope = BbbCoreEnvelope(ClearedAllUsersEmojiEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(ClearedAllUsersEmojiEvtMsg.NAME, meetingId, userId)
val body = ClearedAllUsersEmojiEvtMsgBody()
val event = ClearedAllUsersEmojiEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
outGW.send(msgEvent)
}
}

View File

@ -24,7 +24,8 @@ trait GetLockSettingsReqMsgHdlr {
hideUserList = settings.hideUserList,
lockOnJoin = settings.lockOnJoin,
lockOnJoinConfigurable = settings.lockOnJoinConfigurable,
hideViewersCursor = settings.hideViewersCursor
hideViewersCursor = settings.hideViewersCursor,
hideViewersAnnotation = settings.hideViewersAnnotation
)
val header = BbbClientMsgHeader(GetLockSettingsRespMsg.NAME, meetingId, requestedBy)
val event = GetLockSettingsRespMsg(header, body)

View File

@ -0,0 +1,41 @@
package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.models.{ UserState, Users2x }
import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
import org.bigbluebutton.core.domain.MeetingState2x
trait SetUserSpeechLocaleMsgHdlr extends RightsManagementTrait {
this: UsersApp =>
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleSetUserSpeechLocaleReqMsg(msg: SetUserSpeechLocaleReqMsg): Unit = {
log.info("handleSetUserSpeechLocaleReqMsg: locale={} provider={} userId={}", msg.body.locale, msg.body.provider, msg.header.userId)
def broadcastUserSpeechLocaleChanged(user: UserState, locale: String, provider: String): Unit = {
val routingChange = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, user.intId
)
val envelopeChange = BbbCoreEnvelope(UserSpeechLocaleChangedEvtMsg.NAME, routingChange)
val headerChange = BbbClientMsgHeader(UserSpeechLocaleChangedEvtMsg.NAME, liveMeeting.props.meetingProp.intId, user.intId)
val bodyChange = UserSpeechLocaleChangedEvtMsgBody(locale, provider)
val eventChange = UserSpeechLocaleChangedEvtMsg(headerChange, bodyChange)
val msgEventChange = BbbCommonEnvCoreMsg(envelopeChange, eventChange)
outGW.send(msgEventChange)
}
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.header.userId)
} yield {
var changeLocale: Option[UserState] = None;
changeLocale = Users2x.setUserSpeechLocale(liveMeeting.users2x, msg.header.userId, msg.body.locale)
broadcastUserSpeechLocaleChanged(user, msg.body.locale, msg.body.provider)
}
}
}

View File

@ -0,0 +1,19 @@
package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.models.Users2x
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core.apps.{ RightsManagementTrait }
trait UserReactionTimeExpiredCmdMsgHdlr extends RightsManagementTrait {
this: BaseMeetingActor =>
val liveMeeting: LiveMeeting
def handleUserReactionTimeExpiredCmdMsg(msg: UserReactionTimeExpiredCmdMsg) {
val isNodeUser = msg.header.userId.equals("nodeJSapp")
if (isNodeUser) {
Users2x.setReactionEmoji(liveMeeting.users2x, msg.body.userId, "none")
}
}
}

View File

@ -149,6 +149,7 @@ class UsersApp(
with GetUsersMeetingReqMsgHdlr
with RegisterUserReqMsgHdlr
with ChangeUserRoleCmdMsgHdlr
with SetUserSpeechLocaleMsgHdlr
with SyncGetUsersMeetingRespMsgHdlr
with LogoutAndEndMeetingCmdMsgHdlr
with SetRecordingStatusCmdMsgHdlr
@ -159,6 +160,9 @@ class UsersApp(
with AssignPresenterReqMsgHdlr
with ChangeUserPinStateReqMsgHdlr
with ChangeUserMobileFlagReqMsgHdlr
with ChangeUserReactionEmojiReqMsgHdlr
with ChangeUserRaiseHandReqMsgHdlr
with ChangeUserAwayReqMsgHdlr
with EjectUserFromMeetingCmdMsgHdlr
with EjectUserFromMeetingSysMsgHdlr
with MuteUserCmdMsgHdlr {

View File

@ -7,7 +7,9 @@ trait UsersApp2x
with LockUserInMeetingCmdMsgHdlr
with LockUsersInMeetingCmdMsgHdlr
with GetLockSettingsReqMsgHdlr
with ChangeUserEmojiCmdMsgHdlr {
with ChangeUserEmojiCmdMsgHdlr
with ClearAllUsersEmojiCmdMsgHdlr
with UserReactionTimeExpiredCmdMsgHdlr {
this: MeetingActor =>

View File

@ -49,6 +49,9 @@ trait UserJoinedVoiceConfEvtMsgHdlr extends SystemConfiguration {
authed = true,
guestStatus = GuestStatus.WAIT,
emoji = "none",
reactionEmoji = "none",
raiseHand = false,
away = false,
pin = false,
mobile = false,
presenter = false,

View File

@ -18,7 +18,7 @@ case class BreakoutRoom2x(
captureNotes: Boolean,
captureSlides: Boolean,
captureNotesFilename: String,
captureSlidesFilename: String
captureSlidesFilename: String,
) {
}

View File

@ -62,6 +62,7 @@ case class PresentationInPod(
pages: scala.collection.immutable.Map[String, PresentationPage],
downloadable: Boolean,
removable: Boolean,
filenameConverted: String = "",
)
object PresentationPod {

View File

@ -178,10 +178,42 @@ object Users2x {
u <- findWithIntId(users, intId)
} yield {
val newUser = u.modify(_.emoji).setTo(emoji)
users.save(newUser)
newUser
}
}
def setReactionEmoji(users: Users2x, intId: String, reactionEmoji: String): Option[UserState] = {
for {
u <- findWithIntId(users, intId)
} yield {
val newUser = u.modify(_.reactionEmoji).setTo(reactionEmoji)
.modify(_.reactionChangedOn).setTo(System.currentTimeMillis())
users.save(newUser)
newUser
}
}
def setUserRaiseHand(users: Users2x, intId: String, raiseHand: Boolean): Option[UserState] = {
for {
u <- findWithIntId(users, intId)
} yield {
val newUserState = u.modify(_.away).setTo(raiseHand)
users.save(newUserState)
newUserState
}
}
def setUserAway(users: Users2x, intId: String, away: Boolean): Option[UserState] = {
for {
u <- findWithIntId(users, intId)
} yield {
val newUserState = u.modify(_.away).setTo(away)
users.save(newUserState)
newUserState
}
}
def setUserLocked(users: Users2x, intId: String, locked: Boolean): Option[UserState] = {
for {
@ -203,6 +235,16 @@ object Users2x {
}
}
def setUserSpeechLocale(users: Users2x, intId: String, locale: String): Option[UserState] = {
for {
u <- findWithIntId(users, intId)
} yield {
val newUser = u.modify(_.speechLocale).setTo(locale)
users.save(newUser)
newUser
}
}
def hasPresenter(users: Users2x): Boolean = {
findPresenter(users) match {
case Some(p) => true
@ -364,6 +406,10 @@ case class UserState(
authed: Boolean,
guestStatus: String,
emoji: String,
reactionEmoji: String,
reactionChangedOn: Long = 0,
raiseHand: Boolean,
away: Boolean,
locked: Boolean,
presenter: Boolean,
avatar: String,
@ -373,7 +419,8 @@ case class UserState(
lastInactivityInspect: Long = 0,
clientType: String,
pickExempted: Boolean,
userLeftFlag: UserLeftFlag
userLeftFlag: UserLeftFlag,
speechLocale: String = ""
)
case class UserIdAndName(id: String, name: String)

View File

@ -111,6 +111,8 @@ class ReceivedJsonMsgHandlerActor(
routeGenericMsg[ChangeUserPinStateReqMsg](envelope, jsonNode)
case ChangeUserMobileFlagReqMsg.NAME =>
routeGenericMsg[ChangeUserMobileFlagReqMsg](envelope, jsonNode)
case SetUserSpeechLocaleReqMsg.NAME =>
routeGenericMsg[SetUserSpeechLocaleReqMsg](envelope, jsonNode)
case SelectRandomViewerReqMsg.NAME =>
routeGenericMsg[SelectRandomViewerReqMsg](envelope, jsonNode)
@ -250,8 +252,18 @@ class ReceivedJsonMsgHandlerActor(
case UserLeaveReqMsg.NAME =>
routeGenericMsg[UserLeaveReqMsg](envelope, jsonNode)
case ChangeUserRaiseHandReqMsg.NAME =>
routeGenericMsg[ChangeUserRaiseHandReqMsg](envelope, jsonNode)
case ChangeUserAwayReqMsg.NAME =>
routeGenericMsg[ChangeUserAwayReqMsg](envelope, jsonNode)
case ChangeUserEmojiCmdMsg.NAME =>
routeGenericMsg[ChangeUserEmojiCmdMsg](envelope, jsonNode)
case ChangeUserReactionEmojiReqMsg.NAME =>
routeGenericMsg[ChangeUserReactionEmojiReqMsg](envelope, jsonNode)
case UserReactionTimeExpiredCmdMsg.NAME =>
routeGenericMsg[UserReactionTimeExpiredCmdMsg](envelope, jsonNode)
case ClearAllUsersEmojiCmdMsg.NAME =>
routeGenericMsg[ClearAllUsersEmojiCmdMsg](envelope, jsonNode)
case ChangeUserRoleCmdMsg.NAME =>
routeGenericMsg[ChangeUserRoleCmdMsg](envelope, jsonNode)
@ -314,10 +326,10 @@ class ReceivedJsonMsgHandlerActor(
routeGenericMsg[PdfConversionInvalidErrorSysPubMsg](envelope, jsonNode)
case AssignPresenterReqMsg.NAME =>
routeGenericMsg[AssignPresenterReqMsg](envelope, jsonNode)
case MakePresentationWithAnnotationDownloadReqMsg.NAME =>
routeGenericMsg[MakePresentationWithAnnotationDownloadReqMsg](envelope, jsonNode)
case NewPresAnnFileAvailableMsg.NAME =>
routeGenericMsg[NewPresAnnFileAvailableMsg](envelope, jsonNode)
case MakePresentationDownloadReqMsg.NAME =>
routeGenericMsg[MakePresentationDownloadReqMsg](envelope, jsonNode)
case NewPresFileAvailableMsg.NAME =>
routeGenericMsg[NewPresFileAvailableMsg](envelope, jsonNode)
case PresAnnStatusMsg.NAME =>
routeGenericMsg[PresAnnStatusMsg](envelope, jsonNode)
@ -404,6 +416,29 @@ class ReceivedJsonMsgHandlerActor(
routeGenericMsg[UpdateExternalVideoPubMsg](envelope, jsonNode)
case StopExternalVideoPubMsg.NAME =>
routeGenericMsg[StopExternalVideoPubMsg](envelope, jsonNode)
// Timer
case CreateTimerPubMsg.NAME =>
routeGenericMsg[CreateTimerPubMsg](envelope, jsonNode)
case ActivateTimerReqMsg.NAME =>
routeGenericMsg[ActivateTimerReqMsg](envelope, jsonNode)
case DeactivateTimerReqMsg.NAME =>
routeGenericMsg[DeactivateTimerReqMsg](envelope, jsonNode)
case StartTimerReqMsg.NAME =>
routeGenericMsg[StartTimerReqMsg](envelope, jsonNode)
case StopTimerReqMsg.NAME =>
routeGenericMsg[StopTimerReqMsg](envelope, jsonNode)
case SwitchTimerReqMsg.NAME =>
routeGenericMsg[SwitchTimerReqMsg](envelope, jsonNode)
case SetTimerReqMsg.NAME =>
routeGenericMsg[SetTimerReqMsg](envelope, jsonNode)
case ResetTimerReqMsg.NAME =>
routeGenericMsg[ResetTimerReqMsg](envelope, jsonNode)
case SetTrackReqMsg.NAME =>
routeGenericMsg[SetTrackReqMsg](envelope, jsonNode)
case TimerEndedPubMsg.NAME =>
routeGenericMsg[TimerEndedPubMsg](envelope, jsonNode)
case _ =>
log.error("Cannot route envelope name " + envelope.name)
// do nothing

View File

@ -0,0 +1,24 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2019 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
trait AbstractTimerRecordEvent extends RecordEvent {
setModule("TIMER")
}

View File

@ -0,0 +1,59 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class ActivateTimerRecordEvent extends AbstractTimerRecordEvent {
import ActivateTimerRecordEvent._
setEvent("ActivateTimerEvent")
def setStopwatch(value: Boolean) {
eventMap.put(STOPWATCH, value.toString)
}
def setRunning(value: Boolean) {
eventMap.put(RUNNING, value.toString)
}
def setTime(value: Int) {
eventMap.put(TIME, value.toString)
}
def setAccumulated(value: Int) {
eventMap.put(ACCUMULATED, value.toString)
}
def setTimestamp(value: Int) {
eventMap.put(TIMESTAMP, value.toString)
}
def setTrack(value: String) {
eventMap.put(TRACK, value)
}
}
object ActivateTimerRecordEvent {
protected final val STOPWATCH = "stopwatch"
protected final val RUNNING = "running"
protected final val TIME = "time"
protected final val ACCUMULATED = "accumulated"
protected final val TIMESTAMP = "timestamp"
protected final val TRACK = "track"
}

View File

@ -0,0 +1,24 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class DeactivateTimerRecordEvent extends AbstractTimerRecordEvent {
setEvent("DeactivateTimerEvent")
}

View File

@ -0,0 +1,24 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class ResetTimerRecordEvent extends AbstractTimerRecordEvent {
setEvent("ResetTimerEvent")
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class SetTimerRecordEvent extends AbstractTimerRecordEvent {
import SetTimerRecordEvent._
setEvent("SetTimerEvent")
def setTime(value: Int) {
eventMap.put(TIME, value.toString)
}
}
object SetTimerRecordEvent {
protected final val TIME = "time"
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class SetTimerTrackRecordEvent extends AbstractTimerRecordEvent {
import SetTimerTrackRecordEvent._
setEvent("SetTimerTrackEvent")
def setTrack(value: String) {
eventMap.put(TRACK, value)
}
}
object SetTimerTrackRecordEvent {
protected final val TRACK = "track"
}

View File

@ -0,0 +1,24 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class StartTimerRecordEvent extends AbstractTimerRecordEvent {
setEvent("StartTimerEvent")
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class StopTimerRecordEvent extends AbstractTimerRecordEvent {
import StopTimerRecordEvent._
setEvent("StopTimerEvent")
def setAccumulated(value: Int) {
eventMap.put(ACCUMULATED, value.toString)
}
}
object StopTimerRecordEvent {
protected final val ACCUMULATED = "accumulated"
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class SwitchTimerRecordEvent extends AbstractTimerRecordEvent {
import SwitchTimerRecordEvent._
setEvent("SwitchTimerEvent")
def setStopwatch(value: Boolean) {
eventMap.put(STOPWATCH, value.toString)
}
}
object SwitchTimerRecordEvent {
protected final val STOPWATCH = "stopwatch"
}

View File

@ -0,0 +1,24 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.record.events
class TimerEndedRecordEvent extends AbstractTimerRecordEvent {
setEvent("TimerEndedEvent")
}

View File

@ -62,6 +62,9 @@ trait HandlerHelpers extends SystemConfiguration {
authed = regUser.authed,
guestStatus = regUser.guestStatus,
emoji = "none",
reactionEmoji = "none",
raiseHand = false,
away = false,
pin = false,
mobile = false,
presenter = false,

View File

@ -10,6 +10,7 @@ class LiveMeeting(
val status: MeetingStatus2x,
val screenshareModel: ScreenshareModel,
val audioCaptions: AudioCaptions,
val timerModel: TimerModel,
val chatModel: ChatModel,
val externalVideoModel: ExternalVideoModel,
val layouts: Layouts,

View File

@ -19,6 +19,7 @@ import org.bigbluebutton.core.apps.externalvideo.ExternalVideoApp2x
import org.bigbluebutton.core.apps.pads.PadsApp2x
import org.bigbluebutton.core.apps.screenshare.ScreenshareApp2x
import org.bigbluebutton.core.apps.audiocaptions.AudioCaptionsApp2x
import org.bigbluebutton.core.apps.timer.TimerApp2x
import org.bigbluebutton.core.apps.presentation.PresentationApp2x
import org.bigbluebutton.core.apps.users.UsersApp2x
import org.bigbluebutton.core.apps.webcam.WebcamApp2x
@ -136,6 +137,7 @@ class MeetingActor(
val pollApp = new PollApp2x
val webcamApp2x = new WebcamApp2x
val wbApp = new WhiteboardApp2x
val timerApp2x = new TimerApp2x
object ExpiryTrackerHelper extends MeetingExpiryTrackerHelper
@ -300,7 +302,8 @@ class MeetingActor(
hideUserList = lockSettingsProp.hideUserList,
lockOnJoin = lockSettingsProp.lockOnJoin,
lockOnJoinConfigurable = lockSettingsProp.lockOnJoinConfigurable,
hideViewersCursor = lockSettingsProp.hideViewersCursor
hideViewersCursor = lockSettingsProp.hideViewersCursor,
hideViewersAnnotation = lockSettingsProp.hideViewersAnnotation
)
MeetingStatus2x.initializePermissions(liveMeeting.status)
@ -384,11 +387,17 @@ class MeetingActor(
case m: RecordAndClearPreviousMarkersCmdMsg =>
state = usersApp.handleRecordAndClearPreviousMarkersCmdMsg(m, state)
updateUserLastActivity(m.body.setBy)
case m: GetRecordingStatusReqMsg => usersApp.handleGetRecordingStatusReqMsg(m)
case m: ChangeUserEmojiCmdMsg => handleChangeUserEmojiCmdMsg(m)
case m: SelectRandomViewerReqMsg => usersApp.handleSelectRandomViewerReqMsg(m)
case m: ChangeUserPinStateReqMsg => usersApp.handleChangeUserPinStateReqMsg(m)
case m: ChangeUserMobileFlagReqMsg => usersApp.handleChangeUserMobileFlagReqMsg(m)
case m: GetRecordingStatusReqMsg => usersApp.handleGetRecordingStatusReqMsg(m)
case m: ChangeUserEmojiCmdMsg => handleChangeUserEmojiCmdMsg(m)
case m: ChangeUserReactionEmojiReqMsg => usersApp.handleChangeUserReactionEmojiReqMsg(m)
case m: ChangeUserRaiseHandReqMsg => usersApp.handleChangeUserRaiseHandReqMsg(m)
case m: ChangeUserAwayReqMsg => usersApp.handleChangeUserAwayReqMsg(m)
case m: UserReactionTimeExpiredCmdMsg => handleUserReactionTimeExpiredCmdMsg(m)
case m: ClearAllUsersEmojiCmdMsg => handleClearAllUsersEmojiCmdMsg(m)
case m: SelectRandomViewerReqMsg => usersApp.handleSelectRandomViewerReqMsg(m)
case m: ChangeUserPinStateReqMsg => usersApp.handleChangeUserPinStateReqMsg(m)
case m: ChangeUserMobileFlagReqMsg => usersApp.handleChangeUserMobileFlagReqMsg(m)
case m: SetUserSpeechLocaleReqMsg => usersApp.handleSetUserSpeechLocaleReqMsg(m)
// Client requested to eject user
case m: EjectUserFromMeetingCmdMsg =>
@ -505,8 +514,8 @@ class MeetingActor(
// Presentation
case m: PreuploadedPresentationsSysPubMsg => presentationApp2x.handle(m, liveMeeting, msgBus)
case m: AssignPresenterReqMsg => state = handlePresenterChange(m, state)
case m: MakePresentationWithAnnotationDownloadReqMsg => presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: NewPresAnnFileAvailableMsg => presentationPodsApp.handle(m, liveMeeting, msgBus)
case m: MakePresentationDownloadReqMsg => presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: NewPresFileAvailableMsg => presentationPodsApp.handle(m, liveMeeting, msgBus)
case m: PresAnnStatusMsg => presentationPodsApp.handle(m, liveMeeting, msgBus)
case m: PadCapturePubMsg => presentationPodsApp.handle(m, liveMeeting, msgBus)
@ -596,6 +605,18 @@ class MeetingActor(
case m: UpdateExternalVideoPubMsg => externalVideoApp2x.handle(m, liveMeeting, msgBus)
case m: StopExternalVideoPubMsg => externalVideoApp2x.handle(m, liveMeeting, msgBus)
//Timer
case m: CreateTimerPubMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: ActivateTimerReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: DeactivateTimerReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: StartTimerReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: StopTimerReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: SwitchTimerReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: SetTimerReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: ResetTimerReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: SetTrackReqMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: TimerEndedPubMsg => timerApp2x.handle(m, liveMeeting, msgBus)
case m: ValidateConnAuthTokenSysMsg => handleValidateConnAuthTokenSysMsg(m)
case m: UserActivitySignCmdMsg => handleUserActivitySignCmdMsg(m)

View File

@ -33,13 +33,14 @@ class RunningMeeting(val props: DefaultProps, outGW: OutMessageGateway,
private val guestsWaiting = new GuestsWaiting
private val deskshareModel = new ScreenshareModel
private val audioCaptions = new AudioCaptions
private val timerModel = new TimerModel
// meetingModel.setGuestPolicy(props.usersProp.guestPolicy)
// We extract the meeting handlers into this class so it is
// easy to test.
private val liveMeeting = new LiveMeeting(props, meetingStatux2x, deskshareModel, audioCaptions, chatModel, externalVideoModel,
layouts, pads, registeredUsers, polls2x, wbModel, presModel, captionModel,
private val liveMeeting = new LiveMeeting(props, meetingStatux2x, deskshareModel, audioCaptions, timerModel,
chatModel, externalVideoModel, layouts, pads, registeredUsers, polls2x, wbModel, presModel, captionModel,
webcams, voiceUsers, users2x, guestsWaiting)
GuestsWaiting.setGuestPolicy(

View File

@ -117,8 +117,8 @@ class AnalyticsActor(val includeChat: Boolean) extends Actor with ActorLogging {
//case m: PresentationPageConvertedEventMsg => logMessage(msg)
// case m: StoreAnnotationsInRedisSysMsg => logMessage(msg)
// case m: StoreExportJobInRedisSysMsg => logMessage(msg)
case m: MakePresentationWithAnnotationDownloadReqMsg => logMessage(msg)
case m: NewPresAnnFileAvailableMsg => logMessage(msg)
case m: MakePresentationDownloadReqMsg => logMessage(msg)
case m: NewPresFileAvailableMsg => logMessage(msg)
case m: PresentationPageConversionStartedSysMsg => logMessage(msg)
case m: PresentationConversionEndedSysMsg => logMessage(msg)
case m: PresentationConversionRequestReceivedSysMsg => logMessage(msg)

View File

@ -13,7 +13,8 @@ case class Permissions(
hideUserList: Boolean = false,
lockOnJoin: Boolean = true,
lockOnJoinConfigurable: Boolean = false,
hideViewersCursor: Boolean = false
hideViewersCursor: Boolean = false,
hideViewersAnnotation: Boolean = false
)
case class MeetingExtensionProp(maxExtensions: Int = 2, numExtensions: Int = 0, extendByMinutes: Int = 20,

View File

@ -590,4 +590,32 @@ object MsgBuilder {
BbbCommonEnvCoreMsg(envelope, event)
}
def buildUserEmojiChangedEvtMsg(meetingId: String, userId: String, emoji: String) = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
val envelope = BbbCoreEnvelope(UserEmojiChangedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserEmojiChangedEvtMsg.NAME, meetingId, userId)
val body = UserEmojiChangedEvtMsgBody(userId, emoji)
val event = UserEmojiChangedEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
def buildUserAwayChangedEvtMsg(meetingId: String, userId: String, away: Boolean) = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
val envelope = BbbCoreEnvelope(UserAwayChangedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserAwayChangedEvtMsg.NAME, meetingId, userId)
val body = UserAwayChangedEvtMsgBody(userId, away)
val event = UserAwayChangedEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
def buildUserRaiseHandChangedEvtMsg(meetingId: String, userId: String, raiseHand: Boolean) = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
val envelope = BbbCoreEnvelope(UserRaiseHandChangedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserRaiseHandChangedEvtMsg.NAME, meetingId, userId)
val body = UserRaiseHandChangedEvtMsgBody(userId, raiseHand)
val event = UserRaiseHandChangedEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
}

View File

@ -12,6 +12,9 @@ object UserJoinedMeetingEvtMsgBuilder {
role = userState.role, guest = userState.guest, authed = userState.authed,
guestStatus = userState.guestStatus,
emoji = userState.emoji,
reactionEmoji = userState.reactionEmoji,
raiseHand = userState.raiseHand,
away = userState.away,
pin = userState.pin,
presenter = userState.presenter, locked = userState.locked, avatar = userState.avatar, color = userState.color,
clientType = userState.clientType)

View File

@ -68,7 +68,8 @@ trait FakeTestData {
def createFakeUser(liveMeeting: LiveMeeting, regUser: RegisteredUser): UserState = {
UserState(intId = regUser.id, extId = regUser.externId, name = regUser.name, role = regUser.role, pin = false,
mobile = false, guest = regUser.guest, authed = regUser.authed, guestStatus = regUser.guestStatus,
emoji = "none", locked = false, presenter = false, avatar = regUser.avatarURL, color = "#ff6242", clientType = "unknown",
emoji = "none", reactionEmoji = "none", raiseHand = false, away = false, locked = false, presenter = false,
avatar = regUser.avatarURL, color = "#ff6242", clientType = "unknown",
pickExempted = false, userLeftFlag = UserLeftFlag(false, 0))
}

View File

@ -39,6 +39,7 @@ case class User(
answers: Map[String,Vector[String]] = Map(),
talk: Talk = Talk(),
emojis: Vector[Emoji] = Vector(),
reactions: Vector[Emoji] = Vector(),
webcams: Vector[Webcam] = Vector(),
totalOfMessages: Long = 0,
)
@ -140,6 +141,9 @@ class LearningDashboardActor(
case m: UserLeaveReqMsg => handleUserLeaveReqMsg(m)
case m: UserLeftMeetingEvtMsg => handleUserLeftMeetingEvtMsg(m)
case m: UserEmojiChangedEvtMsg => handleUserEmojiChangedEvtMsg(m)
case m: UserAwayChangedEvtMsg => handleUserAwayChangedEvtMsg(m)
case m: UserRaiseHandChangedEvtMsg => handleUserRaiseHandChangedEvtMsg(m)
case m: UserReactionEmojiChangedEvtMsg => handleUserReactionEmojiChangedEvtMsg(m)
case m: UserRoleChangedEvtMsg => handleUserRoleChangedEvtMsg(m)
case m: UserBroadcastCamStartedEvtMsg => handleUserBroadcastCamStartedEvtMsg(m)
case m: UserBroadcastCamStoppedEvtMsg => handleUserBroadcastCamStoppedEvtMsg(m)
@ -350,7 +354,7 @@ class LearningDashboardActor(
meeting <- meetings.values.find(m => m.intId == msg.header.meetingId)
user <- findUserByIntId(meeting, msg.body.userId)
} yield {
if (msg.body.emoji != "none") {
if (msg.body.emoji != "none" && msg.body.emoji != "raiseHand" && msg.body.emoji != "away") {
val updatedUser = user.copy(emojis = user.emojis :+ Emoji(msg.body.emoji))
val updatedMeeting = meeting.copy(users = meeting.users + (updatedUser.userKey -> updatedUser))
@ -359,6 +363,48 @@ class LearningDashboardActor(
}
}
private def handleUserRaiseHandChangedEvtMsg(msg: UserRaiseHandChangedEvtMsg): Unit = {
for {
meeting <- meetings.values.find(m => m.intId == msg.header.meetingId)
user <- findUserByIntId(meeting, msg.body.userId)
} yield {
if (msg.body.raiseHand) {
val updatedUser = user.copy(emojis = user.emojis :+ Emoji("raiseHand"))
val updatedMeeting = meeting.copy(users = meeting.users + (updatedUser.userKey -> updatedUser))
meetings += (updatedMeeting.intId -> updatedMeeting)
}
}
}
private def handleUserAwayChangedEvtMsg(msg: UserAwayChangedEvtMsg): Unit = {
for {
meeting <- meetings.values.find(m => m.intId == msg.header.meetingId)
user <- findUserByIntId(meeting, msg.body.userId)
} yield {
if (msg.body.away) {
val updatedUser = user.copy(emojis = user.emojis :+ Emoji("away"))
val updatedMeeting = meeting.copy(users = meeting.users + (updatedUser.userKey -> updatedUser))
meetings += (updatedMeeting.intId -> updatedMeeting)
}
}
}
private def handleUserReactionEmojiChangedEvtMsg(msg: UserReactionEmojiChangedEvtMsg): Unit = {
for {
meeting <- meetings.values.find(m => m.intId == msg.header.meetingId)
user <- findUserByIntId(meeting, msg.body.userId)
} yield {
if (msg.body.reactionEmoji != "none") {
val updatedUser = user.copy(reactions = user.reactions :+ Emoji(msg.body.reactionEmoji))
val updatedMeeting = meeting.copy(users = meeting.users + (updatedUser.userKey -> updatedUser))
meetings += (updatedMeeting.intId -> updatedMeeting)
}
}
}
private def handleUserRoleChangedEvtMsg(msg: UserRoleChangedEvtMsg) {
for {
meeting <- meetings.values.find(m => m.intId == msg.header.meetingId)

View File

@ -135,6 +135,17 @@ class RedisRecorderActor(
case m: UpdateExternalVideoEvtMsg => handleUpdateExternalVideoEvtMsg(m)
case m: StopExternalVideoEvtMsg => handleStopExternalVideoEvtMsg(m)
// Timer
case m: ActivateTimerRespMsg => handleActivateTimerRespMsg(m)
case m: DeactivateTimerRespMsg => handleDeactivateTimerRespMsg(m)
case m: StartTimerRespMsg => handleStartTimerRespMsg(m)
case m: StopTimerRespMsg => handleStopTimerRespMsg(m)
case m: SwitchTimerRespMsg => handleSwitchTimerRespMsg(m)
case m: SetTimerRespMsg => handleSetTimerRespMsg(m)
case m: ResetTimerRespMsg => handleResetTimerRespMsg(m)
case m: TimerEndedEvtMsg => handleTimerEndedEvtMsg(m)
case m: SetTrackRespMsg => handleSetTrackRespMsg(m)
case _ => // message not to be recorded.
}
}
@ -545,6 +556,78 @@ class RedisRecorderActor(
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleActivateTimerRespMsg(msg: ActivateTimerRespMsg) {
val ev = new ActivateTimerRecordEvent()
ev.setMeetingId(msg.header.meetingId)
ev.setStopwatch(msg.body.stopwatch)
ev.setRunning(msg.body.running)
ev.setTime(msg.body.time)
ev.setAccumulated(msg.body.accumulated)
ev.setTrack(msg.body.track)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleDeactivateTimerRespMsg(msg: DeactivateTimerRespMsg) {
val ev = new DeactivateTimerRecordEvent()
ev.setMeetingId(msg.header.meetingId)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleStartTimerRespMsg(msg: StartTimerRespMsg) {
val ev = new StartTimerRecordEvent()
ev.setMeetingId(msg.header.meetingId)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleStopTimerRespMsg(msg: StopTimerRespMsg) {
val ev = new StopTimerRecordEvent()
ev.setMeetingId(msg.header.meetingId)
ev.setAccumulated(msg.body.accumulated)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleSwitchTimerRespMsg(msg: SwitchTimerRespMsg) {
val ev = new SwitchTimerRecordEvent()
ev.setMeetingId(msg.header.meetingId)
ev.setStopwatch(msg.body.stopwatch)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleSetTimerRespMsg(msg: SetTimerRespMsg) {
val ev = new SetTimerRecordEvent()
ev.setMeetingId(msg.header.meetingId)
ev.setTime(msg.body.time)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleResetTimerRespMsg(msg: ResetTimerRespMsg) {
val ev = new ResetTimerRecordEvent()
ev.setMeetingId(msg.header.meetingId)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleTimerEndedEvtMsg(msg: TimerEndedEvtMsg) {
val ev = new TimerEndedRecordEvent()
ev.setMeetingId(msg.header.meetingId)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleSetTrackRespMsg(msg: SetTrackRespMsg) {
val ev = new SetTimerTrackRecordEvent()
ev.setMeetingId(msg.header.meetingId)
ev.setTrack(msg.body.track)
record(msg.header.meetingId, ev.toMap.asJava)
}
private def handleRecordingStatusChangedEvtMsg(msg: RecordingStatusChangedEvtMsg) {
val ev = new RecordStatusRecordEvent()
ev.setMeetingId(msg.header.meetingId)

View File

@ -43,8 +43,9 @@ object TestDataGen {
def createUserFor(liveMeeting: LiveMeeting, regUser: RegisteredUser, presenter: Boolean): UserState = {
val u = UserState(intId = regUser.id, extId = regUser.externId, name = regUser.name, role = regUser.role,
guest = regUser.guest, authed = regUser.authed, guestStatus = regUser.guestStatus,
emoji = "none", locked = false, presenter = false, avatar = regUser.avatarURL, color = "#ff6242",
clientType = "unknown", userLeftFlag = UserLeftFlag(false, 0))
emoji = "none", reactionEmoji = "none", raiseHand = false, away = false, pin = false, mobile = false,
locked = false, presenter = false, avatar = regUser.avatarURL, color = "#ff6242",
clientType = "unknown", pickExempted = false, userLeftFlag = UserLeftFlag(false, 0))
Users2x.add(liveMeeting.users2x, u)
u
}

View File

@ -18,7 +18,7 @@ val compileSettings = Seq(
"-Xlint",
"-Ywarn-dead-code",
"-language:_",
"-target:11",
"-release:17",
"-encoding", "UTF-8"
),
javacOptions ++= List(
@ -77,4 +77,4 @@ daemonGroup in Linux := group
javaOptions in Universal ++= Seq("-J-Xms130m", "-J-Xmx256m", "-Dconfig.file=/etc/bigbluebutton/bbb-fsesl-akka.conf", "-Dlogback.configurationFile=conf/logback.xml")
debianPackageDependencies in Debian ++= Seq("java11-runtime-headless", "bash", "bbb-freeswitch-core")
debianPackageDependencies in Debian ++= Seq("java17-runtime-headless", "bash", "bbb-freeswitch-core")

View File

@ -12,7 +12,7 @@ val compileSettings = Seq(
"-Xlint",
"-Ywarn-dead-code",
"-language:_",
"-target:11",
"-release:17",
"-encoding", "UTF-8"
),
javacOptions ++= List(

View File

@ -63,7 +63,8 @@ case class LockSettingsProps(
hideUserList: Boolean,
lockOnJoin: Boolean,
lockOnJoinConfigurable: Boolean,
hideViewersCursor: Boolean
hideViewersCursor: Boolean,
hideViewersAnnotation: Boolean
)
case class SystemProps(

View File

@ -2,7 +2,7 @@ package org.bigbluebutton.common2.domain
case class PresentationVO(id: String, temporaryPresentationId: String, name: String, current: Boolean = false,
pages: Vector[PageVO], downloadable: Boolean, removable: Boolean,
isInitialPresentation: Boolean)
isInitialPresentation: Boolean, filenameConverted: String)
case class PageVO(id: String, num: Int, thumbUri: String = "",
txtUri: String, svgUri: String, current: Boolean = false, xOffset: Double = 0,

View File

@ -9,10 +9,11 @@ case class UpdateTranscriptPubMsgBody(
end: Int,
text: String,
transcript: String,
locale: String
locale: String,
result: Boolean,
)
// Out messages
object TranscriptUpdatedEvtMsg { val NAME = "TranscriptUpdatedEvtMsg" }
case class TranscriptUpdatedEvtMsg(header: BbbClientMsgHeader, body: TranscriptUpdatedEvtMsgBody) extends BbbCoreMsg
case class TranscriptUpdatedEvtMsgBody(transcriptId: String, transcript: String, locale: String)
case class TranscriptUpdatedEvtMsgBody(transcriptId: String, transcript: String, locale: String, result: Boolean)

View File

@ -12,7 +12,7 @@ case class BreakoutRoomJoinURLEvtMsgBody(parentId: String, breakoutId: String, e
// Outgoing messages
object BreakoutRoomsListEvtMsg { val NAME = "BreakoutRoomsListEvtMsg" }
case class BreakoutRoomsListEvtMsg(header: BbbClientMsgHeader, body: BreakoutRoomsListEvtMsgBody) extends BbbCoreMsg
case class BreakoutRoomsListEvtMsgBody(meetingId: String, rooms: Vector[BreakoutRoomInfo], roomsReady: Boolean)
case class BreakoutRoomsListEvtMsgBody(meetingId: String, rooms: Vector[BreakoutRoomInfo], roomsReady: Boolean, sendInviteToModerators: Boolean)
case class BreakoutRoomInfo(name: String, externalId: String, breakoutId: String, sequence: Int, shortName: String, isDefaultName: Boolean, freeJoin: Boolean, html5JoinUrls: Map[String, String], captureNotes: Boolean, captureSlides: Boolean)
object BreakoutRoomsListMsg { val NAME = "BreakoutRoomsListMsg" }
@ -70,7 +70,7 @@ case class BreakoutRoomDetail(
*/
object CreateBreakoutRoomsCmdMsg { val NAME = "CreateBreakoutRoomsCmdMsg" }
case class CreateBreakoutRoomsCmdMsg(header: BbbClientMsgHeader, body: CreateBreakoutRoomsCmdMsgBody) extends StandardMsg
case class CreateBreakoutRoomsCmdMsgBody(meetingId: String, durationInMinutes: Int, record: Boolean, captureNotes: Boolean, captureSlides: Boolean, rooms: Vector[BreakoutRoomMsgBody])
case class CreateBreakoutRoomsCmdMsgBody(meetingId: String, durationInMinutes: Int, record: Boolean, captureNotes: Boolean, captureSlides: Boolean, rooms: Vector[BreakoutRoomMsgBody], sendInviteToModerators: Boolean)
case class BreakoutRoomMsgBody(name: String, sequence: Int, shortName: String, captureNotesFilename: String, captureSlidesFilename: String, isDefaultName: Boolean, freeJoin: Boolean, users: Vector[String])
// Sent by user to request ending all the breakout rooms

View File

@ -10,13 +10,13 @@ object PreuploadedPresentationsSysPubMsg { val NAME = "PreuploadedPresentationsS
case class PreuploadedPresentationsSysPubMsg(header: BbbClientMsgHeader, body: PreuploadedPresentationsSysPubMsgBody) extends StandardMsg
case class PreuploadedPresentationsSysPubMsgBody(presentations: Vector[PresentationVO])
object MakePresentationWithAnnotationDownloadReqMsg { val NAME = "MakePresentationWithAnnotationDownloadReqMsg" }
case class MakePresentationWithAnnotationDownloadReqMsg(header: BbbClientMsgHeader, body: MakePresentationWithAnnotationDownloadReqMsgBody) extends StandardMsg
case class MakePresentationWithAnnotationDownloadReqMsgBody(presId: String, allPages: Boolean, pages: List[Int])
object MakePresentationDownloadReqMsg { val NAME = "MakePresentationDownloadReqMsg" }
case class MakePresentationDownloadReqMsg(header: BbbClientMsgHeader, body: MakePresentationDownloadReqMsgBody) extends StandardMsg
case class MakePresentationDownloadReqMsgBody(presId: String, allPages: Boolean, pages: List[Int], typeOfExport: String)
object NewPresAnnFileAvailableMsg { val NAME = "NewPresAnnFileAvailableMsg" }
case class NewPresAnnFileAvailableMsg(header: BbbClientMsgHeader, body: NewPresAnnFileAvailableMsgBody) extends StandardMsg
case class NewPresAnnFileAvailableMsgBody(fileURI: String, presId: String)
object NewPresFileAvailableMsg { val NAME = "NewPresFileAvailableMsg" }
case class NewPresFileAvailableMsg(header: BbbClientMsgHeader, body: NewPresFileAvailableMsgBody) extends StandardMsg
case class NewPresFileAvailableMsgBody(fileURI: String, presId: String, typeOfExport: String)
object PresAnnStatusMsg { val NAME = "PresAnnStatusMsg" }
case class PresAnnStatusMsg(header: BbbClientMsgHeader, body: PresAnnStatusMsgBody) extends StandardMsg
@ -37,9 +37,9 @@ object NewPresentationEvtMsg { val NAME = "NewPresentationEvtMsg" }
case class NewPresentationEvtMsg(header: BbbClientMsgHeader, body: NewPresentationEvtMsgBody) extends BbbCoreMsg
case class NewPresentationEvtMsgBody(presentation: PresentationVO)
object NewPresAnnFileAvailableEvtMsg { val NAME = "NewPresAnnFileAvailableEvtMsg" }
case class NewPresAnnFileAvailableEvtMsg(header: BbbClientMsgHeader, body: NewPresAnnFileAvailableEvtMsgBody) extends BbbCoreMsg
case class NewPresAnnFileAvailableEvtMsgBody(fileURI: String, presId: String)
object NewPresFileAvailableEvtMsg { val NAME = "NewPresFileAvailableEvtMsg" }
case class NewPresFileAvailableEvtMsg(header: BbbClientMsgHeader, body: NewPresFileAvailableEvtMsgBody) extends BbbCoreMsg
case class NewPresFileAvailableEvtMsgBody(fileURI: String, presId: String, typeOfExport: String)
object PresAnnStatusEvtMsg { val NAME = "PresAnnStatusEvtMsg" }
case class PresAnnStatusEvtMsg(header: BbbClientMsgHeader, body: PresAnnStatusEvtMsgBody) extends BbbCoreMsg

View File

@ -0,0 +1,79 @@
package org.bigbluebutton.common2.msgs
/* In Messages */
object CreateTimerPubMsg { val NAME = "CreateTimerPubMsg" }
case class CreateTimerPubMsg(header: BbbClientMsgHeader, body: CreateTimerPubMsgBody) extends StandardMsg
case class CreateTimerPubMsgBody(stopwatch: Boolean, running: Boolean, time: Int, accumulated: Int, timestamp: Int, track: String)
object ActivateTimerReqMsg { val NAME = "ActivateTimerReqMsg" }
case class ActivateTimerReqMsg(header: BbbClientMsgHeader, body: ActivateTimerReqMsgBody) extends StandardMsg
case class ActivateTimerReqMsgBody(stopwatch: Boolean, running: Boolean, time: Int, accumulated: Int, timestamp: Int, track: String)
object DeactivateTimerReqMsg { val NAME = "DeactivateTimerReqMsg" }
case class DeactivateTimerReqMsg(header: BbbClientMsgHeader, body: DeactivateTimerReqMsgBody) extends StandardMsg
case class DeactivateTimerReqMsgBody()
object StartTimerReqMsg { val NAME = "StartTimerReqMsg" }
case class StartTimerReqMsg(header: BbbClientMsgHeader, body: StartTimerReqMsgBody) extends StandardMsg
case class StartTimerReqMsgBody()
object StopTimerReqMsg { val NAME = "StopTimerReqMsg" }
case class StopTimerReqMsg(header: BbbClientMsgHeader, body: StopTimerReqMsgBody) extends StandardMsg
case class StopTimerReqMsgBody(accumulated: Int)
object SwitchTimerReqMsg { val NAME = "SwitchTimerReqMsg" }
case class SwitchTimerReqMsg(header: BbbClientMsgHeader, body: SwitchTimerReqMsgBody) extends StandardMsg
case class SwitchTimerReqMsgBody(stopwatch: Boolean)
object SetTimerReqMsg { val NAME = "SetTimerReqMsg" }
case class SetTimerReqMsg(header: BbbClientMsgHeader, body: SetTimerReqMsgBody) extends StandardMsg
case class SetTimerReqMsgBody(time: Int)
object ResetTimerReqMsg { val NAME = "ResetTimerReqMsg" }
case class ResetTimerReqMsg(header: BbbClientMsgHeader, body: ResetTimerReqMsgBody) extends StandardMsg
case class ResetTimerReqMsgBody()
object TimerEndedPubMsg { val NAME = "TimerEndedPubMsg" }
case class TimerEndedPubMsg(header: BbbClientMsgHeader, body: TimerEndedPubMsgBody) extends StandardMsg
case class TimerEndedPubMsgBody()
object SetTrackReqMsg { val NAME = "SetTrackReqMsg" }
case class SetTrackReqMsg(header: BbbClientMsgHeader, body: SetTrackReqMsgBody) extends StandardMsg
case class SetTrackReqMsgBody(track: String)
/* Out Messages */
object ActivateTimerRespMsg { val NAME = "ActivateTimerRespMsg" }
case class ActivateTimerRespMsg(header: BbbCoreHeaderWithMeetingId, body: ActivateTimerRespMsgBody) extends BbbCoreMsg
case class ActivateTimerRespMsgBody(userId: String, stopwatch: Boolean, running: Boolean, time: Int, accumulated: Int, track: String)
object DeactivateTimerRespMsg { val NAME = "DeactivateTimerRespMsg" }
case class DeactivateTimerRespMsg(header: BbbCoreHeaderWithMeetingId, body: DeactivateTimerRespMsgBody) extends BbbCoreMsg
case class DeactivateTimerRespMsgBody(userId: String)
object StartTimerRespMsg { val NAME = "StartTimerRespMsg" }
case class StartTimerRespMsg(header: BbbCoreHeaderWithMeetingId, body: StartTimerRespMsgBody) extends BbbCoreMsg
case class StartTimerRespMsgBody(userId: String)
object StopTimerRespMsg { val NAME = "StopTimerRespMsg" }
case class StopTimerRespMsg(header: BbbCoreHeaderWithMeetingId, body: StopTimerRespMsgBody) extends BbbCoreMsg
case class StopTimerRespMsgBody(userId: String, accumulated: Int)
object SwitchTimerRespMsg { val NAME = "SwitchTimerRespMsg" }
case class SwitchTimerRespMsg(header: BbbCoreHeaderWithMeetingId, body: SwitchTimerRespMsgBody) extends BbbCoreMsg
case class SwitchTimerRespMsgBody(userId: String, stopwatch: Boolean)
object SetTimerRespMsg { val NAME = "SetTimerRespMsg" }
case class SetTimerRespMsg(header: BbbCoreHeaderWithMeetingId, body: SetTimerRespMsgBody) extends BbbCoreMsg
case class SetTimerRespMsgBody(userId: String, time: Int)
object ResetTimerRespMsg { val NAME = "ResetTimerRespMsg" }
case class ResetTimerRespMsg(header: BbbCoreHeaderWithMeetingId, body: ResetTimerRespMsgBody) extends BbbCoreMsg
case class ResetTimerRespMsgBody(userId: String)
object TimerEndedEvtMsg { val NAME = "TimerEndedEvtMsg" }
case class TimerEndedEvtMsg(header: BbbCoreHeaderWithMeetingId, body: TimerEndedEvtMsgBody) extends BbbCoreMsg
case class TimerEndedEvtMsgBody()
object SetTrackRespMsg { val NAME = "SetTrackRespMsg" }
case class SetTrackRespMsg(header: BbbCoreHeaderWithMeetingId, body: SetTrackRespMsgBody) extends BbbCoreMsg
case class SetTrackRespMsgBody(userId: String, track: String)

View File

@ -89,20 +89,23 @@ case class UserJoinedMeetingEvtMsg(
body: UserJoinedMeetingEvtMsgBody
) extends BbbCoreMsg
case class UserJoinedMeetingEvtMsgBody(
intId: String,
extId: String,
name: String,
role: String,
guest: Boolean,
authed: Boolean,
guestStatus: String,
emoji: String,
pin: Boolean,
presenter: Boolean,
locked: Boolean,
avatar: String,
color: String,
clientType: String
intId: String,
extId: String,
name: String,
role: String,
guest: Boolean,
authed: Boolean,
guestStatus: String,
emoji: String,
reactionEmoji: String,
raiseHand: Boolean,
away: Boolean,
pin: Boolean,
presenter: Boolean,
locked: Boolean,
avatar: String,
color: String,
clientType: String
)
/**
@ -205,6 +208,69 @@ object UserEmojiChangedEvtMsg { val NAME = "UserEmojiChangedEvtMsg" }
case class UserEmojiChangedEvtMsg(header: BbbClientMsgHeader, body: UserEmojiChangedEvtMsgBody) extends BbbCoreMsg
case class UserEmojiChangedEvtMsgBody(userId: String, emoji: String)
/**
* Sent from client about a user changing RaiseHand.
*/
object ChangeUserRaiseHandReqMsg { val NAME = "ChangeUserRaiseHandReqMsg" }
case class ChangeUserRaiseHandReqMsg(header: BbbClientMsgHeader, body: ChangeUserRaiseHandReqMsgBody) extends StandardMsg
case class ChangeUserRaiseHandReqMsgBody(userId: String, raiseHand: Boolean)
/**
* Sent to all clients about a user changing RaiseHand.
*/
object UserRaiseHandChangedEvtMsg { val NAME = "UserRaiseHandChangedEvtMsg" }
case class UserRaiseHandChangedEvtMsg(header: BbbClientMsgHeader, body: UserRaiseHandChangedEvtMsgBody) extends BbbCoreMsg
case class UserRaiseHandChangedEvtMsgBody(userId: String, raiseHand: Boolean)
/**
* Sent from client about a user changing Away.
*/
object ChangeUserAwayReqMsg { val NAME = "ChangeUserAwayReqMsg" }
case class ChangeUserAwayReqMsg(header: BbbClientMsgHeader, body: ChangeUserAwayReqMsgBody) extends StandardMsg
case class ChangeUserAwayReqMsgBody(userId: String, away: Boolean)
/**
* Sent to all clients about a user changing Away.
*/
object UserAwayChangedEvtMsg { val NAME = "UserAwayChangedEvtMsg" }
case class UserAwayChangedEvtMsg(header: BbbClientMsgHeader, body: UserAwayChangedEvtMsgBody) extends BbbCoreMsg
case class UserAwayChangedEvtMsgBody(userId: String, away: Boolean)
/**
* Sent from client about a user changing ReactionEmoji.
*/
object ChangeUserReactionEmojiReqMsg { val NAME = "ChangeUserReactionEmojiReqMsg" }
case class ChangeUserReactionEmojiReqMsg(header: BbbClientMsgHeader, body: ChangeUserReactionEmojiReqMsgBody) extends StandardMsg
case class ChangeUserReactionEmojiReqMsgBody(userId: String, reactionEmoji: String)
/**
* Sent to all clients about a user changing ReactionEmoji.
*/
object UserReactionEmojiChangedEvtMsg { val NAME = "UserReactionEmojiChangedEvtMsg" }
case class UserReactionEmojiChangedEvtMsg(header: BbbClientMsgHeader, body: UserReactionEmojiChangedEvtMsgBody) extends BbbCoreMsg
case class UserReactionEmojiChangedEvtMsgBody(userId: String, reactionEmoji: String)
/**
* Sent from meteor about a user reaction's expiration.
*/
object UserReactionTimeExpiredCmdMsg { val NAME = "UserReactionTimeExpiredCmdMsg" }
case class UserReactionTimeExpiredCmdMsg(header: BbbClientMsgHeader, body: UserReactionTimeExpiredCmdMsgBody) extends StandardMsg
case class UserReactionTimeExpiredCmdMsgBody(userId: String)
/**
* Sent from client about a mod clearing all users' emoji.
*/
object ClearAllUsersEmojiCmdMsg { val NAME = "ClearAllUsersEmojiCmdMsg" }
case class ClearAllUsersEmojiCmdMsg(header: BbbClientMsgHeader, body: ClearAllUsersEmojiCmdMsgBody) extends StandardMsg
case class ClearAllUsersEmojiCmdMsgBody(userId: String)
/**
* Sent to all clients about clearing all users' emoji.
*/
object ClearedAllUsersEmojiEvtMsg { val NAME = "ClearedAllUsersEmojiEvtMsg" }
case class ClearedAllUsersEmojiEvtMsg(header: BbbClientMsgHeader, body: ClearedAllUsersEmojiEvtMsgBody) extends StandardMsg
case class ClearedAllUsersEmojiEvtMsgBody()
/**
* Sent from client about a user mobile flag.
*/
@ -282,7 +348,7 @@ case class ChangeLockSettingsInMeetingCmdMsg(
) extends StandardMsg
case class ChangeLockSettingsInMeetingCmdMsgBody(disableCam: Boolean, disableMic: Boolean, disablePrivChat: Boolean,
disablePubChat: Boolean, disableNotes: Boolean, hideUserList: Boolean, lockOnJoin: Boolean,
lockOnJoinConfigurable: Boolean, hideViewersCursor: Boolean, setBy: String)
lockOnJoinConfigurable: Boolean, hideViewersCursor: Boolean, hideViewersAnnotation: Boolean, setBy: String)
object LockSettingsInMeetingChangedEvtMsg { val NAME = "LockSettingsInMeetingChangedEvtMsg" }
case class LockSettingsInMeetingChangedEvtMsg(
@ -291,7 +357,7 @@ case class LockSettingsInMeetingChangedEvtMsg(
) extends BbbCoreMsg
case class LockSettingsInMeetingChangedEvtMsgBody(disableCam: Boolean, disableMic: Boolean, disablePrivChat: Boolean,
disablePubChat: Boolean, disableNotes: Boolean, hideUserList: Boolean, lockOnJoin: Boolean,
lockOnJoinConfigurable: Boolean, hideViewersCursor: Boolean, setBy: String)
lockOnJoinConfigurable: Boolean, hideViewersCursor: Boolean, hideViewersAnnotation: Boolean, setBy: String)
/**
* Sent by client to query the lock settings.
@ -307,7 +373,7 @@ object GetLockSettingsRespMsg { val NAME = "GetLockSettingsRespMsg" }
case class GetLockSettingsRespMsg(header: BbbClientMsgHeader, body: GetLockSettingsRespMsgBody) extends BbbCoreMsg
case class GetLockSettingsRespMsgBody(disableCam: Boolean, disableMic: Boolean, disablePrivChat: Boolean,
disablePubChat: Boolean, disableNotes: Boolean, hideUserList: Boolean, lockOnJoin: Boolean,
lockOnJoinConfigurable: Boolean, hideViewersCursor: Boolean)
lockOnJoinConfigurable: Boolean, hideViewersCursor: Boolean, hideViewersAnnotation: Boolean)
object LockSettingsNotInitializedRespMsg { val NAME = "LockSettingsNotInitializedRespMsg" }
case class LockSettingsNotInitializedRespMsg(header: BbbClientMsgHeader, body: LockSettingsNotInitializedRespMsgBody) extends BbbCoreMsg
@ -443,3 +509,11 @@ case class SelectRandomViewerReqMsgBody(requestedBy: String)
object SelectRandomViewerRespMsg { val NAME = "SelectRandomViewerRespMsg" }
case class SelectRandomViewerRespMsg(header: BbbClientMsgHeader, body: SelectRandomViewerRespMsgBody) extends StandardMsg
case class SelectRandomViewerRespMsgBody(requestedBy: String, userIds: Vector[String], choice: String)
object SetUserSpeechLocaleReqMsg { val NAME = "SetUserSpeechLocaleReqMsg" }
case class SetUserSpeechLocaleReqMsg(header: BbbClientMsgHeader, body: SetUserSpeechLocaleReqMsgBody) extends StandardMsg
case class SetUserSpeechLocaleReqMsgBody(locale: String, provider: String)
object UserSpeechLocaleChangedEvtMsg { val NAME = "UserSpeechLocaleChangedEvtMsg" }
case class UserSpeechLocaleChangedEvtMsg(header: BbbClientMsgHeader, body: UserSpeechLocaleChangedEvtMsgBody) extends BbbCoreMsg
case class UserSpeechLocaleChangedEvtMsgBody(locale: String, provider: String)

View File

@ -17,7 +17,7 @@ case class ScreenshareRtmpBroadcastStartedVoiceConfEvtMsg(
extends VoiceStandardMsg
case class ScreenshareRtmpBroadcastStartedVoiceConfEvtMsgBody(voiceConf: String, screenshareConf: String,
stream: String, vidWidth: Int, vidHeight: Int,
timestamp: String, hasAudio: Boolean)
timestamp: String, hasAudio: Boolean, contentType: String)
/**
* Sent to clients to notify them of an RTMP stream starting.
@ -30,7 +30,7 @@ case class ScreenshareRtmpBroadcastStartedEvtMsg(
extends BbbCoreMsg
case class ScreenshareRtmpBroadcastStartedEvtMsgBody(voiceConf: String, screenshareConf: String,
stream: String, vidWidth: Int, vidHeight: Int,
timestamp: String, hasAudio: Boolean)
timestamp: String, hasAudio: Boolean, contentType: String)
/**
* Sync screenshare state with bbb-html5
@ -48,7 +48,8 @@ case class SyncGetScreenshareInfoRespMsgBody(
vidWidth: Int,
vidHeight: Int,
timestamp: String,
hasAudio: Boolean
hasAudio: Boolean,
contentType: String
)
/**

View File

@ -11,7 +11,7 @@ val compileSettings = Seq(
"-Xlint",
"-Ywarn-dead-code",
"-language:_",
"-target:11",
"-release:17",
"-encoding", "UTF-8"
),
javacOptions ++= List(

View File

@ -95,6 +95,7 @@ public class ApiParams {
public static final String LOCK_SETTINGS_LOCK_ON_JOIN = "lockSettingsLockOnJoin";
public static final String LOCK_SETTINGS_LOCK_ON_JOIN_CONFIGURABLE = "lockSettingsLockOnJoinConfigurable";
public static final String LOCK_SETTINGS_HIDE_VIEWERS_CURSOR = "lockSettingsHideViewersCursor";
public static final String LOCK_SETTINGS_HIDE_VIEWERS_ANNOTATION = "lockSettingsHideViewersAnnotation";
// New param passed on create call to callback when meeting ends.
// This is a duplicate of the endCallbackUrl meta param as we want this

View File

@ -1,53 +0,0 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.api;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClientConfigService {
private static Logger log = LoggerFactory.getLogger(ClientConfigService.class);
private String configDir = "/var/bigbluebutton/configs";
private IClientConfigServiceHelper helper;
private Map<String, String> configs = new HashMap<>();
public void init() {
configs = helper.getPreBuiltConfigs(configDir);
log.info("ClientConfigService initialised");
}
public String getConfig(String id) {
return configs.get(id);
}
public void setConfigDir(String dir) {
configDir = dir;
}
public void setClientConfigServiceHelper(IClientConfigServiceHelper r) {
helper = r;
}
}

View File

@ -1,26 +0,0 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.api;
import java.util.Map;
public interface IClientConfigServiceHelper {
public Map<String, String> getPreBuiltConfigs(String dir);
}

View File

@ -48,7 +48,7 @@ public class LearningDashboardService {
File jsonFile = this.getJsonDataFile(meetingId,learningDashboardAccessToken);
FileOutputStream fileOutput = new FileOutputStream(jsonFile);
fileOutput.write(activityJson.getBytes());
fileOutput.write(activityJson.getBytes("UTF-8"));
fileOutput.close();

View File

@ -126,6 +126,7 @@ public class ParamsProcessorUtil {
private boolean defaultLockSettingsLockOnJoin;
private boolean defaultLockSettingsLockOnJoinConfigurable;
private boolean defaultLockSettingsHideViewersCursor;
private boolean defaultLockSettingsHideViewersAnnotation;
private Long maxPresentationFileUpload = 30000000L; // 30MB
@ -374,6 +375,12 @@ public class ParamsProcessorUtil {
lockSettingsHideViewersCursor = Boolean.parseBoolean(lockSettingsHideViewersCursorParam);
}
Boolean lockSettingsHideViewersAnnotation = defaultLockSettingsHideViewersAnnotation;
String lockSettingsHideViewersAnnotationParam = params.get(ApiParams.LOCK_SETTINGS_HIDE_VIEWERS_ANNOTATION);
if (!StringUtils.isEmpty(lockSettingsHideViewersAnnotationParam)) {
lockSettingsHideViewersAnnotation = Boolean.parseBoolean(lockSettingsHideViewersAnnotationParam);
}
return new LockSettingsParams(lockSettingsDisableCam,
lockSettingsDisableMic,
lockSettingsDisablePrivateChat,
@ -382,7 +389,8 @@ public class ParamsProcessorUtil {
lockSettingsHideUserList,
lockSettingsLockOnJoin,
lockSettingsLockOnJoinConfigurable,
lockSettingsHideViewersCursor);
lockSettingsHideViewersCursor,
lockSettingsHideViewersAnnotation);
}
private ArrayList<Group> processGroupsParams(Map<String, String> params) {
@ -1463,6 +1471,10 @@ public class ParamsProcessorUtil {
this.defaultLockSettingsHideViewersCursor = lockSettingsHideViewersCursor;
}
public void setLockSettingsHideViewersAnnotation(Boolean lockSettingsHideViewersAnnotation) {
this.defaultLockSettingsHideViewersAnnotation = lockSettingsHideViewersAnnotation;
}
public void setAllowDuplicateExtUserid(Boolean allow) {
this.defaultAllowDuplicateExtUserid = allow;
}

View File

@ -121,6 +121,8 @@ public final class Util {
File downloadMarker = Util.getPresFileDownloadMarker(presFileDir, presId);
if (downloadable && downloadMarker != null && ! downloadMarker.exists()) {
downloadMarker.createNewFile();
} else if (!downloadable && downloadMarker != null && downloadMarker.exists()) {
downloadMarker.delete();
}
}
}

View File

@ -10,6 +10,7 @@ public class LockSettingsParams {
public final Boolean lockOnJoin;
public final Boolean lockOnJoinConfigurable;
public final Boolean hideViewersCursor;
public final Boolean hideViewersAnnotation;
public LockSettingsParams(Boolean disableCam,
Boolean disableMic,
@ -19,7 +20,8 @@ public class LockSettingsParams {
Boolean hideUserList,
Boolean lockOnJoin,
Boolean lockOnJoinConfigurable,
Boolean hideViewersCursor) {
Boolean hideViewersCursor,
Boolean hideViewersAnnotation) {
this.disableCam = disableCam;
this.disableMic = disableMic;
this.disablePrivateChat = disablePrivateChat;
@ -29,5 +31,6 @@ public class LockSettingsParams {
this.lockOnJoin = lockOnJoin;
this.lockOnJoinConfigurable = lockOnJoinConfigurable;
this.hideViewersCursor = hideViewersCursor;
this.hideViewersAnnotation = hideViewersAnnotation;
}
}

View File

@ -21,6 +21,7 @@ package org.bigbluebutton.presentation;
import java.io.File;
import java.util.ArrayList;
import org.apache.commons.io.FilenameUtils;
public final class UploadedPresentation {
private final String podId;
@ -34,6 +35,7 @@ public final class UploadedPresentation {
private String fileType = "unknown";
private int numberOfPages = 0;
private String conversionStatus;
private String filenameConverted;
private final String baseUrl;
private boolean isDownloadable = false;
private boolean isRemovable = true;
@ -212,4 +214,27 @@ public final class UploadedPresentation {
public boolean getIsInitialPresentation() {
return isInitialPresentation;
}
public String getFilenameConverted() {
if (filenameConverted != null) {
return filenameConverted;
} else {
return "";
}
}
public void generateFilenameConverted(String newExtension) {
String nameWithoutExtension = FilenameUtils.removeExtension(name);
this.filenameConverted = nameWithoutExtension.concat("." + newExtension);
}
public void deleteOriginalFile() {
String pathToFileWithoutExtension = FilenameUtils.removeExtension(uploadedFile.getPath());
String newExtension = FilenameUtils.getExtension(uploadedFile.getPath());
String originalExtension = FilenameUtils.getExtension(name);
if (!originalExtension.equals("pdf") && newExtension.equals("pdf")) {
File originalFile = new File(pathToFileWithoutExtension + "." + originalExtension);
originalFile.delete();
}
}
}

View File

@ -3,10 +3,7 @@ package org.bigbluebutton.presentation.imp;
import com.google.gson.Gson;
import org.bigbluebutton.api.Util;
import org.bigbluebutton.presentation.*;
import org.bigbluebutton.presentation.messages.DocPageConversionStarted;
import org.bigbluebutton.presentation.messages.DocPageCountExceeded;
import org.bigbluebutton.presentation.messages.DocPageCountFailed;
import org.bigbluebutton.presentation.messages.PresentationConvertMessage;
import org.bigbluebutton.presentation.messages.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -76,6 +73,7 @@ public class PresentationFileProcessor {
private void processUploadedPresentation(UploadedPresentation pres) {
if (SupportedFileTypes.isPdfFile(pres.getFileType())) {
pres.generateFilenameConverted("pdf");
determineNumberOfPages(pres);
sendDocPageConversionStartedProgress(pres);
PresentationConvertMessage msg = new PresentationConvertMessage(pres);

View File

@ -108,12 +108,14 @@ public class SlidesGenerationProgressNotifier {
log.error("GeneratedSlidesInfoHelper was not set. Could not notify interested listeners.");
return;
}
// Completed conversion -> delete original file
pres.deleteOriginalFile();
DocPageCompletedProgress progress = new DocPageCompletedProgress(pres.getPodId(), pres.getMeetingId(),
pres.getId(), pres.getTemporaryPresentationId(), pres.getId(),
pres.getName(), "notUsedYet", "notUsedYet",
pres.isDownloadable(), pres.isRemovable(), ConversionMessageConstants.CONVERSION_COMPLETED_KEY,
pres.getNumberOfPages(), generateBasePresUrl(pres), pres.isCurrent(), pres.getIsInitialPresentation());
pres.getNumberOfPages(), generateBasePresUrl(pres), pres.isCurrent(), pres.getIsInitialPresentation(), pres.getFilenameConverted());
messagingService.sendDocConversionMsg(progress);
}

View File

@ -16,11 +16,14 @@ public class DocPageCompletedProgress implements IDocConversionMsg {
public final String presBaseUrl;
public final Boolean current;
public final Boolean isInitialPresentation;
public final String filenameConverted;
public DocPageCompletedProgress(String podId, String meetingId, String presId, String temporaryPresentationId, String presInstance,
String filename, String uploaderId, String authzToken,
Boolean downloadable, Boolean removable, String key,
Integer numPages, String presBaseUrl, Boolean current, Boolean isInitialPresentation) {
Integer numPages, String presBaseUrl, Boolean current,
Boolean isInitialPresentation, String filenameConverted) {
this.podId = podId;
this.meetingId = meetingId;
this.presId = presId;
@ -36,5 +39,6 @@ public class DocPageCompletedProgress implements IDocConversionMsg {
this.presBaseUrl = presBaseUrl;
this.current = current;
this.isInitialPresentation = isInitialPresentation;
this.filenameConverted = filenameConverted;
}
}

View File

@ -224,7 +224,8 @@ class BbbWebApiGWApp(
hideUserList = lockSettingsParams.hideUserList.booleanValue(),
lockOnJoin = lockSettingsParams.lockOnJoin.booleanValue(),
lockOnJoinConfigurable = lockSettingsParams.lockOnJoinConfigurable.booleanValue(),
hideViewersCursor = lockSettingsParams.hideViewersCursor.booleanValue()
hideViewersCursor = lockSettingsParams.hideViewersCursor.booleanValue(),
hideViewersAnnotation = lockSettingsParams.hideViewersAnnotation.booleanValue()
)
val systemProps = SystemProps(

View File

@ -148,8 +148,9 @@ object MsgBuilder {
val pages = generatePresentationPages(msg.presId, msg.numPages.intValue(), msg.presBaseUrl)
val presentation = PresentationVO(msg.presId, msg.temporaryPresentationId, msg.filename,
current = msg.current.booleanValue(), pages.values.toVector, msg.downloadable.booleanValue(), msg.removable.booleanValue(),
isInitialPresentation = msg.isInitialPresentation)
current = msg.current.booleanValue(), pages.values.toVector, msg.downloadable.booleanValue(),
msg.removable.booleanValue(),
isInitialPresentation = msg.isInitialPresentation, msg.filenameConverted)
val body = PresentationConversionCompletedSysPubMsgBody(podId = msg.podId, messageKey = msg.key,
code = msg.key, presentation)

View File

@ -86,6 +86,8 @@ class ReceivedJsonMsgHdlrActor(val msgFromAkkaAppsEventBus: MsgFromAkkaAppsEvent
route[UserBroadcastCamStoppedEvtMsg](envelope, jsonNode)
case UserRoleChangedEvtMsg.NAME =>
route[UserRoleChangedEvtMsg](envelope, jsonNode)
case UserSpeechLocaleChangedEvtMsg.NAME =>
route[UserSpeechLocaleChangedEvtMsg](envelope, jsonNode)
case CreateBreakoutRoomSysCmdMsg.NAME =>
route[CreateBreakoutRoomSysCmdMsg](envelope, jsonNode)
case PresentationUploadTokenSysPubMsg.NAME =>

View File

@ -1,13 +1,4 @@
let _ = require('lodash');
let fs = require('fs');
const settings = require('./settings');
const LOCAL_SETTINGS_FILE_PATH = '/etc/bigbluebutton/bbb-export-annotations.json';
const config = settings;
if (fs.existsSync(LOCAL_SETTINGS_FILE_PATH)) {
const local_config = JSON.parse(fs.readFileSync(LOCAL_SETTINGS_FILE_PATH));
_.mergeWith(config, local_config, (a, b) => (_.isArray(b) ? b : undefined));
}
module.exports = config;

View File

@ -25,10 +25,9 @@
"notifier": {
"pod_id": "DEFAULT_PRESENTATION_POD",
"is_downloadable": "false",
"msgName": "NewPresAnnFileAvailableMsg"
"msgName": "NewPresFileAvailableMsg"
},
"bbbWebAPI": "http://127.0.0.1:8090",
"bbbWebPublicAPI": "/bigbluebutton/",
"bbbPadsAPI": "http://127.0.0.1:9002",
"redis": {
"host": "127.0.0.1",

View File

@ -53,7 +53,7 @@ class PresAnnStatusMsg {
}
};
class NewPresAnnFileAvailableMsg {
class NewPresFileAvailableMsg {
constructor(exportJob, link) {
this.message = {
envelope: {
@ -72,6 +72,7 @@ class NewPresAnnFileAvailableMsg {
body: {
fileURI: link,
presId: exportJob.presId,
typeOfExport: "Annotated",
},
},
};
@ -84,5 +85,5 @@ class NewPresAnnFileAvailableMsg {
module.exports = {
PresAnnStatusMsg,
NewPresAnnFileAvailableMsg,
NewPresFileAvailableMsg,
};

View File

@ -10,7 +10,6 @@
"dependencies": {
"axios": "^0.26.0",
"form-data": "^4.0.0",
"lodash": "^4.17.21",
"perfect-freehand": "^1.0.16",
"probe-image-size": "^7.2.3",
"redis": "^4.0.3",
@ -22,8 +21,8 @@
"eslint-config-google": "^0.14.0"
},
"engines": {
"node": "^16.16.0",
"npm": "^8.5.0"
"node": ">=16",
"npm": ">=8.5"
}
},
"node_modules/@eslint/eslintrc": {
@ -925,11 +924,6 @@
"node": ">= 0.8.0"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@ -2054,11 +2048,6 @@
"type-check": "~0.4.0"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",

View File

@ -9,7 +9,6 @@
"dependencies": {
"axios": "^0.26.0",
"form-data": "^4.0.0",
"lodash": "^4.17.21",
"perfect-freehand": "^1.0.16",
"probe-image-size": "^7.2.3",
"redis": "^4.0.3",
@ -21,7 +20,7 @@
"eslint-config-google": "^0.14.0"
},
"engines": {
"node": "^16.16.0",
"npm": "^8.5.0"
"node": ">=16",
"npm": ">=8.5"
}
}

View File

@ -5,7 +5,7 @@ const FormData = require('form-data');
const redis = require('redis');
const axios = require('axios').default;
const path = require('path');
const {NewPresAnnFileAvailableMsg} = require('../lib/utils/message-builder');
const {NewPresFileAvailableMsg} = require('../lib/utils/message-builder');
const {workerData} = require('worker_threads');
const [jobType, jobId, filename] = [workerData.jobType, workerData.jobId, workerData.filename];
@ -28,11 +28,11 @@ async function notifyMeetingActor() {
await client.connect();
client.on('error', (err) => logger.info('Redis Client Error', err));
const link = config.bbbWebPublicAPI + path.join('presentation',
const link = path.join('presentation',
exportJob.parentMeetingId, exportJob.parentMeetingId,
exportJob.presId, 'pdf', jobId, filename);
const notification = new NewPresAnnFileAvailableMsg(exportJob, link);
const notification = new NewPresFileAvailableMsg(exportJob, link);
logger.info(`Annotated PDF available at ${link}`);
await client.publish(config.redis.channels.publish, notification.build());

Some files were not shown because too many files have changed in this diff Show More