|
|
|
@ -11,12 +11,15 @@ import (
|
|
|
|
"strings"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
|
|
|
|
"golang.org/x/text/unicode/norm"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/denisovdennis/autohero/internal/changelog"
|
|
|
|
"github.com/denisovdennis/autohero/internal/changelog"
|
|
|
|
"github.com/denisovdennis/autohero/internal/game"
|
|
|
|
"github.com/denisovdennis/autohero/internal/game"
|
|
|
|
"github.com/denisovdennis/autohero/internal/model"
|
|
|
|
"github.com/denisovdennis/autohero/internal/model"
|
|
|
|
|
|
|
|
"github.com/denisovdennis/autohero/internal/profanity"
|
|
|
|
"github.com/denisovdennis/autohero/internal/storage"
|
|
|
|
"github.com/denisovdennis/autohero/internal/storage"
|
|
|
|
"github.com/denisovdennis/autohero/internal/tuning"
|
|
|
|
"github.com/denisovdennis/autohero/internal/tuning"
|
|
|
|
"github.com/denisovdennis/autohero/internal/version"
|
|
|
|
"github.com/denisovdennis/autohero/internal/version"
|
|
|
|
@ -1035,13 +1038,14 @@ type heroNameRequest struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// isValidHeroName checks that a name is 2-16 chars, only latin/cyrillic letters and digits,
|
|
|
|
// isValidHeroName checks that a name is 2-16 Unicode characters, only latin/cyrillic letters and digits,
|
|
|
|
// no leading/trailing spaces.
|
|
|
|
// no leading/trailing spaces. Expects trimmed, NFC-normalized input (see SetHeroName).
|
|
|
|
func isValidHeroName(name string) bool {
|
|
|
|
func isValidHeroName(name string) bool {
|
|
|
|
if len(name) < 2 || len(name) > 16 {
|
|
|
|
n := utf8.RuneCountInString(name)
|
|
|
|
|
|
|
|
if n < 2 || n > 16 {
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if name[0] == ' ' || name[len(name)-1] == ' ' {
|
|
|
|
if strings.TrimSpace(name) != name {
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, r := range name {
|
|
|
|
for _, r := range name {
|
|
|
|
@ -1079,12 +1083,20 @@ func (h *GameHandler) SetHeroName(w http.ResponseWriter, r *http.Request) {
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
req.Name = norm.NFC.String(strings.TrimSpace(req.Name))
|
|
|
|
|
|
|
|
|
|
|
|
if !isValidHeroName(req.Name) {
|
|
|
|
if !isValidHeroName(req.Name) {
|
|
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{
|
|
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{
|
|
|
|
"error": "invalid name: must be 2-16 characters, letters (latin/cyrillic) and digits only",
|
|
|
|
"error": "invalid name: must be 2-16 characters, letters (latin/cyrillic) and digits only",
|
|
|
|
})
|
|
|
|
})
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if profanity.HeroNameIsProfane(req.Name) {
|
|
|
|
|
|
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{
|
|
|
|
|
|
|
|
"error": "invalid name: inappropriate language",
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
hero, err := h.store.GetByTelegramID(r.Context(), telegramID)
|
|
|
|
hero, err := h.store.GetByTelegramID(r.Context(), telegramID)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
|