package routes import ( "context" "encoding/json" "strconv" "go-eve-pi/esi" "go-eve-pi/types" wh "go-eve-pi/webhook" logger "git.site.quack-lab.dev/dave/cylogger" "github.com/fasthttp/router" "github.com/valyala/fasthttp" ) // RouteHandler contains dependencies needed for route handlers type RouteHandler struct { SSO SSOInterface Webhook wh.Webhook ESI esi.ESIInterface } // SSOInterface defines the interface for SSO operations type SSOInterface interface { GetCharacter(ctx context.Context, characterName string) (types.Character, error) } // NewRouteHandler creates a new route handler with dependencies func NewRouteHandler(sso SSOInterface, webhook wh.Webhook, esi esi.ESIInterface) *RouteHandler { return &RouteHandler{ SSO: sso, Webhook: webhook, ESI: esi, } } // SetupRoutes configures all routes on the given router func (rh *RouteHandler) SetupRoutes(r *router.Router) { // Root route r.GET("/", rh.handleRoot) // Authentication route r.GET("/login/{character}", rh.handleLogin) // Planet routes r.GET("/planets/{character}", rh.handlePlanets) r.GET("/planet/{character}/{planet_id}", rh.handlePlanetDetails) r.GET("/planets-full/{character}", rh.handlePlanetsFull) } // handleRoot handles the root endpoint func (rh *RouteHandler) handleRoot(ctx *fasthttp.RequestCtx) { ctx.SetStatusCode(fasthttp.StatusOK) ctx.WriteString("EVE PI Server Running") } // handleLogin handles character authentication func (rh *RouteHandler) handleLogin(ctx *fasthttp.RequestCtx) { charName := ctx.UserValue("character") charNameStr, ok := charName.(string) if !ok || charNameStr == "" { ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.WriteString("Missing character parameter") return } logger.Info("Login requested for character %s", charNameStr) // Trigger the auth flow (will register callback if needed) char, err := rh.SSO.GetCharacter(context.Background(), charNameStr) if err != nil { logger.Error("Failed to authenticate character %s: %v", charNameStr, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.WriteString("Authentication failed") return } logger.Info("Successfully authenticated character %s", charNameStr) ctx.SetContentType("text/plain") ctx.SetStatusCode(fasthttp.StatusOK) ctx.WriteString("Authenticated! Access token: " + char.AccessToken) } // handlePlanets handles fetching planets for a character func (rh *RouteHandler) handlePlanets(ctx *fasthttp.RequestCtx) { charName := ctx.UserValue("character") charNameStr, ok := charName.(string) if !ok || charNameStr == "" { ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.WriteString("Missing character parameter") return } logger.Info("Fetching planets for character %s", charNameStr) // Get access token for character char, err := rh.SSO.GetCharacter(context.Background(), charNameStr) if err != nil { logger.Error("Failed to get token for character %s: %v", charNameStr, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.WriteString("Authentication failed") return } // Fetch planets using ESI API planets, err := rh.ESI.GetCharacterPlanets(context.Background(), int(char.ID), char.AccessToken) if err != nil { logger.Error("Failed to fetch planets for character %s: %v", charNameStr, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.WriteString("Failed to fetch planets") return } // Return planets as JSON ctx.SetContentType("application/json") ctx.SetStatusCode(fasthttp.StatusOK) json.NewEncoder(ctx).Encode(planets) } // handlePlanetDetails handles fetching detailed planet information func (rh *RouteHandler) handlePlanetDetails(ctx *fasthttp.RequestCtx) { charName := ctx.UserValue("character") charNameStr, ok := charName.(string) if !ok || charNameStr == "" { ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.WriteString("Missing character parameter") return } planetIDStr := ctx.UserValue("planet_id") planetID, err := strconv.Atoi(planetIDStr.(string)) if err != nil { ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.WriteString("Invalid planet ID") return } logger.Info("Fetching planet details for character %s, planet %d", charNameStr, planetID) // Get access token for character char, err := rh.SSO.GetCharacter(context.Background(), charNameStr) if err != nil { logger.Error("Failed to get token for character %s: %v", charNameStr, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.WriteString("Authentication failed") return } // Fetch planet details using ESI API planetDetail, err := rh.ESI.GetPlanetDetails(context.Background(), int(char.ID), planetID, char.AccessToken) if err != nil { logger.Error("Failed to fetch planet details for character %s, planet %d: %v", charNameStr, planetID, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.WriteString("Failed to fetch planet details") return } // Return planet details as JSON ctx.SetContentType("application/json") ctx.SetStatusCode(fasthttp.StatusOK) json.NewEncoder(ctx).Encode(planetDetail) } // handlePlanetsFull handles fetching all planets with their details for a character func (rh *RouteHandler) handlePlanetsFull(ctx *fasthttp.RequestCtx) { charName := ctx.UserValue("character") charNameStr, ok := charName.(string) if !ok || charNameStr == "" { ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.WriteString("Missing character parameter") return } logger.Info("Fetching full planet data for character %s", charNameStr) // Get access token for character char, err := rh.SSO.GetCharacter(context.Background(), charNameStr) if err != nil { logger.Error("Failed to get token for character %s: %v", charNameStr, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.WriteString("Authentication failed") return } // Fetch planets list planets, err := rh.ESI.GetCharacterPlanets(context.Background(), int(char.ID), char.AccessToken) if err != nil { logger.Error("Failed to fetch planets for character %s: %v", charNameStr, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.WriteString("Failed to fetch planets") return } // Fetch details for each planet type PlanetWithDetails struct { Planet esi.Planet Details *esi.PlanetDetail } var planetsWithDetails []PlanetWithDetails for _, planet := range planets { details, err := rh.ESI.GetPlanetDetails(context.Background(), int(char.ID), planet.PlanetID, char.AccessToken) if err != nil { logger.Warning("Failed to fetch details for planet %d: %v", planet.PlanetID, err) // Continue with other planets even if one fails details = nil } planetsWithDetails = append(planetsWithDetails, PlanetWithDetails{ Planet: planet, Details: details, }) } // Return planets with details as JSON ctx.SetContentType("application/json") ctx.SetStatusCode(fasthttp.StatusOK) json.NewEncoder(ctx).Encode(planetsWithDetails) }