| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- package room
- import (
- "bet24.com/log"
- "bet24.com/servers/common"
- pb "bet24.com/servers/micros/audioroom/proto"
- "bet24.com/servers/micros/audioroom/transaction/database"
- task "bet24.com/servers/micros/task/proto"
- "bet24.com/servers/zego"
- "strconv"
- )
- const (
- mic_lock = -1 // 锁定
- mic_idle = 0 // 空闲
- mic_defaultCount = 5 // 默认上麦数量
- mic_timeOut = 10 // 麦位超时
- )
- // 是否麦位空闲
- func (this *Room) isMicIdle(index int) bool {
- if index < 0 || index >= len(this.mics) {
- log.Error("room_mic.IsMicIdle out of index roomId=%d index=%d", this.RoomId, index)
- return false
- }
- m := &this.mics[index]
- // 麦已锁
- if m.UserId == mic_lock {
- return false
- }
- // 有房间流
- if m.StreamId != "" {
- return false
- }
- // 麦已占(麦位锁定几秒钟)
- if m.UserId > mic_idle && m.TimeStamp+mic_timeOut <= common.GetTimeStamp() {
- return false
- }
- m.UserId = mic_idle
- m.TimeStamp = 0
- return true
- }
- // 判断是否已占麦位
- func (this *Room) isOnMic(userId int) bool {
- for _, v := range this.mics {
- if v.UserId == userId {
- return true
- }
- }
- return false
- }
- // 获取麦克风列表信息
- func (this *Room) GetMicListInfo() []pb.MicInfo {
- return this.mics
- }
- // 获取麦列表
- func (this *Room) GetMicList() []int {
- var list []int
- for k, v := range this.mics {
- // 占位不显示用户
- if v.StreamId == "" && v.UserId > mic_idle {
- // 超时清理
- if v.TimeStamp+mic_timeOut <= common.GetTimeStamp() {
- this.mics[k].UserId = mic_idle
- }
- list = append(list, mic_idle)
- continue
- }
- // 正常处理
- list = append(list, v.UserId)
- }
- return list
- }
- // 上麦
- func (this *Room) OnTheMic(userId, sn int) int {
- // 判断是否在黑名单
- if this.IsBlack(userId, pb.BlackType_Mic) {
- return 15
- }
- // 会员信息
- m := this.GetMemberInfo(userId)
- for i := 0; i < len(this.mics); i++ {
- if i != sn {
- continue
- }
- // 判断是否麦位空闲
- if !this.isMicIdle(i) {
- return 13
- }
- // 上麦模式(3种模式)
- // 0=房间内所有成员自由上麦
- if this.MicMode == pb.OnMic_All {
- // 上麦
- this.mics[i].UserId = userId
- this.mics[i].TimeStamp = common.GetTimeStamp()
- // 添加上麦日志
- go this.addOnMicLog(userId, userId, this.MicMode, m.RoleId)
- break
- }
- // 1=加入为成员才可以上麦
- if this.MicMode == pb.OnMic_Member {
- if m.UserId == 0 {
- return 16
- }
- }
- // 非管理员
- if m.RoleId != pb.Role_Assistant && m.RoleId != pb.Role_Administrator {
- // 2=仅限管理员邀请或者管理员才能上麦(包含创建者),调用邀请上麦接口 InviteOnMic
- if this.MicMode == pb.OnMic_Manager {
- return 17
- }
- // 3=申请才能上麦,调用申请上麦接口 ApplyOnMic
- if this.MicMode == pb.OnMic_Apply {
- return 18
- }
- }
- // 上麦
- this.mics[i].UserId = userId
- this.mics[i].TimeStamp = common.GetTimeStamp()
- // 添加上麦日志
- go this.addOnMicLog(userId, userId, this.MicMode, m.RoleId)
- break
- }
- // 清理重复占麦
- for i := 0; i < len(this.mics); i++ {
- if i == sn {
- continue
- }
- if this.mics[i].UserId != userId {
- continue
- }
- // 占麦清理,添加下麦日志
- if this.mics[i].StreamId != "" {
- go this.AddOffMicLog(userId, this.mics[i].StreamId)
- }
- this.mics[i] = pb.MicInfo{
- UserId: mic_idle,
- StreamId: "",
- TimeStamp: 0,
- }
- }
- return 1
- }
- // 上麦回调通知
- func (this *Room) OnTheMicNotify(userId int, streamId string) int {
- for i := 0; i < len(this.mics); i++ {
- if this.mics[i].UserId != userId {
- continue
- }
- // 清掉已占的麦位
- if this.mics[i].StreamId != "" && this.mics[i].StreamId != streamId {
- this.mics[i] = pb.MicInfo{
- UserId: mic_idle,
- StreamId: "",
- TimeStamp: 0,
- }
- continue
- }
- this.mics[i].StreamId = streamId
- this.mics[i].TimeStamp = common.GetTimeStamp()
- // 通知上麦日志
- go this.notifyOnMicLog(userId, i, streamId)
- }
- // 麦位通知
- go this.notify(pb.Notify_Action_Refresh_Mic, pb.ReasonData{
- Reason: pb.Notify_Reason_Mic_Change,
- UserId: userId,
- })
- return 1
- }
- // 下麦回调通知
- func (this *Room) OffTheMicNotify(userId int, streamId string) int {
- for i := 0; i < len(this.mics); i++ {
- if this.mics[i].UserId != userId {
- continue
- }
- if this.mics[i].StreamId != streamId {
- log.Release("room.offTheMic userId=%d streamId=%s is valid %+v", userId, streamId, this.mics[i])
- continue
- }
- // 计算时长
- seconds := common.GetTimeStamp() - this.mics[i].TimeStamp
- this.mics[i] = pb.MicInfo{
- UserId: mic_idle,
- StreamId: "",
- TimeStamp: 0,
- }
- go func() {
- // 麦位通知
- this.notify(pb.Notify_Action_Refresh_Mic, pb.ReasonData{
- Reason: pb.Notify_Reason_Mic_Change,
- UserId: userId,
- SN: i,
- })
- // 下麦日志
- this.AddOffMicLog(userId, streamId)
- // 触发房间任务
- this.roomMgr.DoRoomTaskAction(userId, this.RoomId, pb.RoomTask_Action_OnMic, seconds)
- // 触发用户任务
- this.roomMgr.DoUserTaskAction(userId, this.RoomId, pb.UserTask_Action_OnMic, seconds, 0)
- // 触发大厅任务
- task.DoTaskAction(userId, task.TaskAction_upMicDuration, seconds, task.TaskScope{})
- }()
- return 1
- }
- return 11
- }
- // 加解锁麦(status -1=上锁 0=解锁)
- func (this *Room) SetMic(userId, sn int, status int) int {
- if status != mic_lock && status != mic_idle {
- return 11
- }
- for i := 0; i < len(this.mics); i++ {
- if i == sn {
- // 空闲时才允许上锁
- if status == mic_lock && this.mics[i].UserId > 0 {
- return 11
- }
- this.mics[i].UserId = status
- // 麦位通知
- go this.notify(pb.Notify_Action_Refresh_Mic, pb.ReasonData{
- Reason: pb.Notify_Reason_Mic_Change,
- SN: i,
- })
- return 1
- }
- }
- return 12
- }
- // 邀请上麦(通知接收者直接调用sdk上麦)
- func (this *Room) InviteOnMic(userId, toUserId int) int {
- // 不能自己邀请自己和房主
- if userId == toUserId || this.UserId == toUserId {
- return 16
- }
- // 会员信息
- m := this.GetMemberInfo(userId)
- // 只有管理员才能发送邀请
- if m.RoleId != pb.Role_Administrator && m.RoleId != pb.Role_Assistant {
- return 16
- }
- // 同级别不能邀请
- toM := this.GetMemberInfo(toUserId)
- if toM.RoleId == m.RoleId {
- return 16
- }
- // 判断是否在黑名单
- if this.IsBlack(toUserId, pb.BlackType_Mic) {
- return 15
- }
- // 判断是否已占麦位
- if this.isOnMic(toUserId) {
- return 12
- }
- // 判断是否在线
- var isOnline bool
- for _, v := range this.onlineUsers {
- if v == toUserId {
- isOnline = true
- break
- }
- }
- // 非在线用户
- if !isOnline {
- return 17
- }
- for i := 0; i < len(this.mics); i++ {
- // 判断是否麦位空闲
- if !this.isMicIdle(i) {
- continue
- }
- // 上麦
- this.mics[i].UserId = toUserId
- this.mics[i].TimeStamp = common.GetTimeStamp()
- // 判断是否已申请
- if this.isMicApply(toUserId) {
- // 麦位申请删除
- this.delMicApply(toUserId)
- // 发送申请同意通知
- go this.notify(pb.Notify_Action_Refresh_User, pb.ReasonData{
- Reason: pb.Notify_Reason_User_Mic_Apply_Agree,
- NotifyUserId: toUserId,
- UserId: userId,
- SN: i,
- })
- // 添加上麦日志
- go this.addOnMicLog(toUserId, userId, pb.OnMic_Apply, toM.RoleId)
- return 1
- }
- // 发送邀请通知
- go this.notify(pb.Notify_Action_Refresh_Mic, pb.ReasonData{
- Reason: pb.Notify_Reason_Mic_Invite,
- NotifyUserId: toUserId,
- UserId: userId,
- SN: i,
- })
- // 添加上麦日志
- go this.addOnMicLog(toUserId, userId, pb.OnMic_Manager, toM.RoleId)
- return 1
- }
- return 11
- }
- // 踢麦
- func (this *Room) KickMic(userId, toUserId int) int {
- for i := 0; i < len(this.mics); i++ {
- if this.mics[i].UserId != toUserId {
- continue
- }
- roomId := strconv.Itoa(this.RoomId)
- uid := strconv.Itoa(toUserId * -1)
- // sdk服务器 ==> 删除房间流
- code, message := zego.MuteUser(roomId, uid, this.mics[i].StreamId)
- log.Debug("room.kickMic(zego.MuteUser) i=%d userId=%s roomId=%s streamId=%s code=%d message=%s",
- i, uid, roomId, this.mics[i].StreamId, code, message)
- // 计算时长
- seconds := common.GetTimeStamp() - this.mics[i].TimeStamp
- // 清空麦位
- this.mics[i] = pb.MicInfo{
- UserId: 0,
- StreamId: "",
- TimeStamp: 0,
- }
- go func() {
- // 触发房间任务
- this.roomMgr.DoRoomTaskAction(toUserId, this.RoomId, pb.RoomTask_Action_OnMic, seconds)
- // 触发用户任务
- this.roomMgr.DoUserTaskAction(toUserId, this.RoomId, pb.UserTask_Action_OnMic, seconds, 0)
- // 踢麦通知
- this.notify(pb.Notify_Action_Refresh_Mic, pb.ReasonData{
- Reason: pb.Notify_Reason_Mic_Kick,
- UserId: toUserId,
- SN: i,
- })
- }()
- // 添加日志
- this.AddOperateLog(this.RoomId, userId, toUserId, pb.OperateType_KickMic)
- return 1
- }
- return 11
- }
- // 上麦申请列表
- func (this *Room) GetOnMicApplyList() []int {
- this.lock.RLock()
- defer this.lock.RUnlock()
- return this.micApplyList
- }
- // 申请队列信息
- func (this *Room) isMicApply(userId int) bool {
- // 判断是否已申请
- for _, uid := range this.micApplyList {
- if uid == userId {
- return true
- }
- }
- return false
- }
- // 申请上麦
- func (this *Room) ApplyOnMic(userId int) pb.RetMsg {
- var retMsg pb.RetMsg
- // 非申请模式
- if this.MicMode != pb.OnMic_Apply {
- retMsg.RetCode = 15
- retMsg.Message = "Non-application mode"
- return retMsg
- }
- // 是否黑名单
- if this.IsBlack(userId, pb.BlackType_Mic) {
- retMsg.RetCode = 11
- retMsg.Message = "blacklist users"
- return retMsg
- }
- // 判断是否已占麦位
- if this.isOnMic(userId) {
- retMsg.RetCode = 13
- retMsg.Message = "already on the mic"
- return retMsg
- }
- // 判断是否已申请
- if this.isMicApply(userId) {
- retMsg.RetCode = 12
- retMsg.Message = "Already in the application list"
- return retMsg
- }
- // 添加到申请列表
- this.micApplyList = append(this.micApplyList, userId)
- // 麦位申请数量变化通知
- go this.notify(pb.Notify_Action_Refresh_User, pb.ReasonData{
- Reason: pb.Notify_Reason_User_Mic_Apply,
- MicApplyCount: len(this.micApplyList),
- })
- retMsg.RetCode = 1
- retMsg.Message = "successful application"
- return retMsg
- }
- // 取消申请上麦
- func (this *Room) CancelApplyOnMic(userId int) pb.RetMsg {
- var retMsg pb.RetMsg
- // 清理占麦
- for i := 0; i < len(this.mics); i++ {
- if this.mics[i].UserId != userId {
- continue
- }
- if this.mics[i].StreamId != "" {
- continue
- }
- this.mics[i].UserId = mic_idle
- this.mics[i].TimeStamp = 0
- break
- }
- // 删除申请处理
- this.delMicApply(userId)
- retMsg.RetCode = 1
- retMsg.Message = "Cancellation request successful"
- return retMsg
- }
- // 麦位申请取消或删除
- func (this *Room) delMicApply(toUserId int) {
- // 清理所有
- if toUserId == 0 {
- this.micApplyList = this.micApplyList[0:0]
- }
- // 处理申请
- for i := 0; i < len(this.micApplyList); i++ {
- if this.micApplyList[i] != toUserId {
- continue
- }
- this.micApplyList = append(this.micApplyList[:i], this.micApplyList[i+1:]...)
- break
- }
- // 麦位申请数量变化通知
- go this.notify(pb.Notify_Action_Refresh_User, pb.ReasonData{
- Reason: pb.Notify_Reason_User_Mic_Apply_Cancel,
- MicApplyCount: len(this.micApplyList),
- })
- return
- }
- // 处理申请上麦(1=同意 2=拒绝)(通知接收者直接调用sdk上麦)
- func (this *Room) DealApplyOnMic(userId, toUserId, status int) pb.RetMsg {
- var retMsg pb.RetMsg
- // 判断申请状态
- if status != pb.MicApply_Status_Agree && status != pb.MicApply_Status_Reject {
- retMsg.RetCode = 11
- retMsg.Message = "illegal data"
- return retMsg
- }
- // 是否管理员
- if !this.isAdmin(userId) {
- retMsg.RetCode = 11
- retMsg.Message = "you are not an administrator"
- return retMsg
- }
- // 拒绝处理
- if status == pb.MicApply_Status_Reject {
- // 麦位申请拒绝
- this.delMicApply(toUserId)
- retMsg.RetCode = 1
- retMsg.Message = "refusal to succeed"
- return retMsg
- }
- // 判断是否有申请
- if !this.isMicApply(toUserId) {
- retMsg.RetCode = 1
- retMsg.Message = "Consent Request Sent"
- return retMsg
- }
- // 同意处理
- for i := 0; i < len(this.mics); i++ {
- // 判断是否麦位空闲
- if !this.isMicIdle(i) {
- continue
- }
- // 上麦
- this.mics[i].UserId = toUserId
- this.mics[i].TimeStamp = common.GetTimeStamp()
- // 麦位申请删除
- this.delMicApply(toUserId)
- // 发送通知
- go this.notify(pb.Notify_Action_Refresh_User, pb.ReasonData{
- Reason: pb.Notify_Reason_User_Mic_Apply_Agree,
- NotifyUserId: toUserId,
- UserId: userId,
- SN: i,
- })
- // 添加上麦日志
- go this.addOnMicLog(toUserId, userId, pb.OnMic_Apply, pb.Role_MAX)
- retMsg.RetCode = 1
- retMsg.Message = "Consent Request Sent"
- return retMsg
- }
- retMsg.RetCode = 12
- retMsg.Message = "Not enough free mic slots"
- return retMsg
- }
- // 添加上麦日志
- func (this *Room) addOnMicLog(userId, opUserId, micMode, roleId int) {
- // 无效值
- if roleId == pb.Role_MAX {
- roleId = this.GetMemberInfo(userId).RoleId
- }
- this.micLogList = append(this.micLogList, pb.MicLog{
- UserId: userId,
- RoleID: roleId,
- MicMode: micMode,
- OpUserId: opUserId,
- })
- return
- }
- // 通知上麦日志
- func (this *Room) notifyOnMicLog(userId, sn int, streamId string) {
- for k, v := range this.micLogList {
- if v.UserId != userId {
- continue
- }
- this.micLogList[k].StreamId = streamId
- this.micLogList[k].SN = sn
- this.micLogList[k].OnMicStamp = common.GetTimeStamp()
- break
- }
- return
- }
- // 添加下麦日志
- func (this *Room) AddOffMicLog(userId int, streamId string) {
- for i := 0; i < len(this.micLogList); i++ {
- v := this.micLogList[i]
- // 无效
- if v.StreamId == "" {
- continue
- }
- if userId > 0 && v.UserId != userId {
- continue
- }
- if streamId != "" && v.StreamId != streamId {
- continue
- }
- // 删除
- this.micLogList = append(this.micLogList[:i], this.micLogList[i+1:]...)
- ts := common.GetTimeStamp()
- seconds := ts - v.OnMicStamp
- // 数据库操作
- go database.AddMicLog(v.UserId, this.RoomId, v.RoleID, v.SN, v.MicMode, v.OnMicStamp, ts, seconds, v.OpUserId)
- // 移动索引
- i--
- }
- return
- }
|