aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_players.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-13 23:01:45 -0400
committerhistoria <[not public]>2026-07-13 23:01:45 -0400
commit5a6986a8c539364b7a166abdfb608b3cc00ecb3b (patch)
tree0a8a199fa28173df7f97493a209b5642ef7b4817 /internal/admin/api_players.go
parent5ea48c1f91298b42924f6865ffc30810cceec2d3 (diff)
downloadthehouseoficarus-5a6986a8c539364b7a166abdfb608b3cc00ecb3b.tar.gz
feat(admin): convert players page into characters page with basic stats/yaml
Diffstat (limited to 'internal/admin/api_players.go')
-rw-r--r--internal/admin/api_players.go153
1 files changed, 119 insertions, 34 deletions
diff --git a/internal/admin/api_players.go b/internal/admin/api_players.go
index 2d0c09b..f7a0b87 100644
--- a/internal/admin/api_players.go
+++ b/internal/admin/api_players.go
@@ -17,29 +17,6 @@ func (s *AdminServer) handlePlayers(w http.ResponseWriter, r *http.Request) {
return
}
- nameFilter := r.URL.Query().Get("name")
-
- if nameFilter != "" {
- name, err := s.accountStore.FindCharacter(nameFilter)
- if err != nil {
- writeJSON(w, map[string]any{"error": "character not found: " + nameFilter})
- return
- }
- charPath := s.accountStore.CharPath(name)
- data, err := os.ReadFile(charPath)
- if err != nil {
- writeJSON(w, map[string]any{"error": "read error: " + err.Error()})
- return
- }
- var p player.Player
- if err := yaml.Unmarshal(data, &p); err != nil {
- writeJSON(w, map[string]any{"error": "parse error: " + err.Error()})
- return
- }
- writeJSON(w, p)
- return
- }
-
charsDir := filepath.Join(s.dataDir, "players", "characters")
entries, err := os.ReadDir(charsDir)
if err != nil {
@@ -47,10 +24,14 @@ func (s *AdminServer) handlePlayers(w http.ResponseWriter, r *http.Request) {
return
}
+ charToAccount := s.buildCharToAccountMap()
+
type playerSummary struct {
- Name string `json:"name"`
- Level int `json:"level"`
- Room int `json:"room"`
+ Name string `json:"name"`
+ Level int `json:"level"`
+ TotalLevel int `json:"total_level"`
+ Room int `json:"room"`
+ Account string `json:"account"`
}
var players []playerSummary
@@ -59,19 +40,123 @@ func (s *AdminServer) handlePlayers(w http.ResponseWriter, r *http.Request) {
continue
}
rawName := strings.TrimSuffix(e.Name(), ".yaml")
- data, err := os.ReadFile(filepath.Join(charsDir, e.Name()))
+ p, err := s.accountStore.LoadCharacter(rawName)
if err != nil {
continue
}
- var p player.Player
- if err := yaml.Unmarshal(data, &p); err != nil {
- continue
- }
players = append(players, playerSummary{
- Name: rawName,
- Level: p.CombatLevel(),
- Room: p.RoomID,
+ Name: rawName,
+ Level: p.CombatLevel(),
+ TotalLevel: p.TotalLevel(),
+ Room: p.RoomID,
+ Account: charToAccount[rawName],
})
}
writeJSON(w, players)
}
+
+func (s *AdminServer) buildCharToAccountMap() map[string]string {
+ m := make(map[string]string)
+ names, err := s.accountStore.ListAccountNames()
+ if err != nil {
+ return m
+ }
+ for _, name := range names {
+ acc, err := s.accountStore.LoadAccount(name)
+ if err != nil {
+ continue
+ }
+ for _, charName := range acc.Characters {
+ m[charName] = acc.Name
+ }
+ }
+ return m
+}
+
+func (s *AdminServer) handlePlayerByID(w http.ResponseWriter, r *http.Request) {
+ path := strings.TrimPrefix(r.URL.Path, "/api/players/")
+ if path == "" {
+ http.Error(w, `{"error":"missing player id"}`, http.StatusBadRequest)
+ return
+ }
+
+ if r.Method != http.MethodGet {
+ http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ if strings.HasPrefix(path, "account/") {
+ s.getAccount(w, r, strings.TrimPrefix(path, "account/"))
+ return
+ }
+
+ s.getCharacter(w, r, path)
+}
+
+func (s *AdminServer) getCharacter(w http.ResponseWriter, r *http.Request, name string) {
+ canonical, err := s.accountStore.FindCharacter(name)
+ if err != nil {
+ writeJSONError(w, "character not found: "+name, http.StatusNotFound)
+ return
+ }
+
+ charPath := s.accountStore.CharPath(canonical)
+ data, err := os.ReadFile(charPath)
+ if err != nil {
+ writeJSONError(w, "read error: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ m, err := yamlToMap(data)
+ if err != nil {
+ writeJSONError(w, "parse error: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ var p player.Player
+ if err := yaml.Unmarshal(data, &p); err == nil {
+ m["combat_level"] = p.CombatLevel()
+ m["total_level"] = p.TotalLevel()
+ m["max_hp"] = p.MaxHP()
+ skillLevels := make(map[string]int)
+ for _, skill := range player.AllSkills {
+ skillLevels[string(skill)] = p.Level(skill)
+ }
+ m["skill_levels"] = skillLevels
+
+ charToAccount := s.buildCharToAccountMap()
+ if acc, ok := charToAccount[canonical]; ok {
+ m["account"] = acc
+ }
+ }
+
+ m["_path"] = charPath
+ m["_raw"] = string(data)
+ writeJSON(w, m)
+}
+
+func (s *AdminServer) getAccount(w http.ResponseWriter, r *http.Request, name string) {
+ canonical, err := s.accountStore.FindAccount(name)
+ if err != nil {
+ writeJSONError(w, "account not found: "+name, http.StatusNotFound)
+ return
+ }
+
+ accPath := s.accountStore.AccountPath(canonical)
+ data, err := os.ReadFile(accPath)
+ if err != nil {
+ writeJSONError(w, "read error: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ m, err := yamlToMap(data)
+ if err != nil {
+ writeJSONError(w, "parse error: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ delete(m, "password_hash")
+
+ m["_path"] = accPath
+ m["_raw"] = string(data)
+ writeJSON(w, m)
+}