First not working app skeleton with nix support and dependency setup and generated logo not final structure
This commit is contained in:
132
src/utils.go
Normal file
132
src/utils.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package src
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func mustRandToken(n int) string {
|
||||
b := make([]byte, n)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
func now() time.Time { return time.Now().UTC() }
|
||||
|
||||
func defaultUsername() string {
|
||||
// io-game style: adjective-animal-xxxx
|
||||
adjectives := []string{"swift", "brave", "mighty", "cheeky", "sneaky", "zippy", "bouncy", "crispy", "fuzzy", "spicy", "snappy", "jazzy", "spry", "bold", "witty"}
|
||||
animals := []string{"otter", "panda", "falcon", "lynx", "badger", "tiger", "koala", "yak", "gecko", "eagle", "mamba", "fox", "yak", "whale", "rhino"}
|
||||
a := adjectives[int(time.Now().UnixNano())%len(adjectives)]
|
||||
an := animals[int(time.Now().UnixNano()/17)%len(animals)]
|
||||
return a + "-" + an + "-" + strings.ToLower(mustRandToken(2))
|
||||
}
|
||||
|
||||
func slugify(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
s = strings.TrimSpace(s)
|
||||
s = strings.ReplaceAll(s, " ", "-")
|
||||
// keep alnum and - only
|
||||
var b strings.Builder
|
||||
for _, r := range s {
|
||||
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' {
|
||||
b.WriteRune(r)
|
||||
}
|
||||
}
|
||||
out := b.String()
|
||||
if out == "" {
|
||||
out = "user-" + mustRandToken(2)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func ensureUniqueUsernameAndSlug(u *User) error {
|
||||
// try to keep username/slug unique by appending short token if needed
|
||||
baseU := u.Username
|
||||
baseS := slugify(u.Username)
|
||||
for i := 0; i < 5; i++ {
|
||||
candU := baseU
|
||||
candS := baseS
|
||||
if i > 0 {
|
||||
suffix := "-" + mustRandToken(1)
|
||||
candU = baseU + suffix
|
||||
candS = baseS + suffix
|
||||
}
|
||||
var cnt int64
|
||||
db.Model(&User{}).Where("username = ?", candU).Count(&cnt)
|
||||
if cnt == 0 {
|
||||
db.Model(&User{}).Where("slug = ?", candS).Count(&cnt)
|
||||
if cnt == 0 {
|
||||
u.Username = candU
|
||||
u.Slug = candS
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.New("cannot create unique username/slug")
|
||||
}
|
||||
|
||||
func userByEmail(email string) (*User, error) {
|
||||
var u User
|
||||
tx := db.Where("email = ?", strings.ToLower(email)).First(&u)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func userBySlug(slug string) (*User, error) {
|
||||
var u User
|
||||
tx := db.Where("slug = ?", slug).First(&u)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func atoiSafe(s string) int {
|
||||
var n int
|
||||
for _, r := range s {
|
||||
if r < '0' || r > '9' {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
_, _ = fmtSscanf(s, "%d", &n)
|
||||
return n
|
||||
}
|
||||
|
||||
// minimal sscanf to avoid fmt import just for one call
|
||||
func fmtSscanf(s, format string, a *int) (int, error) {
|
||||
// Only supports "%d"
|
||||
n := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if c < '0' || c > '9' {
|
||||
break
|
||||
}
|
||||
n = n*10 + int(c-'0')
|
||||
}
|
||||
*a = n
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func render(c *gin.Context, name string, data ctxData) {
|
||||
u := getSessionUser(c)
|
||||
if data == nil {
|
||||
data = ctxData{}
|
||||
}
|
||||
log.Println("tpl error:", name)
|
||||
data["CurrentUser"] = u
|
||||
if err := tpl.ExecuteTemplate(c.Writer, name, data); err != nil {
|
||||
log.Println("tpl error:", err)
|
||||
c.Status(500)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user