Merge branch 'v2.7.x-release' into bbb-wake-locke
This commit is contained in:
commit
45215ed88f
9
.github/workflows/automated-tests.yml
vendored
9
.github/workflows/automated-tests.yml
vendored
@ -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
|
||||
|
1
.github/workflows/deploy-docs.yml
vendored
1
.github/workflows/deploy-docs.yml
vendored
@ -7,6 +7,7 @@ on:
|
||||
- 'develop'
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/**'
|
||||
|
||||
# Do not build the docs concurrently
|
||||
concurrency:
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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] = {
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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 = {
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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] = {
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
@ -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(
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -7,7 +7,9 @@ trait UsersApp2x
|
||||
with LockUserInMeetingCmdMsgHdlr
|
||||
with LockUsersInMeetingCmdMsgHdlr
|
||||
with GetLockSettingsReqMsgHdlr
|
||||
with ChangeUserEmojiCmdMsgHdlr {
|
||||
with ChangeUserEmojiCmdMsgHdlr
|
||||
with ClearAllUsersEmojiCmdMsgHdlr
|
||||
with UserReactionTimeExpiredCmdMsgHdlr {
|
||||
|
||||
this: MeetingActor =>
|
||||
|
||||
|
@ -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,
|
||||
|
@ -18,7 +18,7 @@ case class BreakoutRoom2x(
|
||||
captureNotes: Boolean,
|
||||
captureSlides: Boolean,
|
||||
captureNotesFilename: String,
|
||||
captureSlidesFilename: String
|
||||
captureSlidesFilename: String,
|
||||
) {
|
||||
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ case class PresentationInPod(
|
||||
pages: scala.collection.immutable.Map[String, PresentationPage],
|
||||
downloadable: Boolean,
|
||||
removable: Boolean,
|
||||
filenameConverted: String = "",
|
||||
)
|
||||
|
||||
object PresentationPod {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
@ -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"
|
||||
}
|
@ -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")
|
||||
}
|
@ -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")
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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")
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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")
|
||||
}
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -12,7 +12,7 @@ val compileSettings = Seq(
|
||||
"-Xlint",
|
||||
"-Ywarn-dead-code",
|
||||
"-language:_",
|
||||
"-target:11",
|
||||
"-release:17",
|
||||
"-encoding", "UTF-8"
|
||||
),
|
||||
javacOptions ++= List(
|
||||
|
@ -63,7 +63,8 @@ case class LockSettingsProps(
|
||||
hideUserList: Boolean,
|
||||
lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean,
|
||||
hideViewersCursor: Boolean
|
||||
hideViewersCursor: Boolean,
|
||||
hideViewersAnnotation: Boolean
|
||||
)
|
||||
|
||||
case class SystemProps(
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
@ -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)
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -11,7 +11,7 @@ val compileSettings = Seq(
|
||||
"-Xlint",
|
||||
"-Ywarn-dead-code",
|
||||
"-language:_",
|
||||
"-target:11",
|
||||
"-release:17",
|
||||
"-encoding", "UTF-8"
|
||||
),
|
||||
javacOptions ++= List(
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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 =>
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
};
|
||||
|
15
bbb-export-annotations/package-lock.json
generated
15
bbb-export-annotations/package-lock.json
generated
@ -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",
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user