aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_mobs.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/api_mobs.go')
-rw-r--r--internal/admin/api_mobs.go163
1 files changed, 163 insertions, 0 deletions
diff --git a/internal/admin/api_mobs.go b/internal/admin/api_mobs.go
new file mode 100644
index 0000000..5fdfbc8
--- /dev/null
+++ b/internal/admin/api_mobs.go
@@ -0,0 +1,163 @@
+package admin
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func (s *AdminServer) handleMobs(w http.ResponseWriter, r *http.Request) {
+ switch r.Method {
+ case http.MethodGet:
+ ids, err := listYAMLFiles(s.dataDir, "mobs")
+ if err != nil {
+ writeJSON(w, map[string]any{"error": err.Error()})
+ return
+ }
+ if ids == nil {
+ ids = []string{}
+ }
+ writeJSON(w, ids)
+
+ case http.MethodPost:
+ s.createMob(w, r)
+
+ default:
+ http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed)
+ }
+}
+
+func (s *AdminServer) handleMobByID(w http.ResponseWriter, r *http.Request) {
+ id := strings.TrimPrefix(r.URL.Path, "/api/mobs/")
+ if id == "" {
+ http.Error(w, `{"error":"missing mob id"}`, http.StatusBadRequest)
+ return
+ }
+
+ switch r.Method {
+ case http.MethodGet:
+ s.getMob(w, r, id)
+ case http.MethodPut:
+ s.updateMob(w, r, id)
+ case http.MethodDelete:
+ s.deleteMob(w, r, id)
+ default:
+ http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed)
+ }
+}
+
+func (s *AdminServer) findMobFile(id string) ([]byte, string, error) {
+ data, path, err := readYAMLFile(s.dataDir, "mobs", id)
+ if err == nil {
+ return data, path, nil
+ }
+ return findYAMLFileInSubdirs(s.dataDir, "mobs", id)
+}
+
+func (s *AdminServer) getMob(w http.ResponseWriter, r *http.Request, id string) {
+ data, path, err := s.findMobFile(id)
+ if err != nil {
+ http.Error(w, `{"error":"mob not found"}`, http.StatusNotFound)
+ return
+ }
+ m, err := yamlToMap(data)
+ if err != nil {
+ http.Error(w, `{"error":"failed to parse mob yaml"}`, http.StatusInternalServerError)
+ return
+ }
+ m["_path"] = path
+ m["_raw"] = string(data)
+ writeJSON(w, m)
+}
+
+func (s *AdminServer) updateMob(w http.ResponseWriter, r *http.Request, id string) {
+ _, path, err := s.findMobFile(id)
+ if err != nil {
+ http.Error(w, `{"error":"mob not found"}`, http.StatusNotFound)
+ return
+ }
+ var m map[string]any
+ if err := readJSON(r, &m); err != nil {
+ http.Error(w, `{"error":"invalid json body"}`, http.StatusBadRequest)
+ return
+ }
+ m["id"] = id
+
+ oldContent, err := snapshotFile(path)
+ if err != nil {
+ http.Error(w, `{"error":"failed to read existing mob"}`, http.StatusInternalServerError)
+ return
+ }
+ newContent, err := writeMapAsYAML(path, m)
+ if err != nil {
+ http.Error(w, `{"error":"failed to write mob"}`, http.StatusInternalServerError)
+ return
+ }
+ s.mobStore.ReloadDefs(s.dataDir)
+ s.undoStack.Push(ChangeDesc{
+ Description: fmt.Sprintf("Update mob %s", id),
+ FilePath: path,
+ OldContent: oldContent,
+ NewContent: newContent,
+ })
+ writeJSON(w, m)
+}
+
+func (s *AdminServer) deleteMob(w http.ResponseWriter, r *http.Request, id string) {
+ _, path, err := s.findMobFile(id)
+ if err != nil {
+ http.Error(w, `{"error":"mob not found"}`, http.StatusNotFound)
+ return
+ }
+
+ oldContent := backupFile(path)
+
+ if err := os.Remove(path); err != nil {
+ http.Error(w, `{"error":"failed to delete mob"}`, http.StatusInternalServerError)
+ return
+ }
+
+ s.mobStore.ReloadDefs(s.dataDir)
+
+ s.undoStack.Push(ChangeDesc{
+ Description: fmt.Sprintf("Delete mob %s", id),
+ FilePath: path,
+ OldContent: oldContent,
+ IsDelete: true,
+ })
+
+ writeJSON(w, map[string]any{"deleted": id})
+}
+
+func (s *AdminServer) createMob(w http.ResponseWriter, r *http.Request) {
+ var m map[string]any
+ if err := readJSON(r, &m); err != nil {
+ http.Error(w, `{"error":"invalid json body"}`, http.StatusBadRequest)
+ return
+ }
+ id, _ := m["id"].(string)
+ if strings.TrimSpace(id) == "" {
+ http.Error(w, `{"error":"missing mob id"}`, http.StatusBadRequest)
+ return
+ }
+ if _, _, err := s.findMobFile(id); err == nil {
+ http.Error(w, `{"error":"mob already exists"}`, http.StatusConflict)
+ return
+ }
+ path := filepath.Join(s.dataDir, "mobs", id+".yaml")
+ newContent, err := writeMapAsYAML(path, m)
+ if err != nil {
+ http.Error(w, `{"error":"failed to write mob"}`, http.StatusInternalServerError)
+ return
+ }
+ s.mobStore.ReloadDefs(s.dataDir)
+ s.undoStack.Push(ChangeDesc{
+ Description: fmt.Sprintf("Create mob %s", id),
+ FilePath: path,
+ NewContent: newContent,
+ IsCreate: true,
+ })
+ writeJSON(w, m)
+}