diff --git a/esi/cached.go b/esi/cached.go index feda010..4dc5708 100644 --- a/esi/cached.go +++ b/esi/cached.go @@ -150,3 +150,23 @@ func getCachedResponse[T any](c *CachedESI, url string, fetchFunc func() (T, err return result, nil } + +// GetPlanetName retrieves planet name with caching +func (c *CachedESI) GetPlanetName(ctx context.Context, planetID int) (*PlanetName, error) { + url := fmt.Sprintf("/v1/universe/planets/%d/", planetID) + logger.Info("CachedESI: Getting planet name for planet %d", planetID) + + fetchFunc := func() (*PlanetName, error) { + logger.Debug("CachedESI: Calling direct ESI for planet %d name", planetID) + return c.direct.GetPlanetName(ctx, planetID) + } + + result, err := getCachedResponse(c, url, fetchFunc) + if err != nil { + logger.Error("CachedESI: Failed to get planet name for planet %d: %v", planetID, err) + return nil, err + } + + logger.Info("CachedESI: Successfully retrieved planet name for planet %d: %s", planetID, result.Name) + return result, nil +} diff --git a/esi/client.go b/esi/client.go index 25a99ac..e3521a5 100644 --- a/esi/client.go +++ b/esi/client.go @@ -2,6 +2,7 @@ package esi import ( + "bytes" "context" "encoding/json" "fmt" @@ -82,6 +83,18 @@ type Head struct { Longitude float64 `json:"longitude"` } +type PlanetName struct { + Name string `json:"name"` + PlanetID int `json:"planet_id"` + SystemID int `json:"system_id"` + TypeID int `json:"type_id"` + Position struct { + X float64 `json:"x"` + Y float64 `json:"y"` + Z float64 `json:"z"` + } `json:"position"` +} + type FactoryDetails struct { SchematicID int `json:"schematic_id"` } @@ -99,6 +112,7 @@ type Route struct { type ESIInterface interface { GetCharacterPlanets(ctx context.Context, characterID int, accessToken string) ([]Planet, error) GetPlanetDetails(ctx context.Context, characterID, planetID int, accessToken string) (*PlanetDetail, error) + GetPlanetName(ctx context.Context, planetID int) (*PlanetName, error) } // DirectESI implements ESIInterface with direct API calls @@ -197,3 +211,45 @@ func (d *DirectESI) GetPlanetDetails(ctx context.Context, characterID, planetID logger.Info("Successfully fetched planet details for character ID %d, planet ID %d", characterID, planetID) return &planetDetail, nil } + +// GetPlanetName retrieves planet name from universe endpoint +func (d *DirectESI) GetPlanetName(ctx context.Context, planetID int) (*PlanetName, error) { + logger.Debug("Fetching planet name for planet ID %d", planetID) + + url := fmt.Sprintf("%s/v1/universe/planets/%d/", ESIBaseURL, planetID) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + logger.Error("Failed to create request for planet name: %v", err) + return nil, err + } + + req.Header.Set("Accept", "application/json") + + resp, err := d.httpClient.Do(req) + if err != nil { + logger.Error("Failed to fetch planet name: %v", err) + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + logger.Error("Failed to read planet name response body: %v", err) + return nil, err + } + + if resp.StatusCode != http.StatusOK { + logger.Error("API request failed with status %d: %s", resp.StatusCode, string(body)) + return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body)) + } + + var planetName PlanetName + if err := json.NewDecoder(bytes.NewReader(body)).Decode(&planetName); err != nil { + logger.Error("Failed to decode planet name response: %v", err) + return nil, err + } + + logger.Info("Successfully fetched planet name for planet ID %d: %s", planetID, planetName.Name) + return &planetName, nil +} diff --git a/routes/routes.go b/routes/routes.go index 5abab9c..6971575 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -269,6 +269,15 @@ func (rh *RouteHandler) handleGetExtractors(ctx *fasthttp.RequestCtx) { } if details != nil { + // Get planet name from universe endpoint + planetNameData, err := rh.ESI.GetPlanetName(context.Background(), planet.PlanetID) + if err != nil { + logger.Error("Failed to get planet name for planet ID %d: %v", planet.PlanetID, err) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Failed to get planet name") + return + } + // Count extractors and get expiry dates extractorCount := 0 for _, pin := range details.Pins { @@ -279,17 +288,8 @@ func (rh *RouteHandler) handleGetExtractors(ctx *fasthttp.RequestCtx) { 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, + PlanetName: planetNameData.Name, ExtractorNumber: extractorCount, ExpiryDate: expiryDate, }) @@ -338,6 +338,15 @@ func (rh *RouteHandler) handleGetStorage(ctx *fasthttp.RequestCtx) { } if details != nil { + // Get planet name from universe endpoint + planetNameData, err := rh.ESI.GetPlanetName(context.Background(), planet.PlanetID) + if err != nil { + logger.Error("Failed to get planet name for planet ID %d: %v", planet.PlanetID, err) + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetBodyString("Failed to get planet name") + return + } + // Analyze storage utilization for _, pin := range details.Pins { if len(pin.Contents) > 0 { @@ -347,15 +356,6 @@ func (rh *RouteHandler) handleGetStorage(ctx *fasthttp.RequestCtx) { 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 { @@ -372,7 +372,7 @@ func (rh *RouteHandler) handleGetStorage(ctx *fasthttp.RequestCtx) { } storage = append(storage, StorageInfo{ - PlanetName: planetName, + PlanetName: planetNameData.Name, StorageType: storageType, Utilization: utilization, })