package group_m import ( "fmt" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/utils" "github.com/bluele/gcache" "gorm.io/gorm" "gorm.io/gorm/clause" "hilo-group/_const/enum/group_e" "hilo-group/myerr" "hilo-group/myerr/bizerr" "math/rand" "sort" "time" ) var ( FuncAddEditGroupCd func(model *domain.Model, imGroupId mysql.Str) error ) type GroupInfo struct { Id int64 ImGroupId string TxGroupId string Type uint16 Code string OriginCode string Owner uint64 Name string Introduction string Notification string FaceUrl string Country string ChannelId string Password string EntryLevel uint32 // obsolete MicOn bool LoadHistory bool ThemeId int16 MicNumType group_e.GroupMicNumType TouristMic uint8 // 游客是否能上麦1是2否 TouristSendMsg uint8 // 游客是否能发消息1是2否 TouristSendPic uint8 // 游客是否能发图片1是2否 MemberFee uint64 // 加入会员需要黄钻数 CreatedTime time.Time `gorm:"->"` UpdatedTime time.Time `gorm:"->"` VisitCount int64 `gorm:"-"` // 热度 } func GenerateGroupCode(n uint16) string { const numbers = "0123456789" b := make([]byte, n) for i := range b { if i == 0 { // 第一个数字不能为0 b[i] = numbers[1+rand.Int()%(len(numbers)-1)] } else { b[i] = numbers[rand.Int()%len(numbers)] } } return string(b) } func CreateGroup(model *domain.Model, groupInfo *GroupInfo) error { return model.Db.Create(groupInfo).Error } func FindGroupByOwner(model *domain.Model, ownerId uint64) ([]GroupInfo, error) { rows := make([]GroupInfo, 0) err := model.Db.Where(&GroupInfo{Owner: ownerId}).Find(&rows).Error if err != nil { return nil, err } return rows, nil } func FindGroupMapByOwner(model *domain.Model, ownerId uint64) (map[string]GroupInfo, error) { rows, err := FindGroupByOwner(model, ownerId) if err != nil { return nil, err } result := make(map[string]GroupInfo, 0) for _, i := range rows { result[i.ImGroupId] = i } return result, nil } func FindGroupByOwners(db *gorm.DB, ownerIds []uint64) (map[uint64]GroupInfo, error) { rows := make([]GroupInfo, 0) err := db.Model(&GroupInfo{}).Where("owner IN ?", ownerIds).Find(&rows).Error if err != nil { return nil, err } result := make(map[uint64]GroupInfo, 0) for _, i := range rows { result[i.Owner] = i } return result, nil } func UpdateCountryByOwner(model *domain.Model, country string, ownerId uint64) error { return model.Db.Model(&GroupInfo{}).Where(&GroupInfo{Owner: ownerId}).Update("country", country).Error } // fixme: 删除这个函数 func FindGroupByCode(model *domain.Model, code string) (*GroupInfo, error) { r := GroupInfo{} err := model.Db.Where(&GroupInfo{Code: code}).First(&r).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, nil } else { return nil, err } } return &r, nil } func FindGroupByCodes(db *gorm.DB, codes []string) (map[string]GroupInfo, error) { rows := make([]GroupInfo, 0) err := db.Where("code IN ?", codes).Find(&rows).Error if err != nil { return nil, err } result := make(map[string]GroupInfo, 0) for _, i := range rows { result[i.Code] = i } return result, nil } func GetGroupInfo(model *domain.Model, groupId string) (*GroupInfo, error) { if len(groupId) <= 0 { return nil, bizerr.GroupNotFound } r := GroupInfo{} err := model.Db.Where(&GroupInfo{ImGroupId: groupId}).First(&r).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, nil } else { return nil, err } } return &r, nil } func GetInfoByTxGroupId(model *domain.Model, txGroupId string) (*GroupInfo, error) { if len(txGroupId) <= 0 { return nil, bizerr.GroupNotFound } r := GroupInfo{} err := model.Db.Where(&GroupInfo{TxGroupId: txGroupId}).First(&r).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, nil } else { return nil, err } } return &r, nil } // 分几次获取 // 每次500只 func BatchGetGroupInfo(model *domain.Model, groupIds []string) (map[string]GroupInfo, error) { result := make(map[string]GroupInfo, 0) total := len(groupIds) if total <= 0 { return result, nil } const NUM = 500 start, end := 0, NUM for start < total { if end > total { end = total } tmpGroupId := groupIds[start:end] data := make([]GroupInfo, 0) if err := model.Db.Where("im_group_id IN ?", tmpGroupId).Find(&data).Error; err != nil { return result, err } for _, i := range data { result[i.ImGroupId] = i } start += NUM end += NUM } model.Log.Infof("BatchGetGroupInfo expected:%v,actual:%v", len(groupIds), len(result)) if len(groupIds) != len(result) { model.Log.Warnf("BatchGetGroupInfo expected:%v", groupIds) } return result, nil } func GetGroupByCode(model *domain.Model, code string) (*GroupInfo, error) { rows := make([]GroupInfo, 0) err := model.Db.Where(&GroupInfo{Code: code}).Find(&rows).Error if err != nil { return nil, err } if len(rows) > 0 { return &rows[0], nil } return nil, nil } func GetGroupByCodes(model *domain.Model, codes []string) (map[string]GroupInfo, error) { rows := make([]GroupInfo, 0) err := model.Db.Where("code in (?)", codes).Find(&rows).Error if err != nil { return nil, err } mapGroup := map[string]GroupInfo{} for i, _ := range rows { mapGroup[rows[i].Code] = rows[i] } return mapGroup, nil } func (g *GroupInfo) Update(model *domain.Model, imGroupId string, fields []string) *gorm.DB { return model.Db.Model(&GroupInfo{}).Where("im_group_id = ?", imGroupId).Select(fields).Updates(g) } func ResetGroupInfo(model *domain.Model, groupId string, code string) error { name := fmt.Sprintf(utils.DEFAULT_NICK, code) gi := GroupInfo{ Name: name, FaceUrl: "", Introduction: "", Notification: "", } if err := gi.Update(model, groupId, []string{"name", "face_url", "introduction", "notification"}).Error; err != nil { model.Log.Errorf("ResetGroupInfo fail:%v", err) return err } if err := RemoveWelcomeText(model.Db, groupId); err != nil { model.Log.Errorf("RemoveWelcomeText fail:%v", err) return err } // 编辑群组资料cd if err := FuncAddEditGroupCd(model, groupId); err != nil { model.Log.Warnf("AddEditGroupCd fail %s ", groupId) } return nil } // 设置群组头像 func SetFaceUrl(model *domain.Model, groupId, faceUrl string) error { gi := GroupInfo{ FaceUrl: faceUrl, } return gi.Update(model, groupId, []string{"face_url"}).Error } // 找到所有群 func (g *GroupInfo) FindAllGroups(db *gorm.DB) ([]GroupInfo, error) { result := make([]GroupInfo, 0) err := db.Where(g).Find(&result).Error return result, err } func FindNoPasswordGroups(model *domain.Model) ([]GroupInfo, error) { result := make([]GroupInfo, 0) err := model.Db.Where("password = ''").Find(&result).Error return result, err } func FindNoPasswordGroupsV2(model *domain.Model, imGroupIds []string) ([]GroupInfo, error) { result := make([]GroupInfo, 0) if len(imGroupIds) <= 0 { return result, nil } err := model.Db.Where("im_group_id in ? AND password = ''", imGroupIds).Find(&result).Error return result, err } func GetAllGroupIds(db *gorm.DB) ([]string, error) { result := make([]GroupInfo, 0) err := db.Find(&result).Error if err != nil { return nil, err } groupIds := make([]string, 0) for _, i := range result { groupIds = append(groupIds, i.ImGroupId) } return groupIds, err } var ownerCountryGroupCache = gcache.New(10000).LRU().Build() // 缓存15分钟 func FindOwnerCountryGroups(model *domain.Model, country string) ([]GroupInfo, error) { key := fmt.Sprintf("owner:country:group:%s", country) if data, err := ownerCountryGroupCache.Get(key); err == nil { model.Log.Infof("FindOwnerCountryGroups hit:%v", len(data.([]GroupInfo))) return data.([]GroupInfo), nil } result := make([]GroupInfo, 0) //err := model.Db.Model(&GroupInfo{}).Joins("left join user on user.id = owner").Where("user.country = ?", country).Where("password = ''").Find(&result).Error err := model.Db.Model(&GroupInfo{}).Where(&GroupInfo{ Country: country, }).Find(&result).Error _ = ownerCountryGroupCache.SetWithExpire(key, result, time.Minute*15) return result, err } //过滤被封禁的群或者有密码的群 func FilterGroupBannedOrPassword(groupIds []string) (map[string]struct{}, error) { type result struct { ImGroupId string } results := []result{} if err := mysql.Db.Model(&GroupInfo{}).Select("im_group_id").Where("im_group_id in (?)", groupIds).Where("password = ''").Where("not EXISTS (SELECT 1 from group_banned b where b.im_group_id = group_info.im_group_id) ").Scan(&results).Error; err != nil { return nil, myerr.WrapErr(err) } imGroupIdSet := map[string]struct{}{} for i := 0; i < len(results); i++ { imGroupIdSet[results[i].ImGroupId] = struct{}{} } return imGroupIdSet, nil } func GetGroupImGroupIdByDbId(model *domain.Model, dbId uint64) (string, error) { r := GroupInfo{} //err := model.Db.Model(&GroupInfo{}).First(&r, dbId).Error //if err != nil { // return "", myerr.WrapErr(err) //} if err := model.Db.Raw("SELECT id, im_group_id from group_info i where i.id = ?", dbId).First(&r).Error; err != nil { return "", myerr.WrapErr(err) } return r.ImGroupId, nil } func GetGroupInfoByDbIds(model *domain.Model, dbIds []uint64) (map[mysql.ID]GroupInfo, error) { type result struct { Id uint64 GroupInfo } rs := []result{} if err := model.Db.Raw("SELECT * from group_info i where i.id in (?)", dbIds).Scan(&rs).Error; err != nil { return nil, myerr.WrapErr(err) } imGroupMap := map[mysql.ID]GroupInfo{} for i, _ := range rs { imGroupMap[rs[i].Id] = rs[i].GroupInfo } return imGroupMap, nil } func GetGroupCodeByDbId(model *domain.Model, dbId uint64) (string, error) { type result struct { Code string } r := result{} if err := model.Db.Raw("SELECT code from group_info i where i.id = ?", dbId).First(&r).Error; err != nil { return "", myerr.WrapErr(err) } return r.Code, nil } func GetGroupCodeByDbIds(model *domain.Model, dbIds []uint64) (map[mysql.ID]string, error) { type result struct { Id uint64 Code string } rs := []result{} if err := model.Db.Raw("SELECT id, code from group_info i where i.id in (?)", dbIds).Scan(&rs).Error; err != nil { return nil, myerr.WrapErr(err) } imGroupMap := map[mysql.ID]string{} for i, _ := range rs { imGroupMap[rs[i].Id] = rs[i].Code } return imGroupMap, nil } func GetGroupOwnerByDbIds(model *domain.Model, dbIds []uint64) (map[mysql.ID]mysql.ID, error) { type result struct { Id uint64 Owner uint64 } rs := []result{} if err := model.Db.Raw("SELECT owner, id from group_info i where i.id in (?)", dbIds).Scan(&rs).Error; err != nil { return nil, myerr.WrapErr(err) } imGroupMap := map[mysql.ID]mysql.ID{} for i, _ := range rs { imGroupMap[rs[i].Id] = rs[i].Owner } return imGroupMap, nil } func GetGroupIdByDbIds(model *domain.Model, dbIds []uint64) (map[mysql.ID]string, error) { type result struct { Id uint64 ImGroupId string } rs := []result{} if err := model.Db.Raw("SELECT id, im_group_id from group_info i where i.id in (?)", dbIds).Scan(&rs).Error; err != nil { return nil, myerr.WrapErr(err) } imGroupMap := map[mysql.ID]string{} for i, _ := range rs { imGroupMap[rs[i].Id] = rs[i].ImGroupId } return imGroupMap, nil } func GetGroupDbIdByOwner(model *domain.Model, ownerId uint64) (uint64, error) { type result struct { Id uint64 } results := []result{} if err := model.Db.Raw("SELECT i.id from group_info i where i.owner = ?", ownerId).Scan(&results).Error; err != nil { return 0, myerr.WrapErr(err) } if len(results) == 0 { return 0, nil } return results[0].Id, nil } func GetGroupInfoByOwner(model *domain.Model, ownerId uint64) (*GroupInfo, error) { rows := make([]*GroupInfo, 0) err := model.Db.Where("owner = ?", ownerId).Find(&rows).Error if err != nil { return nil, err } if len(rows) == 0 { return nil, nil } return rows[0], nil } func GetGroupDbIdByCode(model *domain.Model, code string) (uint64, error) { type result struct { Id uint64 } results := []result{} if err := model.Db.Raw("SELECT i.id from group_info i where i.code = ?", code).Scan(&results).Error; err != nil { return 0, myerr.WrapErr(err) } if len(results) == 0 { return 0, nil } return results[0].Id, nil } func GetGroupDbIdByCodes(model *domain.Model, codes []string) (map[string]uint64, error) { type result struct { Id uint64 Code string } results := []result{} if err := model.Db.Raw("SELECT i.id, i.code from group_info i where i.code in (?)", codes).Scan(&results).Error; err != nil { return nil, myerr.WrapErr(err) } if len(results) == 0 { return nil, nil } rs := map[string]uint64{} for i, _ := range results { rs[results[i].Code] = results[i].Id } return rs, nil } //获取数据库的ID,特殊用途 func GetGroupDbId(model *domain.Model, imGroupId string) (mysql.ID, error) { type result struct { Id uint64 } results := []result{} if err := model.Db.Raw("SELECT i.id from group_info i where i.im_group_id = ?", imGroupId).Scan(&results).Error; err != nil { return 0, myerr.WrapErr(err) } if len(results) == 0 { return 0, bizerr.GroupNotFound } return results[0].Id, nil } var officialGroup []string func IsOfficialGroup(groupId string) bool { for _, i := range officialGroup { if i == groupId { return true } } return false } func GetLatestGroupInfos(model *domain.Model, limit, lastId int, groupIds []string) (res []*GroupInfo, err error) { if len(groupIds) <= 0 { return nil, nil } res = make([]*GroupInfo, 0) query := model.Db.Debug().Model(GroupInfo{}).Where("im_group_id IN ?", groupIds) if lastId > 0 { query.Where("id < ?", lastId) } err = query.Order("id DESC").Limit(limit).Find(&res).Error return } func GetFamilyRooms(model *domain.Model, familyId uint64, pageSize, pageIndex int) (res []*GroupInfo, nextIdx int, hasNext bool, err error) { allImGroupIds := make([]string, 0) var count int64 err = model.Db.Model(GroupInfo{}).Select("im_group_id").Where("owner in (select user_id from group_power_user where group_power_id=?)", familyId).Pluck("im_group_id", &allImGroupIds).Count(&count).Error if err != nil { return nil, 0, false, err } // 房间热度排序 visitCountMap, visitCountList, err := BatchGetRoomVisitCountList(model.Log, allImGroupIds) if err != nil { return nil, 0, false, err } roomNum := len(visitCountList) if roomNum > pageIndex { endIndex := pageIndex + pageSize if roomNum >= endIndex { visitCountList = visitCountList[pageIndex : pageIndex+pageSize] if roomNum > endIndex { nextIdx = endIndex hasNext = true } } else { visitCountList = visitCountList[pageIndex:] } } else { return nil, 0, false, err } showImGroupIdList := make([]string, 0, len(visitCountList)) for _, v := range visitCountList { showImGroupIdList = append(showImGroupIdList, v.ImGroupId) } res = make([]*GroupInfo, 0) err = model.Db.Model(GroupInfo{}).Where("im_group_id in ?", showImGroupIdList).Find(&res).Error if err != nil { return nil, 0, false, err } for i, v := range res { if c, ok := visitCountMap[v.ImGroupId]; ok { res[i].VisitCount = c } } sort.Slice(res, func(i, j int) bool { return res[i].VisitCount > res[j].VisitCount }) return res, nextIdx, hasNext, nil } func IsUseTRTC(model *domain.Model, imGroupId string) bool { var count int64 if err := model.DB().Table("group_trtc").Where("im_group_id=?", imGroupId).Count(&count).Error; err != nil { model.Log.Errorf("IsUseTRTC err:%v, groupId:%s", err, imGroupId) return false } return count > 0 } type GroupTrtc struct { mysql.Entity ImGroupId mysql.Str } // 初始化trtc房间 func InitTRTC(model *domain.Model, imGroupId string) error { if err := model.DB().Model(GroupTrtc{}).Clauses(clause.OnConflict{DoNothing: true}).Create(&GroupTrtc{ImGroupId: imGroupId}).Error; err != nil { model.Log.Errorf("InitTRTC err:%v, groupId:%s", err, imGroupId) return err } return nil }