Files
2026-07-15 13:29:08 +03:00

114 lines
3.7 KiB
Go

package main
import (
"html/template"
"io/fs"
"log"
"net/http"
"os"
"chessstars/internal/auth"
"chessstars/internal/courses"
"chessstars/internal/game"
"chessstars/internal/web"
)
func env(key, def string) string {
if v := os.Getenv(key); v != "" {
return v
}
return def
}
func main() {
authDBPath := env("AUTH_DB_PATH", "/data/auth.db")
coursesDir := env("COURSES_DIR", "/data/courses")
addr := ":" + env("PORT", "8080")
authStore, err := auth.Open(authDBPath)
if err != nil {
log.Fatalf("open auth db: %v", err)
}
defer authStore.Close()
courseStore, err := courses.Open(coursesDir)
if err != nil {
log.Fatalf("open courses dir: %v", err)
}
defer courseStore.Close()
startAuthCleaner(authStore)
gameManager := game.NewManager()
startGameCleaner(gameManager)
authHandlers := auth.NewHandlers(authStore)
courseHandlers := courses.NewHandlers(courseStore)
gameHandlers := game.NewHandlers(gameManager, authStore)
tmpl, err := template.ParseFS(web.TemplatesFS, "templates/*.html")
if err != nil {
log.Fatalf("parse templates: %v", err)
}
mux := http.NewServeMux()
// API: auth
mux.HandleFunc("POST /api/register", authHandlers.Register)
mux.HandleFunc("POST /api/login", authHandlers.Login)
mux.HandleFunc("POST /api/logout", authHandlers.Logout)
mux.HandleFunc("GET /api/me", authHandlers.Me)
mux.HandleFunc("PUT /api/me", authHandlers.UpdateMe)
mux.HandleFunc("GET /api/users/{username}", authHandlers.PublicProfile)
mux.HandleFunc("GET /api/users/{username}/export", authHandlers.ExportProfile)
mux.HandleFunc("GET /api/leaderboard", authHandlers.Leaderboard)
// API: courses
mux.HandleFunc("POST /api/courses", courseHandlers.CreateCourse)
mux.HandleFunc("GET /api/courses", courseHandlers.ListPublicCourses)
mux.HandleFunc("GET /api/me/courses", courseHandlers.ListMyCourses)
mux.HandleFunc("GET /api/courses/{id}", courseHandlers.GetCourse)
mux.HandleFunc("POST /api/courses/{id}/chapters", courseHandlers.AddChapter)
mux.HandleFunc("GET /api/courses/{id}/chapters/{chapterID}", courseHandlers.GetChapter)
// API: games
mux.HandleFunc("POST /api/games", gameHandlers.Create)
mux.HandleFunc("GET /api/games/open", gameHandlers.ListOpen)
mux.HandleFunc("GET /api/games/all", gameHandlers.ListAll)
mux.HandleFunc("GET /api/me/games", gameHandlers.ListMine)
mux.HandleFunc("GET /api/games/{id}", gameHandlers.Get)
mux.HandleFunc("POST /api/games/{id}/join", gameHandlers.Join)
mux.HandleFunc("POST /api/games/{id}/move", gameHandlers.Move)
mux.HandleFunc("POST /api/games/{id}/legal", gameHandlers.Legal)
mux.HandleFunc("GET /api/games/{id}/legal-moves", gameHandlers.LegalFrom)
mux.HandleFunc("GET /api/games/{id}/moves", gameHandlers.Moves)
mux.HandleFunc("GET /api/games/{id}/history/{index}", gameHandlers.HistoryAt)
// Static assets + pages
staticSub, err := fs.Sub(web.StaticFS, "static")
if err != nil {
log.Fatalf("static fs: %v", err)
}
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticSub))))
pageHandler := func(name string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := tmpl.ExecuteTemplate(w, name, nil); err != nil {
http.Error(w, "template error", http.StatusInternalServerError)
}
}
}
mux.HandleFunc("GET /", pageHandler("index.html"))
mux.HandleFunc("GET /play", pageHandler("play.html"))
mux.HandleFunc("GET /courses", pageHandler("courses.html"))
mux.HandleFunc("GET /account", pageHandler("account.html"))
mux.HandleFunc("GET /leaderboard", pageHandler("leaderboard.html"))
handler := auth.Middleware(authStore)(mux)
log.Printf("chessstars listening on %s", addr)
if err := http.ListenAndServe(addr, handler); err != nil {
log.Fatal(err)
}
}