diff options
| author | historia <[not public]> | 2026-07-13 23:01:45 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-07-13 23:01:45 -0400 |
| commit | 5a6986a8c539364b7a166abdfb608b3cc00ecb3b (patch) | |
| tree | 0a8a199fa28173df7f97493a209b5642ef7b4817 /internal/admin/api_players.go | |
| parent | 5ea48c1f91298b42924f6865ffc30810cceec2d3 (diff) | |
| download | thehouseoficarus-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.go | 153 |
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) +} |
