Files
evening_detective_server/internal/services/game_service/registration.go
T
2026-09-16 02:44:44 +07:00

83 lines
2.8 KiB
Go

package game_service
import (
"bytes"
"context"
"encoding/json"
"errors"
"net/mail"
"strconv"
"strings"
"time"
"unicode/utf8"
)
var ErrInvalidRegistration = errors.New("Укажите название команды (до 255 символов), почту капитана и положительное количество участников")
type Registration struct {
Name string `json:"name"`
Email string `json:"email"`
ParticipantsCount int32 `json:"participantsCount"`
}
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 (r *Registration) Validate() error {
r.Name = strings.TrimSpace(r.Name)
r.Email = strings.TrimSpace(r.Email)
address, err := mail.ParseAddress(r.Email)
if r.Name == "" || !utf8.ValidString(r.Name) || strings.ContainsRune(r.Name, 0) || utf8.RuneCountInString(r.Name) > 255 ||
err != nil || address.Address != r.Email || len(r.Email) > 254 || r.ParticipantsCount <= 0 {
return ErrInvalidRegistration
}
return nil
}
func (s *GameService) RegisterTeam(ctx context.Context, gameID int, deliveryID string, registration Registration) (int, error) {
if err := registration.Validate(); err != nil {
return 0, err
}
if gameID <= 0 || deliveryID == "" || len(deliveryID) > 255 || strings.ContainsRune(deliveryID, 0) {
return 0, ErrInvalidRegistration
}
password, err := s.passwordGenerator.Generate()
if err != nil {
return 0, err
}
game, err := s.gamesRepo.GetGameByID(ctx, gameID)
if err != nil {
return 0, err
}
autoConfirm := time.Now().Before(game.StartAt.Add(-24*time.Hour)) == false
return s.teamsRepo.RegisterTeamWithParticipation(ctx, gameID, deliveryID, registration.Name, registration.Email, registration.ParticipantsCount, password, autoConfirm)
}