Files
evening_detective_server/internal/services/team_service/registration.go
T
2026-10-03 13:00:50 +07:00

78 lines
2.9 KiB
Go

package team_service
import (
"bytes"
"encoding/json"
"errors"
"net/mail"
"strconv"
"strings"
"unicode/utf8"
)
var (
// ErrInvalidCaptainEmail — почта капитана команды некорректна.
ErrInvalidCaptainEmail = errors.New("Укажите корректную почту капитана")
// ErrTeamNotFound — команда не найдена.
ErrTeamNotFound = errors.New("Команда не найдена")
// ErrInvalidRegistration — входные данные регистрации команды некорректны.
ErrInvalidRegistration = errors.New("Укажите название команды (до 255 символов), почту капитана и положительное количество участников")
// ErrRegistrationClosed — игра не найдена или регистрация в неё закрыта.
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
}