package group_cv import ( "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/utils" "hilo-group/_const/enum/game_e" "hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/group_e" "hilo-group/_const/enum/online_e" "hilo-group/cv/billboard_cv" "hilo-group/cv/group_power_cv" "hilo-group/cv/medal_cv" "hilo-group/cv/user_cv" "hilo-group/domain/cache/res_c" "hilo-group/domain/cache/room_c" "hilo-group/domain/model/game_m" "hilo-group/domain/model/group_m" "hilo-group/domain/model/res_m" "hilo-group/domain/model/rocket_m" "hilo-group/domain/service/group_s" "hilo-group/myerr" "sort" ) type GroupBasicInfo struct { Id int64 `json:"id,omitempty"` GroupId string `json:"groupId"` Name string `json:"name"` Introduction string `json:"introduction"` Notification string `json:"notification"` FaceUrl string `json:"faceUrl"` Owner_Account string `json:"ownerAccount"` CreateTime int `json:"createTime"` //LastInfoTime int `json:"last_info_time"` LastMsgTime int `json:"lastMsgTime"` NextMsgSeq uint `json:"nextMsgSeq"` MemberNum uint `json:"memberNum"` MaxMemberNum uint `json:"maxMemberNum"` ShutUpAllMember string `json:"shutUpAllMember"` Code string `json:"code"` Password *string `json:"password"` CountryIcon string `json:"countryIcon"` SupportLevel uint8 `json:"supportLevel"` // 本周最高的扶持等级 //1:5人 2:10人 MicNumType int `json:"micNumType"` // N天内的进入用户数量(重复进入去重,实时) GroupInUserDuration int64 `json:"groupInUserDuration"` // 群热度 GroupMedals []medal_cv.PicElement `json:"groupMedals"` // 群勋章 TouristMic uint8 `json:"touristMic"` // 游客是否能上麦 TouristSendMsg uint8 `json:"touristSendMsg"` // 游客是否能发言 TouristSendPic uint8 `json:"touristSendPic"` // 游客是否能发图片 MemberFee uint64 `json:"memberFee"` // 加入群组会员需要的黄钻 } type MemberListInfo struct { Member_Account string `json:"memberAccount"` JoinTime int `json:"joinTime"` //MsgSeq uint `json:"msg_seq"` LastSendMsgTime int64 `json:"lastSendMsgTime"` //ShutUpUntil int `json:"shut_up_until"` // AppMemberDefinedData": [ // 群成员自定义字段 【暂时不用】 } type GroupPower struct { Id uint64 `json:"id"` // 群主所在的势力ID Name string `json:"name"` // 群主所在的势力的名称 Nameplate string `json:"nameplate"` // 势力铭牌 Grade groupPower_e.GroupPowerGrade `json:"grade"` // 等级 } type GroupInfo struct { GroupBasicInfo // hilo业务 EntryLevel uint32 `json:"entryLevel"` // obsolete HasOnMic bool `json:"hasOnMic"` // 房间麦上是否有人 GroupPowerId uint64 `json:"groupPowerId"` // 群主所在的势力ID GroupPowerName string `json:"groupPowerName"` // 群主所在的势力的名称 GroupPowerNameplate string `json:"groupPowerNameplate"` // 势力铭牌 GroupPower GroupPower `json:"groupPower"` // 势力信息 // "AppDefinedData": 群组维度的自定义字段 【暂时不用】 MemberList []MemberListInfo } type PopularGroupInfo struct { GroupInfo MicUsers []user_cv.CvUserTiny `json:"micUsers"` // 在麦上的用户,最多4个 RoomUserCount uint `json:"roomUserCount"` // 当前在房间的用户数 MaxStage *uint16 `json:"maxStage"` // 今天爆过的最大的火箭 GameTypes []game_e.GameType `json:"gameTypes,omitempty"` // 房间内正在进行的游戏 1:ludo 2:uno } // 最新的群组列表, 字段暂时应该跟popular一样 type LatestGroupInfo PopularGroupInfo type TheirGroupsInfo struct { Total uint `json:"total"` OwnGroups []JoinedGroupInfo `json:"ownGroups"` Groups []JoinedGroupInfo `json:"groups"` } type JoinedGroupInfo struct { PopularGroupInfo LastEnterTime int64 `json:"lastEnterTime"` // 最后一次进房间的时间 } type JoinedGroupRsp struct { Total uint `json:"total"` Groups []JoinedGroupInfo `json:"groups"` } type RoleMemberInfo struct { user_cv.CvUserBase Role group_e.GroupRoleType `json:"role"` OnlineStatus online_e.OnlineStatusType `json:"onlineStatus"` } type MemberDetail struct { user_cv.CvUserExtend Role group_e.GroupRoleType `json:"role"` OnlineStatus online_e.OnlineStatusType `json:"onlineStatus"` // IM在线状态 InRoom bool `json:"inRoom"` // 是否在房间内 } type GroupDetail struct { GroupBasicInfo // hilo业务 EntryLevel uint32 `json:"entryLevel"` // obsolete MicOn bool `json:"micOn"` LoadHistory bool `json:"loadHistory"` ThemeId uint64 `json:"themeId"` ThemeUrl string `json:"themeUrl"` // 1:官方 2:自定义 ThemeType uint8 `json:"themeType"` Role group_e.GroupRoleType `json:"role"` MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态 WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语 TotalConsume uint64 `json:"totalConsume"` // 群内消费总额 TopConsumers []billboard_cv.BillboardUserInfo `json:"topConsumers"` // 月最高消费三甲 DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量 DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数 // "AppDefinedData": 群组维度的自定义字段 【暂时不用】 RoleMembers []RoleMemberInfo `json:"role_members"` Owner *user_cv.CvUserDetail `json:"owner"` // 群主信息 } type SimpleRoleInfo struct { ExternalId string `json:"externalId"` Role group_e.GroupRoleType `json:"role"` } type BannerElement struct { H5Url string `json:"h5Url"` // h5链接 BannerUrl string `json:"bannerUrl"` // 图片地址 } type RoomInfo struct { GroupBasicInfo // hilo业务 MicOn bool `json:"micOn"` LoadHistory bool `json:"loadHistory"` ThemeId uint64 `json:"themeId"` ThemeUrl string `json:"themeUrl"` // 1:官方 2:自定义 ThemeType uint8 `json:"themeType"` Role group_e.GroupRoleType `json:"role"` DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量 DiceType uint16 `json:"diceType"` // 骰子游戏类型 RoleMembers []SimpleRoleInfo `json:"roleMembers"` WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语 Banners []BannerElement `json:"banners"` LuckyWheel LuckyWheelState `json:"luckyWheel"` TotalConsume uint64 `json:"totalConsume"` GameConfig *game_m.GameConfig `json:"gameConfig"` Owner *user_cv.CvUserDetail `json:"owner"` } type SupportPageDetail struct { GroupId string `json:"groupId"` CurrentConsume uint64 `json:"currentConsume"` // 当前周期的消费额(钻石) CurrentCount uint32 `json:"currentCount"` // 当前周期的消费人数 LastConsume uint64 `json:"lastConsume"` // 上一个周期的消费额(钻石) LastCount uint32 `json:"lastCount"` // 上一个周期的消费人数 SupportLevel string `json:"supportLevel"` // 上一个周期(已结算)的支持等级 SupporterLimit uint32 `json:"supporterLimit"` // 上一个周期(已结算)的支持者的上限 CurrentSupportLevel string `json:"currentSupportLevel"` // 当前的支持等级 RemainSecond int64 `json:"remainSecond"` // 离下一次结算还有多少秒 ProfitAllocator user_cv.CvUserBase `json:"profitAllocator"` // 利益分配人,群主或由运营指定(官方群) Supporters []user_cv.CvUserBase `json:"supporters"` // 扶持管理员 IsDispatched bool `json:"isDispatched"` // 奖励是否已经分配 } type AwardResult struct { Success []string `json:"success"` Failed []string `json:"failed"` } type GroupPowerTitle struct { Id uint64 `json:"id"` Name string `json:"name"` GroupId string `json:"groupId"` // 势力的主群 Avatar string `json:"avatar"` MemberNum uint `json:"memberNum"` // 成员人数 Owner user_cv.CvUserBase `json:"owner"` // 势力主 Assistants []user_cv.CvUserBase `json:"assistants"` // 势力助手,目前就是主群的管理 IsMyGroupPower bool `json:"isMyGroupPower"` // “我”是否属于这个势力 } type RoomMedalInfo struct { Level uint16 `json:"level"` PreviewUrl string `json:"previewUrl"` PicUrl string `json:"picUrl"` Desc string `json:"desc"` } type GroupChannelId struct { ChannelId string `json:"channelId"` Token string `json:"token"` AgoraId uint32 `json:"agoraId"` MicNumType uint8 `json:"micNumType"` Provider uint8 `json:"provider"` // 供应商 1.声网 2.腾讯trtc } //国籍视图 type CvCountry struct { //名字 Name *string `json:"name"` //缩写 ShortName *string `json:"shortName"` //图标地址 Icon *string `json:"icon"` //code Code *string `json:"code"` // 手机区号 AreaCode *string `json:"areaCode"` //手机号国家域名缩写 AreaCodeName *string `json:"areaShortName"` } func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds []string, pageSize, pageIndex int) ([]JoinedGroupInfo, int, error) { model := domain.CreateModel(myService.CtxAndDb) groupInfo, err := group_m.BatchGetGroupInfo(model, groupIds) if err != nil { return nil, 0, err } // todo: 可以移到后面,减小查询范围,因为roomMicUserMap不影响排序 roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds) if err != nil { return nil, 0, err } uids := make([]uint64, 0) micUsersMap := make(map[string][]uint64, 0) for _, i := range groupInfo { micUsersMap[i.ImGroupId] = make([]uint64, 0) if len(i.Password) <= 0 { // 密码群不显示麦上头像 u := roomMicUserMap[i.ImGroupId] if len(u) >= 4 { micUsersMap[i.ImGroupId] = u[0:4] } else if len(u) > 0 { micUsersMap[i.ImGroupId] = u } uids = append(uids, micUsersMap[i.ImGroupId]...) } } uids = utils.UniqueSliceUInt64(uids) userTiny, err := user_cv.GetUserTinyMap(uids) if err != nil { return nil, 0, err } roomCount, err := group_m.BatchGetRoomCount(model, groupIds) if err != nil { return nil, 0, err } countryInfo, err := res_c.GetCountryIconMap(model) if err != nil { return nil, 0, err } supportLevels, err := group_s.NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap() if err != nil { return nil, 0, err } visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds) if err != nil { return nil, 0, err } roomEnterTime, err := room_c.GetUserRoomVisit(myUserId) if err != nil { return nil, 0, err } model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime) // 排序优先级V8.0版本 sort.Slice(groupIds, func(i, j int) bool { gi := groupIds[i] gj := groupIds[j] return roomEnterTime[gi] > roomEnterTime[gj] || roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] > visitCount[gj] || roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] == visitCount[gj] && i >= j }) result := make([]JoinedGroupInfo, 0) beginPos := pageSize * (pageIndex - 1) endPos := pageSize * pageIndex if beginPos < len(groupIds) { if endPos > len(groupIds) { endPos = len(groupIds) } groupIds = groupIds[beginPos:endPos] owners := make([]uint64, 0) for _, i := range groupIds { owners = append(owners, groupInfo[i].Owner) } powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return nil, 0, err } groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds) if err != nil { return nil, 0, err } resMedal, err := res_m.MedalGetAllMap(model.Db) if err != nil { return nil, 0, err } rr := rocket_m.RocketResult{} maxStageMap, err := rr.GetMaxStage(model.Db, groupIds) if err != nil { return nil, 0, err } // 正在进行的游戏 games := game_m.GetNotEndGamesMap(model) for _, i := range groupIds { g := groupInfo[i] micUsers := make([]user_cv.CvUserTiny, 0) for _, j := range micUsersMap[i] { micUsers = append(micUsers, userTiny[j]) } var maxStage *uint16 = nil if s, ok := maxStageMap[i]; ok { maxStage = &s } medals := make([]medal_cv.PicElement, 0) // 补上房间流水勋章 var pe *medal_cv.PicElement _, pe, err = medal_cv.GetGroupConsumeMedal(model, i) if err != nil { model.Log.Infof("BuildJoinedGroupInfo: GetGroupConsumeMedal: %s", err.Error()) } else if pe != nil { medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl}) } // res_medal if m, ok := groupMedals[i]; ok { for _, j := range m { mId := uint32(j) if e, ok := resMedal[mId]; ok { medals = append(medals, medal_cv.PicElement{ PicUrl: e.PicUrl, }) } } } var password *string = nil if len(g.Password) > 0 && g.Owner != myUserId { emptyStr := "" password = &emptyStr } result = append(result, JoinedGroupInfo{ PopularGroupInfo: PopularGroupInfo{ GroupInfo: GroupInfo{ GroupBasicInfo: GroupBasicInfo{ GroupId: g.TxGroupId, Name: g.Name, Notification: g.Notification, Introduction: g.Introduction, FaceUrl: g.FaceUrl, Code: g.Code, CountryIcon: countryInfo[g.Country], Password: password, SupportLevel: supportLevels[i], GroupInUserDuration: visitCount[i], MicNumType: int(g.MicNumType), GroupMedals: medals, }, HasOnMic: len(micUsers) > 0, GroupPowerId: powerIds[g.Owner], GroupPowerName: powerNames[g.Owner], GroupPowerNameplate: powerNameplates[g.Owner], GroupPower: GroupPower{ Id: powerIds[g.Owner], Name: powerNames[g.Owner], Nameplate: powerNameplates[g.Owner], Grade: powerGrades[g.Owner], }, }, MicUsers: micUsers, RoomUserCount: uint(roomCount[i]), MaxStage: maxStage, GameTypes: games[g.TxGroupId], }, LastEnterTime: roomEnterTime[i], }) } } return result, len(groupInfo), nil } func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*group_m.GroupInfo) ([]*PopularGroupInfo, error) { groupIds := make([]string, 0, len(groupInfo)) for _, v := range groupInfo { groupIds = append(groupIds, v.ImGroupId) } // roomMicUserMap不影响排序 roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds) if err != nil { return nil, err } uids := make([]uint64, 0) micUsersMap := make(map[string][]uint64, 0) for _, v := range groupInfo { micUsersMap[v.ImGroupId] = make([]uint64, 0) if len(v.Password) <= 0 { // 密码群不显示麦上头像 u := roomMicUserMap[v.ImGroupId] if len(u) >= 4 { micUsersMap[v.ImGroupId] = u[0:4] } else if len(u) > 0 { micUsersMap[v.ImGroupId] = u } uids = append(uids, micUsersMap[v.ImGroupId]...) } } uids = utils.UniqueSliceUInt64(uids) userTiny, err := user_cv.GetUserTinyMap(uids) if err != nil { return nil, err } roomCount, err := group_m.BatchGetRoomCount(model, groupIds) if err != nil { return nil, err } countryInfo, err := res_c.GetCountryIconMap(model) if err != nil { return nil, err } supportLevels, err := group_s.NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap() if err != nil { return nil, err } visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds) if err != nil { return nil, err } roomEnterTime, err := room_c.GetUserRoomVisit(myUserId) if err != nil { return nil, err } model.Log.Infof("BuildPopularGroupInfo, roomEnterTime: %v", roomEnterTime) // 排序优先级V8.0版本 //sort.Slice(groupIds, func(i, j int) bool { // gi := groupIds[i] // gj := groupIds[j] // return roomEnterTime[gi] > roomEnterTime[gj] || // roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] > visitCount[gj] || // roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] == visitCount[gj] && i >= j //}) sort.Slice(groupIds, func(i, j int) bool { gj := groupIds[j] return visitCount[gj] > visitCount[gj] }) result := make([]*PopularGroupInfo, 0) owners := make([]uint64, 0) for _, v := range groupInfo { owners = append(owners, v.Owner) } powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return nil, err } groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds) if err != nil { return nil, err } resMedal, err := res_m.MedalGetAllMap(model.Db) if err != nil { return nil, err } rr := rocket_m.RocketResult{} maxStageMap, err := rr.GetMaxStage(model.Db, groupIds) if err != nil { return nil, err } // 正在进行的游戏 games := game_m.GetNotEndGamesMap(model) for _, v := range groupInfo { g := v i := v.ImGroupId micUsers := make([]user_cv.CvUserTiny, 0) for _, j := range micUsersMap[i] { micUsers = append(micUsers, userTiny[j]) } var maxStage *uint16 = nil if s, ok := maxStageMap[i]; ok { maxStage = &s } medals := make([]medal_cv.PicElement, 0) if m, ok := groupMedals[i]; ok { for _, j := range m { mId := uint32(j) if e, ok := resMedal[mId]; ok { medals = append(medals, medal_cv.PicElement{ PicUrl: e.PicUrl, }) } } } // 补上房间流水勋章 var pe *medal_cv.PicElement _, pe, err = medal_cv.GetGroupConsumeMedal(model, i) if err != nil { model.Log.Infof("BuildPopularGroupInfo: GetGroupConsumeMedal: %s", err.Error()) } else if pe != nil { medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl}) } var password *string = nil if len(g.Password) > 0 && g.Owner != myUserId { emptyStr := "" password = &emptyStr } result = append(result, &PopularGroupInfo{ GroupInfo: GroupInfo{ GroupBasicInfo: GroupBasicInfo{ GroupId: g.TxGroupId, Name: g.Name, Notification: g.Notification, Introduction: g.Introduction, FaceUrl: g.FaceUrl, Code: g.Code, CountryIcon: countryInfo[g.Country], Password: password, SupportLevel: supportLevels[i], GroupInUserDuration: visitCount[i], MicNumType: int(g.MicNumType), GroupMedals: medals, }, HasOnMic: len(micUsers) > 0, GroupPowerId: powerIds[g.Owner], GroupPowerName: powerNames[g.Owner], GroupPowerNameplate: powerNameplates[g.Owner], GroupPower: GroupPower{ Id: powerIds[g.Owner], Name: powerNames[g.Owner], Nameplate: powerNameplates[g.Owner], Grade: powerGrades[g.Owner], }, }, MicUsers: micUsers, RoomUserCount: uint(roomCount[i]), MaxStage: maxStage, GameTypes: games[g.TxGroupId], }) } return result, nil } //检查群组中是否有有人在麦上,返回存在的Set[imGroupId] func CheckMicHasUserByGroup(groupIds []string) (map[string]struct{}, error) { groupMap := map[string]struct{}{} for i := 0; i < len(groupIds); i++ { flag, err := group_m.CheckGroupMicHasUser(groupIds[i]) if err != nil { return nil, myerr.WrapErr(err) } if flag { groupMap[groupIds[i]] = struct{}{} } } return groupMap, nil }