package chat import ( "context" "regexp" "strconv" "strings" "git.imall.cloud/openim/chat/pkg/common/db/dbutil" table "git.imall.cloud/openim/chat/pkg/common/db/table/chat" "git.imall.cloud/openim/chat/pkg/eerrs" "git.imall.cloud/openim/chat/pkg/protocol/chat" "git.imall.cloud/openim/chat/pkg/protocol/common" "github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/stringutil" ) func DbToPbAttribute(attribute *table.Attribute) *common.UserPublicInfo { if attribute == nil { return nil } return &common.UserPublicInfo{ UserID: attribute.UserID, Account: attribute.Account, Email: attribute.Email, Nickname: attribute.Nickname, FaceURL: attribute.FaceURL, Gender: attribute.Gender, Level: attribute.Level, UserType: attribute.UserType, } } func DbToPbAttributes(attributes []*table.Attribute) []*common.UserPublicInfo { return datautil.Slice(attributes, DbToPbAttribute) } func DbToPbUserFullInfo(attribute *table.Attribute) *common.UserFullInfo { return &common.UserFullInfo{ UserID: attribute.UserID, Password: "", Account: attribute.Account, PhoneNumber: attribute.PhoneNumber, AreaCode: attribute.AreaCode, Email: attribute.Email, Nickname: attribute.Nickname, FaceURL: attribute.FaceURL, Gender: attribute.Gender, Level: attribute.Level, UserType: attribute.UserType, Birth: attribute.BirthTime.UnixMilli(), AllowAddFriend: attribute.AllowAddFriend, AllowBeep: attribute.AllowBeep, AllowVibration: attribute.AllowVibration, GlobalRecvMsgOpt: attribute.GlobalRecvMsgOpt, RegisterType: attribute.RegisterType, UserFlag: attribute.UserFlag, CreateTime: attribute.CreateTime.UnixMilli(), Ip: "", // 默认空字符串 } } func DbToPbUserFullInfos(attributes []*table.Attribute) []*common.UserFullInfo { return datautil.Slice(attributes, DbToPbUserFullInfo) } func DbToPbUserFullInfoWithIP(attribute *table.Attribute, ip string) *common.UserFullInfo { return &common.UserFullInfo{ UserID: attribute.UserID, Password: "", Account: attribute.Account, PhoneNumber: attribute.PhoneNumber, AreaCode: attribute.AreaCode, Email: attribute.Email, Nickname: attribute.Nickname, FaceURL: attribute.FaceURL, Gender: attribute.Gender, Level: attribute.Level, UserType: attribute.UserType, Birth: attribute.BirthTime.UnixMilli(), AllowAddFriend: attribute.AllowAddFriend, AllowBeep: attribute.AllowBeep, AllowVibration: attribute.AllowVibration, GlobalRecvMsgOpt: attribute.GlobalRecvMsgOpt, RegisterType: attribute.RegisterType, UserFlag: attribute.UserFlag, CreateTime: attribute.CreateTime.UnixMilli(), Ip: ip, } } func DbToPbUserFullInfosWithIP(attributes []*table.Attribute, userIPMap map[string]string) []*common.UserFullInfo { result := make([]*common.UserFullInfo, 0, len(attributes)) for _, attr := range attributes { ip := userIPMap[attr.UserID] result = append(result, DbToPbUserFullInfoWithIP(attr, ip)) } return result } // DbToPbUserFullInfosWithRealNameAuth 转换用户信息(包含实名认证信息) func DbToPbUserFullInfosWithRealNameAuth(attributes []*table.Attribute, walletMap map[string]*table.Wallet) []*common.UserFullInfo { result := make([]*common.UserFullInfo, 0, len(attributes)) for _, attr := range attributes { userInfo := DbToPbUserFullInfo(attr) // 填充实名认证信息 if wallet, ok := walletMap[attr.UserID]; ok { userInfo.IdCard = wallet.RealNameAuth.IDCard userInfo.RealName = wallet.RealNameAuth.Name userInfo.IdCardPhotoFront = wallet.RealNameAuth.IDCardPhotoFront userInfo.IdCardPhotoBack = wallet.RealNameAuth.IDCardPhotoBack userInfo.AuditStatus = wallet.RealNameAuth.AuditStatus } result = append(result, userInfo) } return result } // DbToPbUserFullInfosWithRealNameAuthAndIP 转换用户信息(包含实名认证信息和IP) func DbToPbUserFullInfosWithRealNameAuthAndIP(attributes []*table.Attribute, walletMap map[string]*table.Wallet, userIPMap map[string]string) []*common.UserFullInfo { result := make([]*common.UserFullInfo, 0, len(attributes)) for _, attr := range attributes { ip := userIPMap[attr.UserID] userInfo := DbToPbUserFullInfoWithIP(attr, ip) // 填充实名认证信息 if wallet, ok := walletMap[attr.UserID]; ok { userInfo.IdCard = wallet.RealNameAuth.IDCard userInfo.RealName = wallet.RealNameAuth.Name userInfo.IdCardPhotoFront = wallet.RealNameAuth.IDCardPhotoFront userInfo.IdCardPhotoBack = wallet.RealNameAuth.IDCardPhotoBack userInfo.AuditStatus = wallet.RealNameAuth.AuditStatus } result = append(result, userInfo) } return result } func BuildCredentialPhone(areaCode, phone string) string { return areaCode + " " + phone } func (o *chatSvr) checkRegisterInfo(ctx context.Context, user *chat.RegisterUserInfo, isAdmin bool) error { if user == nil { return errs.ErrArgs.WrapMsg("user is nil") } user.Account = strings.TrimSpace(user.Account) // 如果提供了account,则不需要验证phone和email if user.Account != "" { // account验证逻辑在后面,这里直接跳过"至少需要一个账号"的检查 } else if user.Email == "" && !(user.PhoneNumber != "" && user.AreaCode != "") && !isAdmin { // 如果没有account,也没有email,也没有完整的phone(phoneNumber和areaCode都提供),且不是管理员,则报错 return errs.ErrArgs.WrapMsg("at least one valid account is required") } if user.PhoneNumber != "" { if !strings.HasPrefix(user.AreaCode, "+") { user.AreaCode = "+" + user.AreaCode } if _, err := strconv.ParseUint(user.AreaCode[1:], 10, 64); err != nil { return errs.ErrArgs.WrapMsg("area code must be number") } if _, err := strconv.ParseUint(user.PhoneNumber, 10, 64); err != nil { return errs.ErrArgs.WrapMsg("phone number must be number") } _, err := o.Database.TakeAttributeByPhone(ctx, user.AreaCode, user.PhoneNumber) if err == nil { return eerrs.ErrPhoneAlreadyRegister.Wrap() } else if !dbutil.IsDBNotFound(err) { return err } } if user.Account != "" { // 验证长度:6到20位 if len(user.Account) < 6 || len(user.Account) > 20 { return errs.ErrArgs.WrapMsg("account must be between 6 and 20 characters") } // 验证格式:只能包含数字、字母、下划线(_)、横线(-) pattern := `^[a-zA-Z0-9_-]+$` matched, err := regexp.MatchString(pattern, user.Account) if err != nil || !matched { return errs.ErrArgs.WrapMsg("account must contain only letters, numbers, underscores, and hyphens") } _, err = o.Database.TakeAttributeByAccount(ctx, user.Account) if err == nil { return eerrs.ErrAccountAlreadyRegister.Wrap() } else if !dbutil.IsDBNotFound(err) { return err } } if user.Email != "" { if !stringutil.IsValidEmail(user.Email) { return errs.ErrArgs.WrapMsg("invalid email") } _, err := o.Database.TakeAttributeByAccount(ctx, user.Email) if err == nil { return eerrs.ErrEmailAlreadyRegister.Wrap() } else if !dbutil.IsDBNotFound(err) { return err } } return nil }