package group_mic_s import ( "context" "encoding/json" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/rpc" uuid "github.com/satori/go.uuid" "hilo-group/_const/enum/group_e" "hilo-group/_const/redis_key" "hilo-group/domain/event/group_ev" "hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/group_m" "hilo-group/domain/model/user_m" "hilo-group/domain/service/signal_s" "hilo-group/myerr" "hilo-group/myerr/bizerr" "time" ) type GroupMicService struct { svc *domain.Service } func NewGroupPowerService(myContext *mycontext.MyContext) *GroupMicService { svc := domain.CreateService(myContext) return &GroupMicService{svc} } //修改群组中麦的数量 func (s *GroupMicService) GroupMicNumChange(groupId string, userId uint64, micNumType group_e.GroupMicNumType, micOn bool) error { model := domain.CreateModelContext(s.svc.MyContext) //数据库修改群组麦的数量 //检查权限 if err := group_m.CheckPermission(model, groupId, userId); err != nil { return err } //删除麦位数量类型缓存 group_m.InitMicNumType(model, groupId, micNumType).ClearCache() // groupInfo, _ := group_m.GetGroupInfo(model, groupId) if groupInfo == nil { return bizerr.GroupNotFound } //判断数据是否发生了变化 //关闭麦位 if micOn == false { if groupInfo.MicOn == micOn { return nil } } else { if groupInfo.MicOn == micOn && groupInfo.MicNumType == micNumType { return nil } } //修改数据,然后数据持久化, g := group_m.GroupInfo{ MicOn: micOn, } fields := []string{"mic_on"} //开启麦位才修改micNumType returnMicNumType := g.MicNumType if micOn == true { g.MicNumType = micNumType fields = append(fields, "mic_num_type") returnMicNumType = micNumType } db := g.Update(model, groupId, fields) if db.Error != nil { return myerr.WrapErr(db.Error) } //增加麦位数量类型缓存 group_m.InitMicNumType(model, groupId, micNumType).AddCache() //麦位上的信息,清理 group_m.ClearMic(groupId) type Content struct { MicOn bool `json:"micOn"` MicNumType group_e.GroupMicNumType `json:"micNumType"` Timestamp int64 `json:"timestamp"` } r := Content{ MicOn: micOn, MicNumType: returnMicNumType, Timestamp: time.Now().Unix(), } buf, err := json.Marshal(r) if err != nil { model.Log.Errorf("GroupMicNumChange Content json.Marshal err:%v", err) } // 发信令,让前端重新拉取,接受容错, signal_s.SendSignalMsg(model, groupId, group_m.GroupSystemMsg{ MsgId: group_e.GroupMicChangeSignal, Content: string(buf), }, false) group_m.MicNumChangeRPush(model, groupId, returnMicNumType, micOn) return nil } //加锁, sign作为密钥存在(预防被别人删除,比如:先者删除了后者的锁), func redisLock(key string, sign string, expiration time.Duration, callBack func() error) error { flag, err := redisCli.GetRedis().SetNX(context.Background(), key, sign, expiration).Result() if err != nil { return myerr.WrapErr(err) } if flag { err = callBack() redisSign, _ := redisCli.GetRedis().Get(context.Background(), key).Result() if redisSign == sign { redisCli.GetRedis().Del(context.Background(), key) } return err } else { return bizerr.GroupConcurrencyLock } } //加入麦位,锁两秒 func (s *GroupMicService) GroupMicIn(groupUuid string, i int, userId uint64, externalId string) error { return redisLock(redis_key.GetPrefixGroupMicUserInLock(userId), uuid.NewV4().String(), time.Second*2, func() error { model := domain.CreateModel(s.svc.CtxAndDb) mic, err := group_m.GetMic(model, groupUuid, i) if err != nil { return err } return mic.In(userId, externalId) }) } //离开麦位 func (s *GroupMicService) GroupMicLeave(groupUuid string, i int, userId uint64, externalId string) error { return redisLock(redis_key.GetPrefixGroupMicUserDelLock(groupUuid, i), uuid.NewV4().String(), time.Second*2, func() error { model := domain.CreateModel(s.svc.CtxAndDb) micUser, err := group_m.GetMicUser(model, groupUuid, i) if err != nil { return err } if micUser != nil { return micUser.LeaveByUser(userId, externalId) } return nil }) } //邀请上麦,锁两秒 func (s *GroupMicService) GroupMicInvite(groupUuid string, operateUserId uint64, beInvitedExternalId string) error { model := domain.CreateModelContext(s.svc.MyContext) if err := group_m.InviteMicIn(model, groupUuid, operateUserId, beInvitedExternalId); err != nil { return err } return nil } //麦位加锁, func (s *GroupMicService) GroupMicLock(userId uint64, externalId string, groupUuid string, i int) error { //后果等级不高,不需要加锁 model := domain.CreateModelContext(s.svc.MyContext) mic, err := group_m.GetMic(model, groupUuid, i) if err != nil { return err } return mic.MgrLock(userId, externalId) } //麦位解锁 func (s *GroupMicService) GroupMicUnLock(userId uint64, externalId string, groupUuid string, i int) error { //后果等级不高,不需要加锁 model := domain.CreateModelContext(s.svc.MyContext) mic, err := group_m.GetMic(model, groupUuid, i) if err != nil { return err } return mic.MgrUnLock(userId, externalId) } // 麦位静音 func (s *GroupMicService) GroupMicMute(userId uint64, externalId string, groupUuid string, i int) error { //后果等级不高,不需要加锁 model := domain.CreateModelContext(s.svc.MyContext) mic, err := group_m.GetMic(model, groupUuid, i) if err != nil { return err } return mic.MgrMute(userId, externalId) } // 麦位解除静音 func (s *GroupMicService) GroupMicUnMute(userId uint64, externalId string, groupUuid string, i int) error { //后果等级不高,不需要加锁 model := domain.CreateModelContext(s.svc.MyContext) mic, err := group_m.GetMic(model, groupUuid, i) if err != nil { return err } return mic.MgrUnMute(userId, externalId) } //开启麦 func (s *GroupMicService) GroupMicSpeechOpen(userId uint64, externalId string, groupUuid string, i int) error { //自己/管理人开启禁麦,并发率不高,后果等级不高 model := domain.CreateModelContext(s.svc.MyContext) micUser, err := group_m.GetMicUser(model, groupUuid, i) if err != nil { return err } return micUser.SpeechOpen(userId, externalId) } //关闭麦 func (s *GroupMicService) GroupMicSpeechClose(userId uint64, externalId string, groupUuid, lang string, i int) error { model := domain.CreateModelContext(s.svc.MyContext) micUser, err := group_m.GetMicUser(model, groupUuid, i) if err != nil { return err } return micUser.SpeechClose(userId, externalId, lang) } //麦上的人群发消息 func (s *GroupMicService) GroupIMMassByInMic(groupId string, userId uint64, externalId string, content string) error { return s.svc.Transactional(func() error { model := domain.CreateModel(s.svc.CtxAndDb) micUser, err := group_m.GetMicUserByExternalId(model, externalId) if err != nil { return err } if err := micUser.ImMass(externalId); err != nil { return err } //校验群组ID if micUser.GroupUuid != groupId { return myerr.NewSysError("groupId 不一致, http:groupId <> micUser.groupId") } //获取群成员 gm, err := group_m.GetMembers(model.Db, groupId) if err != nil { return err } uids := make([]uint64, 0) for _, i := range gm { //排除自己 if userId != i.UserId { uids = append(uids, i.UserId) } } return group_ev.PublishGroupImMass(model, &group_ev.GroupImMassEvent{ GroupId: groupId, UserId: userId, Members: uids, Content: content, }) }) } // 群管理人群发消息 func (s *GroupMicService) GroupIMMassByMgr(groupId string, userId uint64, externalId string, content string) error { return s.svc.Transactional(func() error { model := domain.CreateModel(s.svc.CtxAndDb) //检查权限 if err := group_m.CheckPermission(model, groupId, userId); err != nil { return err } //获取群成员 gm, err := group_m.GetMembers(model.Db, groupId) if err != nil { return err } uids := make([]uint64, 0) for _, i := range gm { //排除自己 if userId != i.UserId { uids = append(uids, i.UserId) } } return group_ev.PublishGroupImMass(model, &group_ev.GroupImMassEvent{ GroupId: groupId, UserId: userId, Members: uids, Content: content, }) }) } // 增加势力上麦经验/时长 func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId uint64, joinMicTimestamp int64) error { var model = domain.CreateModelContext(s.svc.MyContext) exists, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, userId) if err != nil { return err } if !exists { return nil } // 获取势力下所有群组 groups, err := groupPower_m.GetGroupPowerGroups(model, groupPowerId) if err != nil { return err } inGroup := false for _, group := range groups { if group.ImGroupId == groupId { inGroup = true break } } if !inGroup { return nil } // 增加势力上麦经验 if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId, joinMicTimestamp); err != nil { model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err) } // 增加势力上麦时长-月 if err := groupPower_m.IncrGroupPowerStarOnMicMonth(model, groupPowerId, userId, joinMicTimestamp); err != nil { model.Log.Errorf("IncrGroupPowerStarOnMicMonth fail:%v", err) } // 增加势力上麦时长-天 if err := groupPower_m.IncrGroupPowerStarOnMicDay(model, groupPowerId, userId, joinMicTimestamp); err != nil { model.Log.Errorf("IncrGroupPowerStarOnMicDay fail:%v", err) } return nil } // 检查cp上麦 func (s *GroupMicService) CheckCpOnMic(groupUuid string) { model := domain.CreateModelContext(s.svc.MyContext) // 填充cp麦位 micNumType, err := group_m.GetMicNumType(model, groupUuid) if err != nil { return } _, micUsers, err := group_m.GetAllMic(groupUuid, micNumType) if err != nil { return } // userId->micIndex var userMicIndex = make(map[uint64]int) var userIds []uint64 forbidMap := make(map[uint64]bool) for _, u := range micUsers { userMicIndex[u.UserId] = u.I userIds = append(userIds, u.UserId) forbidMap[u.UserId] = u.Forbid } cpPairs, err := rpc.MGetUserCpPairs(model, userIds) // 更新麦上cp的信息 if err != nil { model.Log.Errorf("MGetUserCpPairs fail:%v", err) return } users, err := user_m.GetUserMapByIds(model, userIds) if err != nil { model.Log.Errorf("GetUserMapByIds fail:%v", err) return } for _, pairs := range cpPairs { level := pairs[2] if level < 5 { // cpLevel < 5 级别没有麦位特效 continue } userId := pairs[0] cpUserId := pairs[1] redisLock(redis_key.GetPrefixGroupMicUserInLock(userId), uuid.NewV4().String(), time.Second*2, func() error { model := domain.CreateModel(s.svc.CtxAndDb) mic, err := group_m.GetMic(model, groupUuid, userMicIndex[userId]) if err != nil { return err } return mic.Update(userId, users[userId].ExternalId, cpUserId, forbidMap[userId]) }) redisLock(redis_key.GetPrefixGroupMicUserInLock(cpUserId), uuid.NewV4().String(), time.Second*2, func() error { model := domain.CreateModel(s.svc.CtxAndDb) mic, err := group_m.GetMic(model, groupUuid, userMicIndex[cpUserId]) if err != nil { return err } return mic.Update(cpUserId, users[cpUserId].ExternalId, userId, forbidMap[cpUserId]) }) } return } // 检查cp下麦 func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) { model := domain.CreateModelContext(s.svc.MyContext) // 填充cp麦位 micNumType, err := group_m.GetMicNumType(model, groupUuid) if err != nil { return } _, micUsers, err := group_m.GetAllMic(groupUuid, micNumType) if err != nil { return } // userId->micIndex var userMicIndex = make(map[uint64]int) var cpUserId uint64 forbidMap := make(map[uint64]bool) for _, u := range micUsers { if u.UserId == leaveUid { cpUserId = u.CpUserId } userMicIndex[u.UserId] = u.I forbidMap[u.UserId] = u.Forbid } if cpUserId <= 0 { return } user, err := user_m.GetUser(model, cpUserId) if err != nil { model.Log.Errorf("GetUser fail:%v", err) return } redisLock(redis_key.GetPrefixGroupMicUserInLock(cpUserId), uuid.NewV4().String(), time.Second*2, func() error { model := domain.CreateModel(s.svc.CtxAndDb) mic, err := group_m.GetMic(model, groupUuid, userMicIndex[cpUserId]) if err != nil { return err } return mic.Update(cpUserId, user.ExternalId, 0, forbidMap[cpUserId]) }) return }