package team_service import ( "bytes" "encoding/json" "errors" "net/mail" "strconv" "strings" "unicode/utf8" ) var ( ErrInvalidCaptainEmail = errors.New("укажите корректную почту капитана") ErrTeamNotFound = errors.New("команда не найдена") ErrInvalidRegistration = errors.New("укажите название команды (до 255 символов), почту капитана и положительное количество участников") ErrRegistrationClosed = errors.New("игра не найдена или регистрация уже закрыта") ) // Registration contains data required to register a team. type Registration struct { Name string `json:"name"` Email string `json:"email"` ParticipantsCount int32 `json:"participantsCount"` } // UnmarshalJSON decodes and normalizes registration data. func (r *Registration) UnmarshalJSON(data []byte) error { var payload struct { Name string `json:"name"` Email string `json:"email"` ParticipantsCount json.RawMessage `json:"participantsCount"` } decoder := json.NewDecoder(bytes.NewReader(data)) decoder.DisallowUnknownFields() if err := decoder.Decode(&payload); err != nil { return err } r.Name = payload.Name r.Email = payload.Email if len(payload.ParticipantsCount) == 0 { return nil } if err := json.Unmarshal(payload.ParticipantsCount, &r.ParticipantsCount); err == nil { return nil } var value string if err := json.Unmarshal(payload.ParticipantsCount, &value); err != nil { return errors.New(`поле "participantsCount" должно быть целым числом или строкой с целым числом`) } count, err := strconv.ParseInt(value, 10, 32) if err != nil { return errors.New(`поле "participantsCount" должно быть целым числом или строкой с целым числом`) } r.ParticipantsCount = int32(count) return nil } func validCaptainEmail(email string) bool { address, err := mail.ParseAddress(email) return err == nil && address.Address == email && len(email) <= 254 } // Validate checks registration data. func (r *Registration) Validate() error { r.Name = strings.TrimSpace(r.Name) r.Email = strings.TrimSpace(r.Email) if r.Name == "" || !utf8.ValidString(r.Name) || strings.ContainsRune(r.Name, 0) || utf8.RuneCountInString(r.Name) > 255 || !validCaptainEmail(r.Email) || r.ParticipantsCount <= 0 { return ErrInvalidRegistration } return nil }