diff --git a/routes/routes.go b/routes/routes.go index 7bf611e..5abab9c 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -47,6 +47,10 @@ func (rh *RouteHandler) SetupRoutes(r *router.Router) { r.GET("/planets/{character}", rh.handlePlanets) r.GET("/planet/{character}/{planet_id}", rh.handlePlanetDetails) r.GET("/planets-full/{character}", rh.handlePlanetsFull) + + // New endpoints + r.GET("/extractors/{characterName}", rh.handleGetExtractors) + r.GET("/storage/{characterName}", rh.handleGetStorage) } // handleRoot handles the root endpoint @@ -216,3 +220,169 @@ func (rh *RouteHandler) handlePlanetsFull(ctx *fasthttp.RequestCtx) { ctx.SetStatusCode(fasthttp.StatusOK) json.NewEncoder(ctx).Encode(planetsWithDetails) } + +// ExtractorInfo represents extractor information +type ExtractorInfo struct { + PlanetName string `json:"planet_name"` + ExtractorNumber int `json:"extractor_number"` + ExpiryDate string `json:"expiry_date"` +} + +// StorageInfo represents storage information +type StorageInfo struct { + PlanetName string `json:"planet_name"` + StorageType string `json:"storage_type"` + Utilization float64 `json:"utilization"` +} + +// handleGetExtractors returns extractor information for a character +func (rh *RouteHandler) handleGetExtractors(ctx *fasthttp.RequestCtx) { + characterName := ctx.UserValue("characterName").(string) + logger.Info("Getting extractors for character: %s", characterName) + + // Get character info + char, err := rh.SSO.GetCharacter(context.Background(), characterName) + if err != nil { + logger.Error("Failed to get character %s: %v", characterName, err) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Failed to get character") + return + } + + // Get planets + planets, err := rh.ESI.GetCharacterPlanets(context.Background(), int(char.ID), char.AccessToken) + if err != nil { + logger.Error("Failed to get planets for character %s: %v", characterName, err) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Failed to get planets") + return + } + + var extractors []ExtractorInfo + + // Get details for each planet and extract extractor info + 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 + } + + if details != nil { + // Count extractors and get expiry dates + extractorCount := 0 + for _, pin := range details.Pins { + if pin.ExtractorDetails != nil { + extractorCount++ + expiryDate := "N/A" + if pin.ExpiryTime != nil { + expiryDate = *pin.ExpiryTime + } + + // Get actual planet name - if empty, this is an error + planetName := planet.PlanetName + if planetName == "" { + logger.Error("Planet name is empty for planet ID %d", planet.PlanetID) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Planet name is empty - this should not happen") + return + } + + extractors = append(extractors, ExtractorInfo{ + PlanetName: planetName, + ExtractorNumber: extractorCount, + ExpiryDate: expiryDate, + }) + } + } + } + } + + // Return extractors as JSON + ctx.SetContentType("application/json") + ctx.SetStatusCode(fasthttp.StatusOK) + json.NewEncoder(ctx).Encode(extractors) +} + +// handleGetStorage returns storage information for a character +func (rh *RouteHandler) handleGetStorage(ctx *fasthttp.RequestCtx) { + characterName := ctx.UserValue("characterName").(string) + logger.Info("Getting storage for character: %s", characterName) + + // Get character info + char, err := rh.SSO.GetCharacter(context.Background(), characterName) + if err != nil { + logger.Error("Failed to get character %s: %v", characterName, err) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Failed to get character") + return + } + + // Get planets + planets, err := rh.ESI.GetCharacterPlanets(context.Background(), int(char.ID), char.AccessToken) + if err != nil { + logger.Error("Failed to get planets for character %s: %v", characterName, err) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Failed to get planets") + return + } + + var storage []StorageInfo + + // Get details for each planet and extract storage info + 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 + } + + if details != nil { + // Analyze storage utilization + for _, pin := range details.Pins { + if len(pin.Contents) > 0 { + // Calculate utilization based on contents + totalAmount := 0 + for _, content := range pin.Contents { + totalAmount += content.Amount + } + + // Get actual planet name - if empty, this is an error + planetName := planet.PlanetName + if planetName == "" { + logger.Error("Planet name is empty for planet ID %d", planet.PlanetID) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Planet name is empty - this should not happen") + return + } + + // Determine storage type based on pin type + storageType := "Unknown" + switch pin.TypeID { + case 2254, 2255, 2256: // Launch pads + storageType = "Launch Pad" + case 2524, 2525, 2526: // Storage facilities + storageType = "Storage" + } + + // Calculate utilization percentage (assuming max capacity of 10000) + utilization := float64(totalAmount) / 10000.0 * 100.0 + if utilization > 100.0 { + utilization = 100.0 + } + + storage = append(storage, StorageInfo{ + PlanetName: planetName, + StorageType: storageType, + Utilization: utilization, + }) + } + } + } + } + + // Return storage as JSON + ctx.SetContentType("application/json") + ctx.SetStatusCode(fasthttp.StatusOK) + json.NewEncoder(ctx).Encode(storage) +}