Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(html5): Added captionLocale property and related logic #20272

Merged
merged 12 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,6 @@ class CaptionModel {
return None
}

def updateTranscriptOwner(name: String, locale: String, ownerId: String): Map[String, TranscriptVO] = {
var updatedTranscripts = new HashMap[String, TranscriptVO]

// clear owner from previous locale
if (ownerId.length > 0) {
findTranscriptByOwnerId(ownerId).foreach(t => {
val oldTranscript = t._2.copy(ownerId = "")

transcripts += t._1 -> oldTranscript
updatedTranscripts += t._1 -> oldTranscript
})
}
// change the owner if it does exist
if (transcripts contains name) {
val newTranscript = transcripts(name).copy(ownerId = ownerId)

transcripts += name -> newTranscript
updatedTranscripts += name -> newTranscript
} else { // create the locale if it doesn't exist
val addedTranscript = createTranscript(name, locale, ownerId)
updatedTranscripts += name -> addedTranscript
}

updatedTranscripts
}

def getHistory(): Map[String, TranscriptVO] = {
transcripts
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ class CaptionApp2x(implicit val context: ActorContext) extends RightsManagementT
liveMeeting.captionModel.getHistory()
}

def updateCaptionOwner(liveMeeting: LiveMeeting, name: String, locale: String, userId: String): Map[String, TranscriptVO] = {
liveMeeting.captionModel.updateTranscriptOwner(name, locale, userId)
}

def editCaptionHistory(liveMeeting: LiveMeeting, userId: String, startIndex: Integer, endIndex: Integer, name: String, text: String): Boolean = {
liveMeeting.captionModel.editHistory(userId, startIndex, endIndex, name, text)
}
Expand Down Expand Up @@ -75,46 +71,25 @@ class CaptionApp2x(implicit val context: ActorContext) extends RightsManagementT
broadcastEvent(msg, getCaptionHistory(liveMeeting))
}

def handle(msg: UpdateCaptionOwnerPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
def broadcastUpdateCaptionOwnerEvent(name: String, locale: String, newOwnerId: String): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, newOwnerId)
val envelope = BbbCoreEnvelope(UpdateCaptionOwnerEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UpdateCaptionOwnerEvtMsg.NAME, liveMeeting.props.meetingProp.intId, newOwnerId)
def handle(msg: AddCaptionLocalePubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
def broadcastAddCaptionLocaleEvent(locale: String, userId: String): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, userId)
val envelope = BbbCoreEnvelope(AddCaptionLocaleEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(AddCaptionLocaleEvtMsg.NAME, liveMeeting.props.meetingProp.intId, userId)

val body = UpdateCaptionOwnerEvtMsgBody(name, locale, newOwnerId)
val event = UpdateCaptionOwnerEvtMsg(header, body)
val body = AddCaptionLocaleEvtMsgBody(locale)
val event = AddCaptionLocaleEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
CaptionLocaleDAO.insertOrUpdateCaptionLocale(liveMeeting.props.meetingProp.intId, locale, CaptionTypes.TYPED, newOwnerId)
CaptionLocaleDAO.insertOrUpdateCaptionLocale(liveMeeting.props.meetingProp.intId, locale, CaptionTypes.TYPED, userId)
}

if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
val meetingId = liveMeeting.props.meetingProp.intId
val reason = "No permission to change caption owners."
val reason = "No permission to add caption locale."
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, bus.outGW, liveMeeting)
} else {
updateCaptionOwner(liveMeeting, msg.body.name, msg.body.locale, msg.body.ownerId).foreach(f => {
broadcastUpdateCaptionOwnerEvent(f._1, f._2.locale, f._2.ownerId)
})
}
}

def handleUserLeavingMsg(userId: String, liveMeeting: LiveMeeting, bus: MessageBus): Unit = {
def broadcastUpdateCaptionOwnerEvent(name: String, locale: String, newOwnerId: String): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, newOwnerId)
val envelope = BbbCoreEnvelope(UpdateCaptionOwnerEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UpdateCaptionOwnerEvtMsg.NAME, liveMeeting.props.meetingProp.intId, newOwnerId)

val body = UpdateCaptionOwnerEvtMsgBody(name, locale, newOwnerId)
val event = UpdateCaptionOwnerEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}

for {
transcriptInfo <- checkCaptionOwnerLogOut(liveMeeting, userId)
GuiLeme marked this conversation as resolved.
Show resolved Hide resolved
} yield {
broadcastUpdateCaptionOwnerEvent(transcriptInfo._1, transcriptInfo._2.locale, transcriptInfo._2.ownerId)
broadcastAddCaptionLocaleEvent(msg.body.locale, msg.header.userId)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
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 SetUserCaptionLocaleMsgHdlr extends RightsManagementTrait {
this: UsersApp =>

val liveMeeting: LiveMeeting
val outGW: OutMsgRouter

def handleSetUserCaptionLocaleReqMsg(msg: SetUserCaptionLocaleReqMsg): Unit = {
log.info("handleSetUserCaptionLocaleReqMsg: locale={} provider={} userId={}", msg.body.locale, msg.body.provider, msg.header.userId)

def broadcastUserCaptionLocaleChanged(user: UserState, locale: String, provider: String): Unit = {
val routingChange = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, user.intId
)
val envelopeChange = BbbCoreEnvelope(UserCaptionLocaleChangedEvtMsg.NAME, routingChange)
val headerChange = BbbClientMsgHeader(UserCaptionLocaleChangedEvtMsg.NAME, liveMeeting.props.meetingProp.intId, user.intId)

val bodyChange = UserCaptionLocaleChangedEvtMsgBody(locale, provider)
val eventChange = UserCaptionLocaleChangedEvtMsg(headerChange, bodyChange)
val msgEventChange = BbbCommonEnvCoreMsg(envelopeChange, eventChange)
outGW.send(msgEventChange)
}

for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.header.userId)
} yield {
Users2x.setUserCaptionLocale(liveMeeting.users2x, msg.header.userId, msg.body.locale)
broadcastUserCaptionLocaleChanged(user, msg.body.locale, msg.body.provider)
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class UsersApp(
with RegisterUserReqMsgHdlr
with ChangeUserRoleCmdMsgHdlr
with SetUserSpeechLocaleMsgHdlr
with SetUserCaptionLocaleMsgHdlr
with SetUserSpeechOptionsMsgHdlr
with SyncGetUsersMeetingRespMsgHdlr
with LogoutAndEndMeetingCmdMsgHdlr
Expand Down
GuiLeme marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ class CaptionLocaleTableDef(tag: Tag) extends Table[CaptionLocaleDbModel](tag, N
}

object CaptionLocaleDAO {
def insertOrUpdateCaptionLocale(meetingId: String, locale: String, captionType: String, ownerUserId: String) = {
def insertOrUpdateCaptionLocale(meetingId: String, locale: String, captionType: String, userId: String) = {
DatabaseConnection.db.run(
TableQuery[CaptionLocaleTableDef].insertOrUpdate(
CaptionLocaleDbModel(
meetingId = meetingId,
locale = locale,
captionType = captionType,
ownerUserId = ownerUserId,
ownerUserId = userId,
GuiLeme marked this conversation as resolved.
Show resolved Hide resolved
updatedAt = new java.sql.Timestamp(System.currentTimeMillis())
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package org.bigbluebutton.core.db

import org.bigbluebutton.core.models.{UserState}
import org.bigbluebutton.core.models.UserState
import slick.jdbc.PostgresProfile.api._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}


case class UserEjectColumnsDbModel(
ejected: Boolean = false,
ejectReason: Option[String],
ejectReasonCode: Option[String],
ejectedByModerator: Option[String],
)
case class UserStateDbModel(
meetingId: String,
userId: String,
Expand All @@ -19,22 +26,20 @@ case class UserStateDbModel(
clientType: String,
disconnected: Boolean = false,
expired: Boolean = false,
ejected: Boolean = false,
ejectReason: Option[String],
ejectReasonCode: Option[String],
ejectedByModerator: Option[String],
ejectColumns: UserEjectColumnsDbModel,
presenter: Boolean = false,
pinned: Boolean = false,
locked: Boolean = false,
speechLocale: String,
captionLocale: String,
inactivityWarningDisplay: Boolean = false,
inactivityWarningTimeoutSecs: Option[Long],
)

class UserStateDbTableDef(tag: Tag) extends Table[UserStateDbModel](tag, None, "user") {
override def * = (
meetingId, userId,emoji,away,raiseHand,guestStatus,guestStatusSetByModerator,guestLobbyMessage,mobile,clientType,disconnected,
expired,ejected,ejectReason,ejectReasonCode,ejectedByModerator,presenter,pinned,locked,speechLocale,
expired,ejectColumns,presenter,pinned,locked,speechLocale, captionLocale,
inactivityWarningDisplay, inactivityWarningTimeoutSecs) <> (UserStateDbModel.tupled, UserStateDbModel.unapply)
val meetingId = column[String]("meetingId", O.PrimaryKey)
val userId = column[String]("userId", O.PrimaryKey)
Expand All @@ -52,10 +57,12 @@ class UserStateDbTableDef(tag: Tag) extends Table[UserStateDbModel](tag, None, "
val ejectReason = column[Option[String]]("ejectReason")
val ejectReasonCode = column[Option[String]]("ejectReasonCode")
val ejectedByModerator = column[Option[String]]("ejectedByModerator")
val ejectColumns = (ejected, ejectReason, ejectReasonCode, ejectedByModerator) <> (UserEjectColumnsDbModel.tupled, UserEjectColumnsDbModel.unapply)
val presenter = column[Boolean]("presenter")
val pinned = column[Boolean]("pinned")
val locked = column[Boolean]("locked")
val speechLocale = column[String]("speechLocale")
val captionLocale = column[String]("captionLocale")
val inactivityWarningDisplay = column[Boolean]("inactivityWarningDisplay")
val inactivityWarningTimeoutSecs = column[Option[Long]]("inactivityWarningTimeoutSecs")
}
Expand All @@ -66,8 +73,20 @@ object UserStateDAO {
TableQuery[UserStateDbTableDef]
.filter(_.meetingId === userState.meetingId)
.filter(_.userId === userState.intId)
.map(u => (u.presenter, u.pinned, u.locked, u.speechLocale, u.emoji, u.away, u.raiseHand, u.mobile, u.clientType, u.disconnected))
.update((userState.presenter, userState.pin, userState.locked, userState.speechLocale, userState.emoji, userState.away, userState.raiseHand, userState.mobile, userState.clientType, userState.userLeftFlag.left))
.map(u => (u.presenter, u.pinned, u.locked, u.speechLocale, u.captionLocale, u.emoji, u.away, u.raiseHand, u.mobile, u.clientType, u.disconnected))
.update((
userState.presenter,
userState.pin,
userState.locked,
userState.speechLocale,
userState.captionLocale,
userState.emoji,
userState.away,
userState.raiseHand,
userState.mobile,
userState.clientType,
userState.userLeftFlag.left
))
).onComplete {
case Success(rowsAffected) => DatabaseConnection.logger.debug(s"$rowsAffected row(s) updated on user table!")
case Failure(e) => DatabaseConnection.logger.error(s"Error updating user: $e")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,17 @@ object Users2x {
}
}

def setUserCaptionLocale(users: Users2x, intId: String, locale: String): Option[UserState] = {
for {
u <- findWithIntId(users, intId)
} yield {
val newUser = u.modify(_.captionLocale).setTo(locale)
UserStateDAO.update(newUser)
users.save(newUser)
newUser
}
}

def hasPresenter(users: Users2x): Boolean = {
findPresenter(users) match {
case Some(p) => true
Expand Down Expand Up @@ -431,7 +442,9 @@ case class UserState(
lastInactivityInspect: Long = 0,
clientType: String,
userLeftFlag: UserLeftFlag,
speechLocale: String = ""
speechLocale: String = "",
captionLocale: String = ""

)

case class UserIdAndName(id: String, name: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ class ReceivedJsonMsgHandlerActor(
routeGenericMsg[UserConnectionAliveReqMsg](envelope, jsonNode)
case SetUserSpeechLocaleReqMsg.NAME =>
routeGenericMsg[SetUserSpeechLocaleReqMsg](envelope, jsonNode)
case SetUserCaptionLocaleReqMsg.NAME =>
routeGenericMsg[SetUserCaptionLocaleReqMsg](envelope, jsonNode)
case SetUserSpeechOptionsReqMsg.NAME =>
routeGenericMsg[SetUserSpeechOptionsReqMsg](envelope, jsonNode)

Expand Down Expand Up @@ -351,8 +353,8 @@ class ReceivedJsonMsgHandlerActor(
// Caption
case EditCaptionHistoryPubMsg.NAME =>
routeGenericMsg[EditCaptionHistoryPubMsg](envelope, jsonNode)
case UpdateCaptionOwnerPubMsg.NAME =>
routeGenericMsg[UpdateCaptionOwnerPubMsg](envelope, jsonNode)
case AddCaptionLocalePubMsg.NAME =>
routeGenericMsg[AddCaptionLocalePubMsg](envelope, jsonNode)
case SendCaptionHistoryReqMsg.NAME =>
routeGenericMsg[SendCaptionHistoryReqMsg](envelope, jsonNode)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ class MeetingActor(
case m: ChangeUserMobileFlagReqMsg => usersApp.handleChangeUserMobileFlagReqMsg(m)
case m: UserConnectionAliveReqMsg => usersApp.handleUserConnectionAliveReqMsg(m)
case m: SetUserSpeechLocaleReqMsg => usersApp.handleSetUserSpeechLocaleReqMsg(m)
case m: SetUserCaptionLocaleReqMsg => usersApp.handleSetUserCaptionLocaleReqMsg(m)
case m: SetUserSpeechOptionsReqMsg => usersApp.handleSetUserSpeechOptionsReqMsg(m)

// Client requested to eject user
Expand Down Expand Up @@ -582,7 +583,7 @@ class MeetingActor(

// Caption
case m: EditCaptionHistoryPubMsg => captionApp2x.handle(m, liveMeeting, msgBus)
case m: UpdateCaptionOwnerPubMsg => captionApp2x.handle(m, liveMeeting, msgBus)
case m: AddCaptionLocalePubMsg => captionApp2x.handle(m, liveMeeting, msgBus)
case m: SendCaptionHistoryReqMsg => captionApp2x.handle(m, liveMeeting, msgBus)

// Guests
Expand Down Expand Up @@ -934,8 +935,6 @@ class MeetingActor(

RegisteredUsers.updateUserJoin(liveMeeting.registeredUsers, ru, joined = false)

captionApp2x.handleUserLeavingMsg(leftUser.intId, liveMeeting, msgBus)

// send a user left event for the clients to update
val userLeftMeetingEvent = MsgBuilder.buildUserLeftMeetingEvtMsg(liveMeeting.props.meetingProp.intId, u.intId)
outGW.send(userLeftMeetingEvent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ object EditCaptionHistoryPubMsg { val NAME = "EditCaptionHistoryPubMsg" }
case class EditCaptionHistoryPubMsg(header: BbbClientMsgHeader, body: EditCaptionHistoryPubMsgBody) extends StandardMsg
case class EditCaptionHistoryPubMsgBody(startIndex: Integer, endIndex: Integer, name: String, locale: String, text: String)

object UpdateCaptionOwnerPubMsg { val NAME = "UpdateCaptionOwnerPubMsg" }
case class UpdateCaptionOwnerPubMsg(header: BbbClientMsgHeader, body: UpdateCaptionOwnerPubMsgBody) extends StandardMsg
case class UpdateCaptionOwnerPubMsgBody(name: String, locale: String, ownerId: String)
object AddCaptionLocalePubMsg { val NAME = "AddCaptionLocalePubMsg" }
case class AddCaptionLocalePubMsg(header: BbbClientMsgHeader, body: AddCaptionLocalePubMsgBody) extends StandardMsg
case class AddCaptionLocalePubMsgBody(locale: String)

object SendCaptionHistoryReqMsg { val NAME = "SendCaptionHistoryReqMsg" }
case class SendCaptionHistoryReqMsg(header: BbbClientMsgHeader, body: SendCaptionHistoryReqMsgBody) extends StandardMsg
Expand All @@ -18,9 +18,9 @@ object EditCaptionHistoryEvtMsg { val NAME = "EditCaptionHistoryEvtMsg" }
case class EditCaptionHistoryEvtMsg(header: BbbClientMsgHeader, body: EditCaptionHistoryEvtMsgBody) extends StandardMsg
case class EditCaptionHistoryEvtMsgBody(startIndex: Integer, endIndex: Integer, name: String, locale: String, text: String)

object UpdateCaptionOwnerEvtMsg { val NAME = "UpdateCaptionOwnerEvtMsg" }
case class UpdateCaptionOwnerEvtMsg(header: BbbClientMsgHeader, body: UpdateCaptionOwnerEvtMsgBody) extends StandardMsg
case class UpdateCaptionOwnerEvtMsgBody(name: String, locale: String, ownerId: String)
object AddCaptionLocaleEvtMsg { val NAME = "AddCaptionLocaleEvtMsg" }
case class AddCaptionLocaleEvtMsg(header: BbbClientMsgHeader, body: AddCaptionLocaleEvtMsgBody) extends StandardMsg
case class AddCaptionLocaleEvtMsgBody(locale: String)

object SendCaptionHistoryRespMsg { val NAME = "SendCaptionHistoryRespMsg" }
case class SendCaptionHistoryRespMsg(header: BbbClientMsgHeader, body: SendCaptionHistoryRespMsgBody) extends StandardMsg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,14 @@ object UserSpeechLocaleChangedEvtMsg { val NAME = "UserSpeechLocaleChangedEvtMsg
case class UserSpeechLocaleChangedEvtMsg(header: BbbClientMsgHeader, body: UserSpeechLocaleChangedEvtMsgBody) extends BbbCoreMsg
case class UserSpeechLocaleChangedEvtMsgBody(locale: String, provider: String)

object SetUserCaptionLocaleReqMsg { val NAME = "SetUserCaptionLocaleReqMsg" }
case class SetUserCaptionLocaleReqMsg(header: BbbClientMsgHeader, body: SetUserCaptionLocaleReqMsgBody) extends StandardMsg
case class SetUserCaptionLocaleReqMsgBody(locale: String, provider: String)

object UserCaptionLocaleChangedEvtMsg { val NAME = "UserCaptionLocaleChangedEvtMsg" }
case class UserCaptionLocaleChangedEvtMsg(header: BbbClientMsgHeader, body: UserCaptionLocaleChangedEvtMsgBody) extends BbbCoreMsg
case class UserCaptionLocaleChangedEvtMsgBody(locale: String, provider: String)

object SetUserSpeechOptionsReqMsg { val NAME = "SetUserSpeechOptionsReqMsg" }
case class SetUserSpeechOptionsReqMsg(header: BbbClientMsgHeader, body: SetUserSpeechOptionsReqMsgBody) extends StandardMsg
case class SetUserSpeechOptionsReqMsgBody(partialUtterances: Boolean, minUtteranceLength: Int)
Expand Down
GuiLeme marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RedisMessage } from '../types';

export default function buildRedisMessage(sessionVariables: Record<string, unknown>, input: Record<string, unknown>): RedisMessage {
const eventName = `UpdateCaptionOwnerPubMsg`;
const eventName = `AddCaptionLocalePubMsg`;

const routing = {
meetingId: sessionVariables['x-hasura-meetingid'] as String,
Expand All @@ -15,9 +15,7 @@ export default function buildRedisMessage(sessionVariables: Record<string, unkno
};

const body = {
name: '',
locale: input.locale,
ownerId: input.ownerUserId,
};

return { eventName, routing, header, body };
Expand Down
Loading
Loading