You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
5.7 KiB
Go
252 lines
5.7 KiB
Go
package routes
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/aziis98/lupus-lite/events"
|
|
"github.com/aziis98/lupus-lite/lupus"
|
|
"github.com/aziis98/lupus-lite/model"
|
|
"github.com/aziis98/lupus-lite/util"
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/valyala/fasthttp"
|
|
)
|
|
|
|
func (s *Server) Api(api fiber.Router) {
|
|
api.Get("/status", func(c *fiber.Ctx) error {
|
|
s, err := json.MarshalIndent(s.db, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(string(s))
|
|
|
|
return c.SendString("ok")
|
|
})
|
|
|
|
api.Post("/login", func(c *fiber.Ctx) error {
|
|
var loginForm struct {
|
|
Username string `form:"username"`
|
|
Password string `form:"password"`
|
|
}
|
|
|
|
if err := c.BodyParser(&loginForm); err != nil {
|
|
return err
|
|
}
|
|
|
|
token, err := s.auth.Login(loginForm.Username, loginForm.Password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.Cookie(&fiber.Cookie{
|
|
Name: "sid",
|
|
Value: token,
|
|
Path: "/",
|
|
Expires: time.Now().Add(3 * 24 * time.Hour),
|
|
})
|
|
|
|
return c.Redirect("/")
|
|
})
|
|
|
|
api.Post("/logout", func(c *fiber.Ctx) error {
|
|
c.Cookie(&fiber.Cookie{
|
|
Name: "sid",
|
|
Value: "",
|
|
Path: "/",
|
|
Expires: time.Now(),
|
|
})
|
|
|
|
return c.SendString("ok")
|
|
})
|
|
|
|
api.Post("/register", func(c *fiber.Ctx) error {
|
|
var loginForm struct {
|
|
Username string `form:"username"`
|
|
Password string `form:"password"`
|
|
Password2 string `form:"password2"`
|
|
}
|
|
|
|
if err := c.BodyParser(&loginForm); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := util.ValidateUsername(loginForm.Username); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := util.ValidatePasswords(loginForm.Password, loginForm.Password2); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.auth.Register(loginForm.Username, loginForm.Password); err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.Redirect("/login")
|
|
})
|
|
|
|
api.Post("/crea-partita", s.requireLogged, func(c *fiber.Ctx) error {
|
|
user := requestUser(c)
|
|
|
|
var form struct {
|
|
NumGiocatori string `form:"numero-giocatori"`
|
|
NumLupi string `form:"numero-lupi"`
|
|
NumFattucchiere string `form:"numero-fattucchiere"`
|
|
NumGuardie string `form:"numero-guardie"`
|
|
NumCacciatori string `form:"numero-cacciatori"`
|
|
NumMedium string `form:"numero-medium"`
|
|
NumVeggenti string `form:"numero-veggenti"`
|
|
}
|
|
if err := c.BodyParser(&form); err != nil {
|
|
return err
|
|
}
|
|
|
|
cfg := model.PartitaConfig{
|
|
NumeroPerRuolo: map[string]int{},
|
|
}
|
|
|
|
if err := util.AtoiInto(form.NumGiocatori, &cfg.NumeroGiocatori); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Questo codice magico scorre su questa "tabella" con colonne ruolo e stringa del ruolo nel form e popola la mappa NumeroPerRuolo da uid ruolo a numero per ruolo.
|
|
for _, r := range []struct {
|
|
ruolo lupus.Ruolo
|
|
num string
|
|
}{
|
|
{lupus.Lupo, form.NumLupi},
|
|
{lupus.Fattucchiera, form.NumFattucchiere},
|
|
{lupus.Guardia, form.NumGuardie},
|
|
{lupus.Cacciatore, form.NumCacciatori},
|
|
{lupus.Medium, form.NumMedium},
|
|
{lupus.Veggente, form.NumVeggenti},
|
|
} {
|
|
num, err := strconv.Atoi(r.num)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cfg.NumeroPerRuolo[r.ruolo.Uid] = num
|
|
}
|
|
|
|
partita, err := s.db.CreatePartita(user.Username, cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.JSON(partita)
|
|
})
|
|
|
|
api.Get("/user", s.requireLogged, func(c *fiber.Ctx) error {
|
|
return c.JSON(requestUser(c).PublicUser())
|
|
})
|
|
|
|
api.Get("/partita/:partita/joined-players", func(c *fiber.Ctx) error {
|
|
partitaUid := c.Params("partita")
|
|
|
|
partita, err := s.db.GetPartita(partitaUid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.JSON(partita.Players)
|
|
})
|
|
|
|
api.Get("/partita/:partita/joined-players/events", func(c *fiber.Ctx) error {
|
|
partitaUid := c.Params("partita")
|
|
|
|
c.Set("Content-Type", "text/event-stream")
|
|
c.Set("Cache-Control", "no-cache")
|
|
c.Set("Connection", "keep-alive")
|
|
c.Set("Transfer-Encoding", "chunked")
|
|
|
|
sse := make(chan any, 1)
|
|
done := make(chan bool)
|
|
|
|
clientId := util.GenerateRandomString(16)
|
|
log.Printf(`[%v] New SSE listener`, clientId)
|
|
|
|
l := s.eventBus.Subscribe(
|
|
events.OnPartitaPlayerJoins(partitaUid),
|
|
func(e interface{}) {
|
|
sse <- e
|
|
},
|
|
)
|
|
|
|
go func() {
|
|
<-done
|
|
close(sse)
|
|
close(done)
|
|
s.eventBus.Unsubscribe(l)
|
|
}()
|
|
|
|
c.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
|
|
log.Printf("[%v] Starting communication...", clientId)
|
|
|
|
if _, err := fmt.Fprintf(w, "data: initial message\n\n"); err != nil {
|
|
log.Printf(`SSE Writer error: %v`, err)
|
|
return
|
|
}
|
|
|
|
outer:
|
|
for {
|
|
select {
|
|
case e := <-sse:
|
|
log.Printf(`[%v] Event: New player joined`, clientId)
|
|
players := e.([]string)
|
|
|
|
msg, err := json.Marshal(players)
|
|
if err != nil {
|
|
log.Printf("[%v] Error %v", clientId, err)
|
|
break outer
|
|
}
|
|
|
|
if _, err := fmt.Fprintf(w, "data: %s\n\n", msg); err != nil {
|
|
log.Printf("[%v] Error: sse writer error, %v", clientId, err)
|
|
break outer
|
|
}
|
|
|
|
err = w.Flush()
|
|
log.Printf(`[%v] Flush result %v`, clientId, err)
|
|
if err != nil {
|
|
log.Printf("[%v] Error: error while flushing, %v, Closing connection.", clientId, err)
|
|
break outer
|
|
}
|
|
case <-time.After(10 * time.Second):
|
|
break outer
|
|
}
|
|
}
|
|
|
|
log.Printf("[%v] Connection timeout", clientId)
|
|
done <- true
|
|
}))
|
|
|
|
return nil
|
|
})
|
|
|
|
api.Get("/partita/:partita/join-partita", s.requireLogged, func(c *fiber.Ctx) error {
|
|
user := requestUser(c)
|
|
partitaUid := c.Params("partita")
|
|
|
|
partita, err := s.db.GetPartita(partitaUid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
partita.Players = append(partita.Players, user.Username)
|
|
|
|
if err := s.db.UpdatePartita(partita); err != nil {
|
|
return err
|
|
}
|
|
|
|
s.eventBus.Dispatch(events.OnPartitaPlayerJoins(partitaUid), partita.Players)
|
|
|
|
return c.SendString("ok")
|
|
})
|
|
}
|