From 6dbd136cd428bce878f30b36072d68c9c3204f23 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Fri, 10 Oct 2025 23:15:00 +0200 Subject: [PATCH] Refactor storages and extractors to actual functions --- routes/data.go | 212 +++++++++++++++++++++++++++++++++++++++++++++++ routes/routes.go | 122 ++------------------------- 2 files changed, 220 insertions(+), 114 deletions(-) create mode 100644 routes/data.go diff --git a/routes/data.go b/routes/data.go new file mode 100644 index 0000000..a92c85b --- /dev/null +++ b/routes/data.go @@ -0,0 +1,212 @@ +package routes + +import ( + "context" + "fmt" + "time" + + "go-eve-pi/esi" + + logger "git.site.quack-lab.dev/dave/cylogger" +) + +// ExtractorInfo represents extractor information for a planet +type ExtractorInfo struct { + PlanetName string `json:"planet_name"` + ExtractorNumber int `json:"extractor_number"` + ExpiryDate string `json:"expiry_date"` +} + +// StorageInfo represents storage information for a planet +type StorageInfo struct { + PlanetName string `json:"planet_name"` + StorageType string `json:"storage_type"` + Utilization float64 `json:"utilization"` +} + +// GetExtractorsForCharacter retrieves extractor information for a character +func GetExtractorsForCharacter(esiClient esi.ESIInterface, characterID int, accessToken string) ([]ExtractorInfo, error) { + logger.Debug("Getting extractors for character ID %d", characterID) + + // Get character planets + planets, err := esiClient.GetCharacterPlanets(context.Background(), characterID, accessToken) + if err != nil { + logger.Error("Failed to get planets for character %d: %v", characterID, err) + return nil, err + } + + var extractors []ExtractorInfo + + for _, planet := range planets { + // Get planet details + details, err := esiClient.GetPlanetDetails(context.Background(), characterID, planet.PlanetID, accessToken) + if err != nil { + logger.Warning("Failed to fetch details for planet %d: %v", planet.PlanetID, err) + continue + } + + if details != nil { + // Get planet name from universe endpoint + planetNameData, err := esiClient.GetPlanetName(context.Background(), planet.PlanetID) + if err != nil { + logger.Error("Failed to get planet name for planet ID %d: %v", planet.PlanetID, err) + continue + } + + // 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 + } + + extractors = append(extractors, ExtractorInfo{ + PlanetName: planetNameData.Name, + ExtractorNumber: extractorCount, + ExpiryDate: expiryDate, + }) + } + } + } + } + + return extractors, nil +} + +// GetStorageForCharacter retrieves storage information for a character +func GetStorageForCharacter(esiClient esi.ESIInterface, characterID int, accessToken string) ([]StorageInfo, error) { + logger.Debug("Getting storage for character ID %d", characterID) + + // Get character planets + planets, err := esiClient.GetCharacterPlanets(context.Background(), characterID, accessToken) + if err != nil { + logger.Error("Failed to get planets for character %d: %v", characterID, err) + return nil, err + } + + var storage []StorageInfo + + for _, planet := range planets { + // Get planet details + details, err := esiClient.GetPlanetDetails(context.Background(), characterID, planet.PlanetID, accessToken) + if err != nil { + logger.Warning("Failed to fetch details for planet %d: %v", planet.PlanetID, err) + continue + } + + if details != nil { + // Get planet name from universe endpoint + planetNameData, err := esiClient.GetPlanetName(context.Background(), planet.PlanetID) + if err != nil { + logger.Error("Failed to get planet name for planet ID %d: %v", planet.PlanetID, err) + continue + } + + // 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 + } + + // 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: planetNameData.Name, + StorageType: storageType, + Utilization: utilization, + }) + } + } + } + } + + return storage, nil +} + +// CheckStorageThresholds checks storage utilization against thresholds +func CheckStorageThresholds(storage []StorageInfo, warningThreshold, criticalThreshold float64) []StorageInfo { + var alerts []StorageInfo + + for _, s := range storage { + if s.Utilization >= criticalThreshold { + alerts = append(alerts, s) + } else if s.Utilization >= warningThreshold { + alerts = append(alerts, s) + } + } + + return alerts +} + +// CheckExtractorExpiry checks extractor expiry against thresholds +func CheckExtractorExpiry(extractors []ExtractorInfo, warningDuration, criticalDuration time.Duration) []ExtractorInfo { + var alerts []ExtractorInfo + now := time.Now() + + for _, e := range extractors { + if e.ExpiryDate == "N/A" { + continue + } + + expiryTime, err := time.Parse("2006-01-02 15:04:05", e.ExpiryDate) + if err != nil { + logger.Warning("Failed to parse expiry date %s: %v", e.ExpiryDate, err) + continue + } + + timeUntilExpiry := expiryTime.Sub(now) + if timeUntilExpiry <= criticalDuration { + alerts = append(alerts, e) + } else if timeUntilExpiry <= warningDuration { + alerts = append(alerts, e) + } + } + + return alerts +} + +// FormatStorageAlert formats a storage alert message +func FormatStorageAlert(storage StorageInfo, isCritical bool) string { + severity := "WARNING" + if isCritical { + severity = "CRITICAL" + } + + return fmt.Sprintf("🚨 %s: %s almost full on %s! (%.1f%% utilized)", + severity, storage.StorageType, storage.PlanetName, storage.Utilization) +} + +// FormatExtractorAlert formats an extractor alert message +func FormatExtractorAlert(extractor ExtractorInfo, isCritical bool) string { + severity := "WARNING" + if isCritical { + severity = "CRITICAL" + } + + status := "expiring soon" + if isCritical { + status = "expired" + } + + return fmt.Sprintf("⏰ %s: Extractor #%d %s on %s! (expires: %s)", + severity, extractor.ExtractorNumber, status, extractor.PlanetName, extractor.ExpiryDate) +} diff --git a/routes/routes.go b/routes/routes.go index 6971575..a77e658 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -222,18 +222,6 @@ func (rh *RouteHandler) handlePlanetsFull(ctx *fasthttp.RequestCtx) { } // 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) { @@ -249,55 +237,15 @@ func (rh *RouteHandler) handleGetExtractors(ctx *fasthttp.RequestCtx) { return } - // Get planets - planets, err := rh.ESI.GetCharacterPlanets(context.Background(), int(char.ID), char.AccessToken) + // Get extractors using the standalone function + extractors, err := GetExtractorsForCharacter(rh.ESI, int(char.ID), char.AccessToken) if err != nil { - logger.Error("Failed to get planets for character %s: %v", characterName, err) + logger.Error("Failed to get extractors for character %s: %v", characterName, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) - ctx.SetBodyString("Failed to get planets") + ctx.SetBodyString("Failed to get extractors") 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 { - // 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 { - if pin.ExtractorDetails != nil { - extractorCount++ - expiryDate := "N/A" - if pin.ExpiryTime != nil { - expiryDate = *pin.ExpiryTime - } - - extractors = append(extractors, ExtractorInfo{ - PlanetName: planetNameData.Name, - ExtractorNumber: extractorCount, - ExpiryDate: expiryDate, - }) - } - } - } - } - // Return extractors as JSON ctx.SetContentType("application/json") ctx.SetStatusCode(fasthttp.StatusOK) @@ -318,69 +266,15 @@ func (rh *RouteHandler) handleGetStorage(ctx *fasthttp.RequestCtx) { return } - // Get planets - planets, err := rh.ESI.GetCharacterPlanets(context.Background(), int(char.ID), char.AccessToken) + // Get storage using the standalone function + storage, err := GetStorageForCharacter(rh.ESI, int(char.ID), char.AccessToken) if err != nil { - logger.Error("Failed to get planets for character %s: %v", characterName, err) + logger.Error("Failed to get storage for character %s: %v", characterName, err) ctx.SetStatusCode(fasthttp.StatusInternalServerError) - ctx.SetBodyString("Failed to get planets") + ctx.SetBodyString("Failed to get storage") 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 { - // 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 { - // Calculate utilization based on contents - totalAmount := 0 - for _, content := range pin.Contents { - totalAmount += content.Amount - } - - // 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: planetNameData.Name, - StorageType: storageType, - Utilization: utilization, - }) - } - } - } - } - // Return storage as JSON ctx.SetContentType("application/json") ctx.SetStatusCode(fasthttp.StatusOK)