Enable toggling waypoint sending characters
This commit is contained in:
195
esi_sso.go
195
esi_sso.go
@@ -63,34 +63,36 @@ type SolarSystem struct {
|
||||
func (SolarSystem) TableName() string { return "mapSolarSystems" }
|
||||
|
||||
type ESIToken struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
CharacterID int64 `gorm:"index"`
|
||||
CharacterName string
|
||||
AccessToken string
|
||||
RefreshToken string
|
||||
ExpiresAt time.Time
|
||||
UpdatedAt time.Time
|
||||
CreatedAt time.Time
|
||||
ID uint `gorm:"primaryKey"`
|
||||
CharacterID int64 `gorm:"index"`
|
||||
CharacterName string
|
||||
AccessToken string
|
||||
RefreshToken string
|
||||
ExpiresAt time.Time
|
||||
WaypointEnabled bool `gorm:"default:true"`
|
||||
UpdatedAt time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type CharacterInfo struct {
|
||||
CharacterID int64 `json:"character_id"`
|
||||
CharacterName string `json:"character_name"`
|
||||
CharacterID int64 `json:"character_id"`
|
||||
CharacterName string `json:"character_name"`
|
||||
WaypointEnabled bool `json:"waypoint_enabled"`
|
||||
}
|
||||
|
||||
// CharacterLocation represents a character's current location
|
||||
type CharacterLocation struct {
|
||||
CharacterID int64 `json:"character_id"`
|
||||
CharacterName string `json:"character_name"`
|
||||
SolarSystemID int64 `json:"solar_system_id"`
|
||||
SolarSystemName string `json:"solar_system_name"`
|
||||
RetrievedAt time.Time `json:"retrieved_at"`
|
||||
CharacterID int64 `json:"character_id"`
|
||||
CharacterName string `json:"character_name"`
|
||||
SolarSystemID int64 `json:"solar_system_id"`
|
||||
SolarSystemName string `json:"solar_system_name"`
|
||||
RetrievedAt time.Time `json:"retrieved_at"`
|
||||
}
|
||||
|
||||
type esiCharacterLocationResponse struct {
|
||||
SolarSystemID int64 `json:"solar_system_id"`
|
||||
StationID int64 `json:"station_id"`
|
||||
StructureID int64 `json:"structure_id"`
|
||||
SolarSystemID int64 `json:"solar_system_id"`
|
||||
StationID int64 `json:"station_id"`
|
||||
StructureID int64 `json:"structure_id"`
|
||||
}
|
||||
|
||||
func NewESISSO(clientID string, redirectURI string, scopes []string) *ESISSO {
|
||||
@@ -122,39 +124,57 @@ func (s *ESISSO) initDB() error {
|
||||
|
||||
// resolveSystemNameByID returns the system name for an ID from the local DB, or empty if not found
|
||||
func (s *ESISSO) resolveSystemNameByID(id int64) string {
|
||||
if s.db == nil || id == 0 { return "" }
|
||||
var ss SolarSystem
|
||||
if err := s.db.Select("solarSystemName").First(&ss, "solarSystemID = ?", id).Error; err != nil { return "" }
|
||||
return ss.SolarSystemName
|
||||
if s.db == nil || id == 0 {
|
||||
return ""
|
||||
}
|
||||
var ss SolarSystem
|
||||
if err := s.db.Select("solarSystemName").First(&ss, "solarSystemID = ?", id).Error; err != nil {
|
||||
return ""
|
||||
}
|
||||
return ss.SolarSystemName
|
||||
}
|
||||
|
||||
// GetCharacterLocations returns current locations for all stored characters
|
||||
func (s *ESISSO) GetCharacterLocations(ctx context.Context) ([]CharacterLocation, error) {
|
||||
if s.db == nil { return nil, errors.New("db not initialised") }
|
||||
var tokens []ESIToken
|
||||
if err := s.db.Find(&tokens).Error; err != nil { return nil, err }
|
||||
out := make([]CharacterLocation, 0, len(tokens))
|
||||
client := &http.Client{ Timeout: 5 * time.Second }
|
||||
for i := range tokens {
|
||||
t := &tokens[i]
|
||||
tok, err := s.ensureAccessTokenFor(ctx, t)
|
||||
if err != nil { continue }
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, esiBase+"/v2/characters/"+strconv.FormatInt(t.CharacterID,10)+"/location", nil)
|
||||
if err != nil { continue }
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+tok)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil { continue }
|
||||
func() {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK { return }
|
||||
var lr esiCharacterLocationResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&lr); err != nil { return }
|
||||
name := s.resolveSystemNameByID(lr.SolarSystemID)
|
||||
out = append(out, CharacterLocation{ CharacterID: t.CharacterID, CharacterName: t.CharacterName, SolarSystemID: lr.SolarSystemID, SolarSystemName: name, RetrievedAt: time.Now() })
|
||||
}()
|
||||
}
|
||||
return out, nil
|
||||
if s.db == nil {
|
||||
return nil, errors.New("db not initialised")
|
||||
}
|
||||
var tokens []ESIToken
|
||||
if err := s.db.Find(&tokens).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make([]CharacterLocation, 0, len(tokens))
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
for i := range tokens {
|
||||
t := &tokens[i]
|
||||
tok, err := s.ensureAccessTokenFor(ctx, t)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, esiBase+"/v2/characters/"+strconv.FormatInt(t.CharacterID, 10)+"/location", nil)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+tok)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
func() {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return
|
||||
}
|
||||
var lr esiCharacterLocationResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&lr); err != nil {
|
||||
return
|
||||
}
|
||||
name := s.resolveSystemNameByID(lr.SolarSystemID)
|
||||
out = append(out, CharacterLocation{CharacterID: t.CharacterID, CharacterName: t.CharacterName, SolarSystemID: lr.SolarSystemID, SolarSystemName: name, RetrievedAt: time.Now()})
|
||||
}()
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *ESISSO) saveToken() {
|
||||
@@ -527,6 +547,9 @@ func (s *ESISSO) PostWaypointForAll(destinationID int64, clearOthers bool, addTo
|
||||
}
|
||||
var firstErr error
|
||||
for i := range tokens {
|
||||
if !tokens[i].WaypointEnabled {
|
||||
continue
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
tok, err := s.ensureAccessTokenFor(ctx, &tokens[i])
|
||||
cancel()
|
||||
@@ -543,6 +566,19 @@ func (s *ESISSO) PostWaypointForAll(destinationID int64, clearOthers bool, addTo
|
||||
return firstErr
|
||||
}
|
||||
|
||||
// ToggleCharacterWaypointEnabled toggles the waypoint enabled status for a character
|
||||
func (s *ESISSO) ToggleCharacterWaypointEnabled(characterID int64) error {
|
||||
if s.db == nil {
|
||||
return errors.New("db not initialised")
|
||||
}
|
||||
var token ESIToken
|
||||
if err := s.db.Where("character_id = ?", characterID).First(&token).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
token.WaypointEnabled = !token.WaypointEnabled
|
||||
return s.db.Save(&token).Error
|
||||
}
|
||||
|
||||
func (s *ESISSO) Status() SSOStatus {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
@@ -667,16 +703,24 @@ func (s *ESISSO) ResolveSystemIDsByNames(ctx context.Context, names []string) ([
|
||||
|
||||
// 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") }
|
||||
if s.db == nil {
|
||||
return errors.New("db not initialised")
|
||||
}
|
||||
var tokens []ESIToken
|
||||
if err := s.db.Find(&tokens).Error; err != nil { return err }
|
||||
// Deduplicate by CharacterID
|
||||
if err := s.db.Find(&tokens).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// Deduplicate by CharacterID and filter enabled characters
|
||||
uniq := make(map[int64]ESIToken, len(tokens))
|
||||
for _, t := range tokens {
|
||||
uniq[t.CharacterID] = t
|
||||
if t.WaypointEnabled {
|
||||
uniq[t.CharacterID] = t
|
||||
}
|
||||
}
|
||||
uniqueTokens := make([]ESIToken, 0, len(uniq))
|
||||
for _, t := range uniq { uniqueTokens = append(uniqueTokens, t) }
|
||||
for _, t := range uniq {
|
||||
uniqueTokens = append(uniqueTokens, t)
|
||||
}
|
||||
|
||||
var mu sync.Mutex
|
||||
var firstErr error
|
||||
@@ -690,20 +734,53 @@ func (s *ESISSO) PostRouteForAll(destID int64, viaIDs []int64) error {
|
||||
tok, err := s.ensureAccessTokenFor(ctx, &t)
|
||||
cancel()
|
||||
if err != nil {
|
||||
mu.Lock(); if firstErr == nil { firstErr = err }; mu.Unlock(); return
|
||||
mu.Lock()
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
// Post sequence for this character
|
||||
if len(viaIDs) > 0 {
|
||||
if err := s.postWaypointWithToken(tok, viaIDs[0], true, false); err != nil { mu.Lock(); if firstErr == nil { firstErr = err }; mu.Unlock(); return }
|
||||
for _, id := range viaIDs[1:] {
|
||||
if err := s.postWaypointWithToken(tok, id, false, false); err != nil { mu.Lock(); if firstErr == nil { firstErr = err }; mu.Unlock(); return }
|
||||
if err := s.postWaypointWithToken(tok, viaIDs[0], true, false); err != nil {
|
||||
mu.Lock()
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
for _, id := range viaIDs[1:] {
|
||||
if err := s.postWaypointWithToken(tok, id, false, false); err != nil {
|
||||
mu.Lock()
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := s.postWaypointWithToken(tok, destID, false, false); err != nil {
|
||||
mu.Lock()
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
if err := s.postWaypointWithToken(tok, destID, false, false); err != nil { mu.Lock(); if firstErr == nil { firstErr = err }; mu.Unlock(); return }
|
||||
} else {
|
||||
if err := s.postWaypointWithToken(tok, destID, true, false); err != nil { mu.Lock(); if firstErr == nil { firstErr = err }; mu.Unlock(); return }
|
||||
if err := s.postWaypointWithToken(tok, destID, true, false); err != nil {
|
||||
mu.Lock()
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}(uniqueTokens[i])
|
||||
}
|
||||
wg.Wait()
|
||||
return firstErr
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user