package main import ( "flag" "fmt" "log" "os" "os/signal" "path/filepath" "syscall" "time" "dk/internal/control" "dk/internal/database" "dk/internal/models/users" "dk/internal/routes" "dk/internal/template" sushi "git.sharkk.net/Sharkk/Sushi" "git.sharkk.net/Sharkk/Sushi/auth" "git.sharkk.net/Sharkk/Sushi/csrf" "git.sharkk.net/Sharkk/Sushi/session" "git.sharkk.net/Sharkk/Sushi/timing" ) func main() { var port string flag.StringVar(&port, "p", "3000", "Port to run server on") if len(os.Args) < 2 { startServer(port) return } switch os.Args[1] { case "serve": flag.CommandLine.Parse(os.Args[2:]) startServer(port) default: fmt.Fprintf(os.Stderr, "Unknown command: %s\n", os.Args[1]) fmt.Fprintln(os.Stderr, "Available commands:") fmt.Fprintln(os.Stderr, " serve - Start the server") fmt.Fprintln(os.Stderr, " (no command) - Start the server") os.Exit(1) } } func startServer(port string) { fmt.Println("Starting Dragon Knight server...") if err := start(port); err != nil { log.Fatalf("Server failed: %v", err) } } func start(port string) error { cwd, err := os.Getwd() if err != nil { return fmt.Errorf("failed to get current working directory: %w", err) } err = database.Init(filepath.Join(cwd, "data/dk.db")) if err != nil { log.Fatal("Failed to initialize database:", err) } defer database.DB().Close() control.Init(filepath.Join(cwd, "data/control.json")) defer control.Save() template.InitializeCache(cwd) authMW := auth.New(getUserByID) app := sushi.New() sushi.InitSessions(filepath.Join(cwd, "data/sessions.json")) app.Use(session.Middleware()) app.Use(authMW.Middleware()) app.Use(csrf.Middleware()) app.Use(timing.Middleware()) app.Use(func(ctx sushi.Ctx, next func()) { if ctx.IsAuthenticated() { user := ctx.GetCurrentUser().(*users.User) now := time.Now().Unix() if (now - user.LastOnline) >= 540 { // 540 seconds = 9 minutes database.Update("users", map[string]any{ "last_online": now, }, "id", user.ID) } } next() }) app.Get("/", routes.Index) protected := app.Group("") protected.Use(auth.RequireAuth("/login")) protected.Get("/explore", routes.Explore) protected.Post("/move", routes.Move) protected.Get("/teleport/:to", routes.Teleport) routes.RegisterAuthRoutes(app) routes.RegisterTownRoutes(app) routes.RegisterFightRoutes(app) app.Get("/assets/*path", sushi.Static(cwd)) addr := ":" + port log.Printf("Server starting on %s", addr) c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { app.Listen(addr) }() <-c log.Println("\nReceived shutdown signal, shutting down gracefully...") log.Println("Saving sessions...") sushi.SaveSessions() log.Println("Server stopped") return nil } func getUserByID(userID int) any { user, err := users.Find(userID) if err != nil { panic(fmt.Sprintf("Error finding user ID %d", userID)) } return user }