room.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. package room
  2. import (
  3. "bet24.com/log"
  4. "bet24.com/servers/common"
  5. IRoomMgr "bet24.com/servers/micros/audioroom/handler/interface"
  6. pb "bet24.com/servers/micros/audioroom/proto"
  7. "bet24.com/servers/micros/audioroom/transaction/database"
  8. userservices "bet24.com/servers/micros/userservices/proto"
  9. "bet24.com/servers/zego"
  10. "strconv"
  11. "sync"
  12. "time"
  13. )
  14. const room_Seconds = 600 // 过期时长(秒)
  15. type Room struct {
  16. roomMgr IRoomMgr.RoomMgr
  17. pb.RoomInfo // 房间基本信息
  18. pb.RoomExtInfo // 房间扩展信息
  19. pb.EnterCondition // 进入条件
  20. onlineUsers []int // 在线用户
  21. members []pb.UserRoomInfo // 成员用户
  22. mics []pb.MicInfo // 麦位
  23. blackList []pb.BlackInfo // 黑名单
  24. permissionList []pb.PermissionInfo // 权限列表
  25. taskList []*pb.RoomTask // 房间任务
  26. collectList []*pb.RoomCollect // 房间收集
  27. micApplyList []int // 上麦申请列表
  28. gameRoomList []*pb.GameRoomInfo // 游戏房间列表
  29. micLogList []pb.MicLog // 麦位日志
  30. lock *sync.RWMutex
  31. timeStamp int // 时间戳(用于清理过期数据)
  32. }
  33. func NewRoom(roomId int, mgr IRoomMgr.RoomMgr) *Room {
  34. ret := new(Room)
  35. ret.RoomId = roomId
  36. ret.roomMgr = mgr
  37. ret.lock = &sync.RWMutex{}
  38. ret.timeStamp = common.GetTimeStamp() + room_Seconds
  39. //log.Debug("room.newRoom roomId=%d", roomId)
  40. if !ret.loadRoom() {
  41. return ret
  42. }
  43. go func() {
  44. ret.loadEnterCondition()
  45. ret.loadMembers()
  46. ret.loadBlackList()
  47. ret.loadPermission(true)
  48. ret.loadTask()
  49. ret.loadCollect()
  50. }()
  51. return ret
  52. }
  53. // 获取房间信息
  54. func (this *Room) loadRoom() bool {
  55. // DB:房间信息
  56. info := database.GetRoom(this.RoomId)
  57. if info.RoomId <= 0 {
  58. return false
  59. }
  60. // 获取麦位信息
  61. mics := database.GetMicInfo(info.RoomId)
  62. if len(mics) <= 0 {
  63. mics = make([]pb.MicInfo, info.MicCount)
  64. }
  65. this.RoomInfo = info
  66. this.mics = mics
  67. return true
  68. }
  69. // 获取扩展信息
  70. func (this *Room) GetExtInfo() *pb.RoomExtInfo {
  71. // 还没有扩展信息
  72. if this.RoomExtInfo.UpdateTime == 0 {
  73. this.RoomExtInfo = database.GetExtInfo(this.RoomId)
  74. }
  75. // 判断是否过期
  76. if common.IsSameDay(this.RoomExtInfo.UpdateTime, common.GetTimeStamp()) {
  77. return &this.RoomExtInfo
  78. }
  79. this.RoomExtInfo.DayExps = 0
  80. this.RoomExtInfo.UpdateTime = common.GetTimeStamp()
  81. return &this.RoomExtInfo
  82. }
  83. // 获取房间进入条件
  84. func (this *Room) loadEnterCondition() {
  85. this.EnterCondition = database.GetEnterCondition(this.RoomId)
  86. return
  87. }
  88. // 是否过期房间
  89. func (this *Room) IsExpire() bool {
  90. if this.timeStamp >= common.GetTimeStamp() {
  91. //log.Debug("room.checkExpire roomId=%d 有效期时间 %s", this.RoomId, time.Unix(int64(this.timeStamp), 0).Format(common.Layout))
  92. this.checkOnlineUser()
  93. return false
  94. }
  95. if len(this.onlineUsers) > 0 {
  96. //log.Debug("room.checkExpire roomId=%d 已过期,仍有在线用户 %+v,有效期时间 %s",
  97. // this.RoomId, this.onlineUsers, time.Unix(int64(this.timeStamp), 0).Format(common.Layout))
  98. this.checkOnlineUser()
  99. return false
  100. }
  101. log.Debug("room.checkExpire roomId=%d 过期房间清理", this.RoomId)
  102. return true
  103. }
  104. // 更新时间戳
  105. func (this *Room) UpdateTimeStamp() {
  106. this.timeStamp = common.GetTimeStamp() + room_Seconds
  107. return
  108. }
  109. // sdk服务器 ==> 检查在线
  110. func (this *Room) checkOnlineUser() {
  111. // TODO:暂时不调用
  112. return
  113. log.Debug("room.checkOnlineUser roomId=%d 检查", this.RoomId)
  114. // 房间id
  115. roomId := strconv.Itoa(this.RoomId)
  116. // 获取在线用户数
  117. userCount := zego.GetUserNum(roomId)
  118. // 判断在线人数
  119. if this.OnlineCount == userCount {
  120. return
  121. }
  122. // 人数不相等,需要去同步
  123. var onlineUsers []int
  124. // 获取在线用户列表
  125. list := zego.GetUserList(roomId)
  126. for _, v := range list {
  127. uid, err := strconv.Atoi(v.UserId)
  128. if err != nil {
  129. log.Error("room.checkOnlineUser roomId=%s info=%+v err %v", roomId, v, err)
  130. continue
  131. }
  132. // 在线用户
  133. onlineUsers = append(onlineUsers, uid)
  134. }
  135. // 同步在线用户
  136. this.OnlineCount = userCount
  137. this.onlineUsers = onlineUsers
  138. // 用户通知在线
  139. go this.notify(pb.Notify_Action_Refresh_User, pb.ReasonData{
  140. Reason: pb.Notify_Reason_User_Online,
  141. UserId: -1,
  142. })
  143. log.Debug("room.checkOnlineUser 同步sdk服务器在线用户(%d)人,用户列表%v", this.OnlineCount, this.onlineUsers)
  144. }
  145. // 获取房间基本信息
  146. func (this *Room) GetRoomInfo() *pb.RoomInfo {
  147. return &this.RoomInfo
  148. }
  149. // 是否有效房间
  150. func (this *Room) IsValid() bool {
  151. return this.UserId > 0
  152. }
  153. // 获取房间任务列表
  154. func (this *Room) GetRoomTaskList() []*pb.RoomTask {
  155. return this.taskList
  156. }
  157. // 是否允许进入房间
  158. func (this *Room) IsEnterRoom(userId int, password string) int {
  159. // 管理员直接进入
  160. if this.UserId == userId {
  161. return 1
  162. }
  163. // 会员用户
  164. for _, v := range this.members {
  165. if v.UserId == userId {
  166. return 1
  167. }
  168. }
  169. // 游客,需要判断条件
  170. // 1=只能邀请进入
  171. if this.InviteOnly {
  172. return 11
  173. }
  174. // 2=是否隐藏
  175. if this.IsHide {
  176. return 14
  177. }
  178. // 3=是否黑名单
  179. if this.IsBlack(userId, pb.BlackType_Room) {
  180. return 13
  181. }
  182. // 4=房间密码
  183. if this.PwdExpire > common.GetTimeStamp() {
  184. // 校验密码
  185. if password != this.Password {
  186. return 12
  187. }
  188. }
  189. return 1
  190. }
  191. // 进入房间
  192. func (this *Room) EnterRoom(userId int) bool {
  193. // 在线用户
  194. for _, uid := range this.onlineUsers {
  195. if uid == userId {
  196. return true
  197. }
  198. }
  199. this.onlineUsers = append(this.onlineUsers, userId)
  200. this.OnlineCount = len(this.onlineUsers)
  201. go func() {
  202. roleId := this.GetMemberInfo(userId).RoleId
  203. this.notify(pb.Notify_Action_Refresh_User, pb.ReasonData{
  204. Reason: pb.Notify_Reason_User_Online,
  205. NotifyUserId: userId,
  206. UserId: userId,
  207. OldRoleId: roleId,
  208. NewRoleId: roleId,
  209. })
  210. }()
  211. return true
  212. }
  213. // 退出房间
  214. func (this *Room) ExitRoom(userId int) {
  215. for i := 0; i < len(this.onlineUsers); i++ {
  216. if this.onlineUsers[i] != userId {
  217. continue
  218. }
  219. this.onlineUsers = append(this.onlineUsers[:i], this.onlineUsers[i+1:]...)
  220. break
  221. }
  222. this.OnlineCount = len(this.onlineUsers)
  223. go this.notify(pb.Notify_Action_Refresh_User, pb.ReasonData{
  224. Reason: pb.Notify_Reason_User_Offline,
  225. NotifyUserId: userId,
  226. UserId: userId,
  227. })
  228. // 删除申请处理
  229. this.delMicApply(userId)
  230. return
  231. }
  232. // 创建房间
  233. func (this *Room) CreateRoom(userId int, roomName, country, language, ipAddress, roomImg, announce, tag string) {
  234. // 封面为空信息,取头像
  235. if roomImg == "" {
  236. if u := userservices.GetUserInfo(userId); u != nil {
  237. roomImg = u.FaceUrl
  238. }
  239. }
  240. if country == "" {
  241. country = "SAR"
  242. }
  243. // 初始化房间信息
  244. info := pb.RoomInfo{
  245. RoomId: userId,
  246. RoomName: roomName,
  247. RoomImg: roomImg,
  248. UserId: userId,
  249. Family: "Club",
  250. Country: country,
  251. Language: language,
  252. MicCount: mic_defaultCount,
  253. MicMode: pb.OnMic_All,
  254. Announce: announce,
  255. Tag: tag,
  256. MemberCount: 1,
  257. Crdate: common.GetNowTimeStr(),
  258. Level: 1,
  259. }
  260. this.RoomInfo = info
  261. this.mics = make([]pb.MicInfo, info.MicCount)
  262. this.members = append(this.members, pb.UserRoomInfo{
  263. UserId: userId,
  264. RoomId: userId,
  265. RoleId: pb.Role_Administrator,
  266. Crdate: common.GetNowTimeStr(),
  267. })
  268. this.loadPermission(false)
  269. // DB:创建房间
  270. go func() {
  271. // 创建房间
  272. database.CreateRoom(&this.RoomInfo)
  273. // 保存麦位信息
  274. database.SetMicInfo(this.RoomId, this.mics)
  275. this.loadTask()
  276. }()
  277. return
  278. }
  279. // 修改房间封面
  280. func (this *Room) UpdateRoomImg(roomImg string) {
  281. this.RoomImg = roomImg
  282. go func() {
  283. // 修改房间
  284. database.UpdateRoom(&this.RoomInfo)
  285. // 发送通知
  286. this.notify(pb.Notify_Action_Refresh_Room, pb.ReasonData{})
  287. }()
  288. return
  289. }
  290. // 修改房间信息
  291. func (this *Room) UpdateRoom(userId int, r *pb.RoomInfo) int {
  292. if this.UserId != userId {
  293. return 11
  294. }
  295. log.Debug("room.updateRoom userId=%d ==> %+v", userId, r)
  296. this.RoomName = r.RoomName
  297. this.Family = r.Family
  298. this.Country = r.Country
  299. this.Language = r.Language
  300. // 麦位发生变化
  301. if this.MicCount != r.MicCount {
  302. log.Debug("room.updateRoom userId=%d this.MicCount=%d r.MicCount=%d", userId, this.MicCount, r.MicCount)
  303. if this.MicCount < r.MicCount { // 扩麦处理
  304. log.Debug("room.updateRoom userId=%d 扩麦处理", userId)
  305. // 新增麦位
  306. for i := r.MicCount - 1; i >= this.MicCount; i-- {
  307. this.mics = append(this.mics, pb.MicInfo{
  308. UserId: mic_idle,
  309. StreamId: "",
  310. })
  311. }
  312. } else if this.MicCount > r.MicCount { // 缩麦处理
  313. log.Debug("room.updateRoom userId=%d 缩麦处理", userId)
  314. // 踢麦且发送通知
  315. for i := r.MicCount; i < this.MicCount; i++ {
  316. if this.mics[i].UserId > mic_idle {
  317. roomId := strconv.Itoa(this.RoomId)
  318. uid := strconv.Itoa(this.mics[i].UserId * -1)
  319. // sdk服务器 ==> 删除房间流
  320. code, message := zego.MuteUser(roomId, uid, this.mics[i].StreamId)
  321. log.Debug("room.offTheMic(zego.MuteUser) i=%d userId=%s roomId=%s streamId=%s code=%d message=%s",
  322. i, uid, roomId, this.mics[i].StreamId, code, message)
  323. // 麦位通知
  324. //go this.notify(this.mics[i].UserId, pb.Notify_Action_Refresh_Mic, pb.ReasonData{
  325. // Reason: pb.Notify_Reason_Mic_Change,
  326. // SN: i,
  327. //})
  328. }
  329. }
  330. log.Debug("room.updateRoom 缩麦前 this.Mics=%+v", this.mics)
  331. // 缩麦
  332. this.mics = this.mics[:r.MicCount]
  333. log.Debug("room.updateRoom 缩麦后 this.Mics=%+v", this.mics)
  334. }
  335. // 麦位通知
  336. this.notify(pb.Notify_Action_Refresh_Mic, pb.ReasonData{Reason: pb.Notify_Reason_Mic_Change})
  337. }
  338. this.MicCount = r.MicCount
  339. // 申请模式切换到其他模式,需要清理麦位申请列表
  340. if this.MicMode == pb.OnMic_Apply && r.MicMode != pb.OnMic_Apply {
  341. this.delMicApply(0)
  342. }
  343. this.MicMode = r.MicMode
  344. this.JoinFee = r.JoinFee
  345. this.Announce = r.Announce
  346. this.Tag = r.Tag
  347. // DB:更新数据库
  348. go func() {
  349. // 修改房间
  350. database.UpdateRoom(&this.RoomInfo)
  351. var mics []pb.MicInfo
  352. for _, v := range this.mics {
  353. if v.UserId == mic_lock {
  354. mics = append(mics, v)
  355. } else {
  356. mics = append(mics, pb.MicInfo{
  357. UserId: mic_idle,
  358. StreamId: "",
  359. })
  360. }
  361. }
  362. // 保存麦位信息
  363. database.SetMicInfo(this.RoomId, mics)
  364. }()
  365. // 发送通知
  366. go this.notify(pb.Notify_Action_Refresh_Room, pb.ReasonData{})
  367. return 1
  368. }
  369. // 在线用户列表
  370. func (this *Room) GetOnlineUsers() []int {
  371. return this.onlineUsers
  372. }
  373. // 查询用户信息
  374. func (this *Room) SearchUser(userId int) pb.UserRoomInfo {
  375. // 会员
  376. for _, v := range this.members {
  377. if v.UserId == userId {
  378. return v
  379. }
  380. }
  381. // 黑名单
  382. for _, v := range this.blackList {
  383. if v.UserId == userId {
  384. return pb.UserRoomInfo{
  385. UserId: userId,
  386. RoomId: this.RoomId,
  387. RoleId: pb.Role_Guest,
  388. Crdate: common.GetNowTimeStr(),
  389. }
  390. }
  391. }
  392. return pb.UserRoomInfo{}
  393. }
  394. // 获取房间进入条件
  395. func (this *Room) GetEnterCondition(userId int) pb.EnterCondition {
  396. // 只有管理员才能设置
  397. if this.UserId != userId {
  398. return pb.EnterCondition{}
  399. }
  400. return this.EnterCondition
  401. }
  402. // 设置房间进入条件
  403. func (this *Room) SetEnterCondition(userId int, inviteOnly bool, password string, seconds int, isHide bool) int {
  404. // 只有管理员才能设置
  405. if this.UserId != userId {
  406. return 11
  407. }
  408. pwdExpire := 0
  409. if len(password) > 0 {
  410. pwdExpire = common.GetTimeStamp() + seconds
  411. }
  412. // 修改数据
  413. this.EnterCondition = pb.EnterCondition{
  414. InviteOnly: inviteOnly,
  415. Password: password,
  416. PwdExpire: pwdExpire,
  417. IsHide: isHide,
  418. }
  419. // 数据库操作
  420. go database.SetEnterCondition(this.RoomId, this.EnterCondition)
  421. return 1
  422. }
  423. // 通知房间
  424. func (this *Room) NotifyRoom() {
  425. go this.notify(pb.Notify_Action_Refresh_Room, pb.ReasonData{})
  426. }
  427. // 设置屏幕锁(1=锁定,0=解锁)
  428. func (this *Room) SetScreenLock(userId, screenLock int) int {
  429. // 是否管理员
  430. if !this.isAdmin(userId) {
  431. return -1
  432. }
  433. // 锁屏广播
  434. go this.notify(pb.Notify_Action_Screen_Lock, pb.ReasonData{
  435. Reason: pb.Notify_Reason_Screen_Lock,
  436. UserId: userId,
  437. ScreenLock: screenLock,
  438. })
  439. this.RoomExtInfo.ScreenLock = screenLock
  440. this.RoomExtInfo.UpdateTime = common.GetTimeStamp()
  441. go database.UpdateExtInfo(this.RoomId, &this.RoomExtInfo)
  442. return 1
  443. }
  444. // 是否禁止发言(true:禁止)
  445. func (this *Room) IsBannedSpeak(userId int) bool {
  446. if this.RoomExtInfo.ScreenLock == 0 {
  447. return false
  448. }
  449. // 是否管理员
  450. if this.isAdmin(userId) {
  451. return false
  452. }
  453. if this.isOnMic(userId) {
  454. return false
  455. }
  456. return true
  457. }
  458. // 打印房间
  459. func (this *Room) DumpRoom() {
  460. log.Debug("房间ID(%d),过期时间[%s]:", this.RoomId, time.Unix(int64(this.timeStamp), 0).Format(common.Layout))
  461. log.Debug(" 基本信息:%+v ", this.RoomInfo)
  462. log.Debug(" 房间进入条件:%+v", this.EnterCondition)
  463. log.Debug(" 在线用户(%d)人:%+v", len(this.onlineUsers), this.onlineUsers)
  464. log.Debug(" 成员用户(%d)人:%+v", len(this.members), this.members)
  465. log.Debug(" 黑名单用户(%d)个:%+v", len(this.blackList), this.blackList)
  466. log.Debug(" 权限列表(%d)个:%+v", len(this.permissionList), this.permissionList)
  467. log.Debug(" 麦位用户(%d)个:%+v", len(this.mics), this.mics)
  468. log.Debug(" 任务列表:")
  469. for _, v := range this.taskList {
  470. log.Debug(" %+v", v)
  471. }
  472. log.Debug(" 收集列表:")
  473. for _, v := range this.collectList {
  474. log.Debug(" %+v", v)
  475. }
  476. log.Debug(" 游戏房间列表(%d)个:", len(this.gameRoomList))
  477. for _, v := range this.gameRoomList {
  478. log.Debug(" %+v", v)
  479. }
  480. log.Debug(" 麦位申请列表(%d)个:", len(this.micApplyList))
  481. for _, v := range this.micApplyList {
  482. log.Debug(" %+v", v)
  483. }
  484. log.Debug(" 麦位日志列表(%d)个:", len(this.micLogList))
  485. for _, v := range this.micLogList {
  486. log.Debug(" %+v", v)
  487. }
  488. log.Debug("###############################################")
  489. }
  490. // 获取上麦的数量
  491. func (this *Room) GetUpMicCount() int {
  492. return pb.AdminGetUpMicCount(this.mics)
  493. }