package contact import ( "errors" "regexp" "strings" ) var ( ErrInvalid = errors.New("联系人或通道信息不符合要求") ErrNotFound = errors.New("联系人或通道不存在") ErrConflict = errors.New("数据已被其他人员更新,请刷新后重试") phonePattern = regexp.MustCompile(`^\+?[0-9]{6,20}$`) ) type WriteInput struct { Name string `json:"name"` Role string `json:"role"` ExpectedVersion int `json:"expectedVersion"` } type ChannelInput struct { Kind string `json:"kind"` Address string `json:"address"` } func normalizeContact(input WriteInput) (WriteInput, error) { input.Name = strings.TrimSpace(input.Name) input.Role = strings.TrimSpace(input.Role) if input.Name == "" || len([]rune(input.Name)) > 128 || input.Role == "" || len([]rune(input.Role)) > 128 || hasControl(input.Name+input.Role) { return WriteInput{}, ErrInvalid } return input, nil } func normalizeChannel(input ChannelInput) (ChannelInput, error) { input.Kind = strings.ToLower(strings.TrimSpace(input.Kind)) input.Address = strings.ReplaceAll(strings.ReplaceAll(strings.TrimSpace(input.Address), " ", ""), "-", "") if (input.Kind != "sms" && input.Kind != "voice") || !phonePattern.MatchString(input.Address) { return ChannelInput{}, ErrInvalid } return input, nil } func maskAddress(value string) string { runes := []rune(value) if len(runes) <= 4 { return "****" } return strings.Repeat("*", min(8, len(runes)-4)) + string(runes[len(runes)-4:]) } func hasControl(value string) bool { for _, r := range value { if r < 32 || r == 127 { return true } } return false }