diff --git a/Makefile b/Makefile index 56f822e..f8eeff6 100644 --- a/Makefile +++ b/Makefile @@ -25,5 +25,10 @@ sattrack-front: mv js/dist/* public rm -rf js/dist +dev: + go run . & + npm --prefix js i + npm --prefix js run dev + clean: rm -rf sattrack public data/local.db js/dist diff --git a/app/Middlewares.go b/app/Middlewares.go new file mode 100644 index 0000000..c3bff84 --- /dev/null +++ b/app/Middlewares.go @@ -0,0 +1,17 @@ +package app + +import ( + "github.com/gofiber/fiber/v2" + "github.com/gofiber/websocket/v2" +) + +func InitMiddlewares(app *fiber.App) { + + app.Use("/ws", func(c *fiber.Ctx) error { + if websocket.IsWebSocketUpgrade(c) { + c.Locals("allowed", true) + return c.Next() + } + return fiber.ErrUpgradeRequired + }) +} diff --git a/app/Routes.go b/app/Routes.go new file mode 100644 index 0000000..a4b0d6a --- /dev/null +++ b/app/Routes.go @@ -0,0 +1,39 @@ +package app + +import ( + "github.com/SharkEzz/sattrack/handlers" + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/websocket/v2" + "gorm.io/gorm" +) + +func InitRoutes(app *fiber.App, db *gorm.DB, validator *validator.Validate) { + + // Middlewares + + InitMiddlewares(app) + + // API + + apiGroup := app.Group("/api") + apiGroup.Post("/tracking", func(c *fiber.Ctx) error { + return handlers.HandlePostTracking(c, db, validator) + }) + apiGroup.Get("/passes", func(c *fiber.Ctx) error { + return handlers.HandleGetPasses(c, db, validator) + }) + + // WebSocket + + app.Get("/ws/tracking", websocket.New(func(c *websocket.Conn) { + handlers.HandleWsTracking(c, db) + })) + + // Frontend + + app.Static("/", "public") + app.Get("*", func(c *fiber.Ctx) error { + return c.SendFile("public/index.html") + }) +} diff --git a/app/SatTrack.go b/app/SatTrack.go new file mode 100644 index 0000000..30e5f6b --- /dev/null +++ b/app/SatTrack.go @@ -0,0 +1,36 @@ +package app + +import ( + "log" + + "github.com/SharkEzz/sattrack/database" + "github.com/SharkEzz/sattrack/services" + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" +) + +func Run(dbPath, appName, version, tleURL string, update bool) { + log.Println("Starting", appName, version) + + db := database.Init("./data/local.db") + + if update { + services.UpdateDatabase(tleURL, db) + } else { + log.Println("Not updating TLE database (flag -update not given)") + } + + log.Println("Loaded", services.GetTLECount(db), "TLEs") + + validator := validator.New() + + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + AppName: appName, + }) + + InitRoutes(app, db, validator) + + log.Println(appName, "ready") + app.Listen(":8000") +} diff --git a/database/Database.go b/database/Database.go index 3b4ef50..6b4e239 100644 --- a/database/Database.go +++ b/database/Database.go @@ -1,6 +1,8 @@ package database import ( + "log" + "github.com/SharkEzz/sattrack/database/models" "gorm.io/driver/sqlite" "gorm.io/gorm" @@ -16,5 +18,7 @@ func Init(path string) *gorm.DB { db.AutoMigrate(&models.TLE{}) + log.Println("Database initialized") + return db } diff --git a/dto/Passes.go b/dto/Passes.go new file mode 100644 index 0000000..f2c0577 --- /dev/null +++ b/dto/Passes.go @@ -0,0 +1,11 @@ +package dto + +import "time" + +type PassesRequest struct { + CatNBR int `validate:"required"` + Lat float64 `validate:"required,latitude"` + Lng float64 `validate:"required,longitude"` + Alt float64 `validate:"required"` + StopTime time.Time `validate:"required"` +} diff --git a/handlers/PassesHandler.go b/handlers/PassesHandler.go new file mode 100644 index 0000000..3c27c6b --- /dev/null +++ b/handlers/PassesHandler.go @@ -0,0 +1,64 @@ +package handlers + +import ( + "net/http" + "time" + + "github.com/SharkEzz/sattrack/dto" + "github.com/SharkEzz/sattrack/services" + "github.com/SharkEzz/sgp4" + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" + "gorm.io/gorm" +) + +func HandleGetPasses(c *fiber.Ctx, db *gorm.DB, validator *validator.Validate) error { + requestData := dto.PassesRequest{} + c.BodyParser(&requestData) + err := validator.Struct(requestData) + if err != nil { + return c.Status(http.StatusBadRequest).JSON(dto.Response{ + Status: http.StatusBadRequest, + Message: err.Error(), + }) + } + if requestData.StopTime.Before(time.Now()) { + return c.Status(http.StatusBadRequest).JSON(dto.Response{ + Status: http.StatusBadRequest, + Message: "StopTime can't be before current time", + }) + } + if requestData.StopTime.After(time.Now().Add(time.Second * 864000)) { // 10 days + return c.Status(http.StatusBadRequest).JSON(dto.Response{ + Status: http.StatusBadRequest, + Message: "Can't computes passes more than 10 days in the future", + }) + } + + tle, err := services.GetTLEFromDatabase(requestData.CatNBR, db) + if err != nil { + return c.Status(http.StatusNotFound).JSON(dto.Response{ + Status: http.StatusNotFound, + Message: "TLE not found", + }) + } + + sgp4, err := sgp4.NewSGP4(tle) + if err != nil { + return c.Status(http.StatusInternalServerError).JSON(dto.Response{ + Status: http.StatusInternalServerError, + Message: err.Error(), + }) + } + + passes := sgp4.GeneratePasses( + requestData.Lat, + requestData.Lng, + requestData.Alt, + time.Now().UTC(), + requestData.StopTime.UTC(), + 360, + ) + + return c.JSON(passes) +} diff --git a/main.go b/main.go index 57b6401..98437d3 100644 --- a/main.go +++ b/main.go @@ -2,15 +2,8 @@ package main import ( "flag" - "log" - "github.com/SharkEzz/sattrack/database" - "github.com/SharkEzz/sattrack/handlers" - "github.com/SharkEzz/sattrack/services" - - "github.com/go-playground/validator/v10" - "github.com/gofiber/fiber/v2" - "github.com/gofiber/websocket/v2" + "github.com/SharkEzz/sattrack/app" ) const ( @@ -24,50 +17,13 @@ var ( ) func main() { - log.Println("Starting", appName, version) flag.Parse() - db := database.Init("./data/local.db") - - if *shouldUpdate { - services.UpdateDatabase(*tleListURL, db) - } else { - log.Println("Not updating TLE database (flag -update not given)") - } - - log.Println("Loaded", services.GetTLECount(db), "TLEs") - - validator := validator.New() - - app := fiber.New(fiber.Config{ - DisableStartupMessage: true, - AppName: appName, - }) - - app.Use("/ws", func(c *fiber.Ctx) error { - if websocket.IsWebSocketUpgrade(c) { - c.Locals("allowed", true) - return c.Next() - } - return fiber.ErrUpgradeRequired - }) - - apiGroup := app.Group("/api") - apiGroup.Post("/tracking", func(c *fiber.Ctx) error { - return handlers.HandlePostTracking(c, db, validator) - }) - - app.Get("/ws/tracking", websocket.New(func(c *websocket.Conn) { - handlers.HandleWsTracking(c, db) - })) - - // SPA - - app.Static("/", "public") - app.Get("*", func(c *fiber.Ctx) error { - return c.SendFile("public/index.html") - }) - - log.Println(appName, "ready") - app.Listen(":8000") + app.Run( + "./data/local.db", + appName, + version, + *tleListURL, + *shouldUpdate, + ) }