feat(esi): add PostRouteForAllByNames and resolve system names in batch

This commit introduces a new function `PostRouteForAllByNames` to the ESI service, which allows setting a complete route (including waypoints) for all logged-in characters. This is achieved by batch resolving system names to their IDs, improving efficiency and simplifying the process of setting complex routes.

The changes include:
- Adding `ResolveSystemIDsByNames` to `ESISSO` to fetch multiple system IDs in a single ESI request.
- Implementing `PostRouteForAll` in `ESISSO` to handle the logic of setting the destination and waypoints for all characters.
- Updating `App.go` to expose `PostRouteForAllByNames` for frontend use.
- Modifying the frontend component `RegionMap.tsx` to utilize the new `PostRouteForAllByNames` function when setting routes, replacing the previous sequential calls to `SetDestinationForAll` and `AddWaypointForAllByName`.
- Updating Wails generated type definitions (`.d.ts` and `.js`) to reflect the new function.
This commit is contained in:
2025-08-09 20:01:59 +02:00
parent ef57bf4cde
commit f06a60c701
5 changed files with 96 additions and 40 deletions

View File

@@ -670,4 +670,81 @@ func (s *ESISSO) ResolveSystemIDByName(ctx context.Context, name string) (int64,
}
fmt.Printf("ESI: names resolved fallback: returning %d for %q\n", namesResp[0].ID, name)
return namesResp[0].ID, nil
}
// ResolveSystemIDsByNames returns IDs in the same order as names. Missing entries error.
func (s *ESISSO) ResolveSystemIDsByNames(ctx context.Context, names []string) ([]int64, error) {
ordered := make([]int64, len(names))
if len(names) == 0 {
return ordered, nil
}
// DB first
nameLower := make([]string, len(names))
for i, n := range names { nameLower[i] = strings.TrimSpace(n) }
found := map[string]int64{}
if s.db != nil {
var rows []SolarSystem
if err := s.db.Where("solarSystemName IN ?", nameLower).Find(&rows).Error; err == nil {
for _, r := range rows {
found[r.SolarSystemName] = r.SolarSystemID
}
}
}
// Collect missing for ESI batch
missing := []string{}
for _, n := range nameLower {
if _, ok := found[n]; !ok {
missing = append(missing, n)
}
}
if len(missing) > 0 {
idsURL := esiBase + "/v3/universe/ids/?datasource=tranquility"
body, _ := json.Marshal(struct{ Names []string `json:"names"` }{Names: missing})
req, err := http.NewRequestWithContext(ctx, http.MethodPost, idsURL, strings.NewReader(string(body)))
if err != nil { return nil, err }
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
b, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("universe/ids failed: %s: %s", resp.Status, string(b))
}
var idsResp struct{ Systems []struct{ ID int64 `json:"id"`; Name string `json:"name"` } `json:"systems"` }
if err := json.NewDecoder(resp.Body).Decode(&idsResp); err != nil { return nil, err }
for _, it := range idsResp.Systems { found[it.Name] = it.ID }
}
// Build ordered list
for i, n := range nameLower {
id, ok := found[n]
if !ok { return nil, fmt.Errorf("system not found: %s", n) }
ordered[i] = id
}
return ordered, nil
}
// PostRouteForAll clears route and posts vias then destination last
func (s *ESISSO) PostRouteForAll(destID int64, viaIDs []int64) error {
if s.db == nil { return errors.New("db not initialised") }
var tokens []ESIToken
if err := s.db.Find(&tokens).Error; err != nil { return err }
var firstErr error
for i := range tokens {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
tok, err := s.ensureAccessTokenFor(ctx, &tokens[i])
cancel()
if err != nil { if firstErr == nil { firstErr = err }; continue }
// Determine sequence: clear with first element (via if any, else dest)
if len(viaIDs) > 0 {
if err := s.postWaypointWithToken(tok, viaIDs[0], true, false); err != nil && firstErr == nil { firstErr = err }
for _, id := range viaIDs[1:] {
if err := s.postWaypointWithToken(tok, id, false, false); err != nil && firstErr == nil { firstErr = err }
}
if err := s.postWaypointWithToken(tok, destID, false, false); err != nil && firstErr == nil { firstErr = err }
} else {
if err := s.postWaypointWithToken(tok, destID, true, false); err != nil && firstErr == nil { firstErr = err }
}
}
return firstErr
}