package handler import ( "encoding/json" "net/http" "git.yeij.top/AskaEth/Cyrene/platform-bridge/internal/bridge" "git.yeij.top/AskaEth/Cyrene/platform-bridge/internal/config" ) var knownPlatforms = map[string]bool{ "qq": true, "telegram": true, "webhook": true, "wechat": true, "feishu": true, "discord": true, } // ConfigHandler exposes CRUD endpoints for platform configs. type ConfigHandler struct { store *config.Store router *bridge.PlatformRouter } func NewConfigHandler(store *config.Store, router *bridge.PlatformRouter) *ConfigHandler { return &ConfigHandler{store: store, router: router} } func (h *ConfigHandler) RegisterRoutes(mux *http.ServeMux) { mux.HandleFunc("/api/v1/configs", h.listConfigs) mux.HandleFunc("/api/v1/configs/", h.handleConfig) } func (h *ConfigHandler) listConfigs(w http.ResponseWriter, r *http.Request) { configs := h.store.List() type configSummary struct { Name string `json:"name"` Enabled bool `json:"enabled"` Label string `json:"label,omitempty"` Fields map[string]string `json:"fields"` UpdatedAt string `json:"updated_at"` Connected bool `json:"connected"` } var result []configSummary for _, c := range configs { connected := false if a, err := h.router.GetAdapter(c.Name); err == nil { connected = a.IsConnected() } result = append(result, configSummary{ Name: c.Name, Enabled: c.Enabled, Label: c.Label, Fields: c.Fields, UpdatedAt: c.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"), Connected: connected, }) } // Also include platforms that exist as adapters but have no config yet. for _, name := range h.router.ListAdapters() { found := false for _, c := range configs { if c.Name == name { found = true break } } if !found { connected := false if a, err := h.router.GetAdapter(name); err == nil { connected = a.IsConnected() } result = append(result, configSummary{ Name: name, Enabled: false, Fields: map[string]string{}, Connected: connected, }) } } if result == nil { result = []configSummary{} } writeJSON(w, http.StatusOK, map[string]interface{}{ "configs": result, "total": len(result), }) } func (h *ConfigHandler) handleConfig(w http.ResponseWriter, r *http.Request) { name := r.URL.Path[len("/api/v1/configs/"):] if name == "" { writeJSON(w, http.StatusBadRequest, errResp("missing config name")) return } if !knownPlatforms[name] { writeJSON(w, http.StatusBadRequest, errResp("unknown platform: "+name)) return } switch r.Method { case "GET": h.getConfig(w, r, name) case "POST", "PUT": h.saveConfig(w, r, name) case "DELETE": h.deleteConfig(w, r, name) default: writeJSON(w, http.StatusMethodNotAllowed, errResp("method not allowed")) } } func (h *ConfigHandler) getConfig(w http.ResponseWriter, r *http.Request, name string) { cfg, err := h.store.Get(name) if err != nil { writeJSON(w, http.StatusNotFound, errResp(err.Error())) return } connected := false if a, err := h.router.GetAdapter(name); err == nil { connected = a.IsConnected() } writeJSON(w, http.StatusOK, map[string]interface{}{ "name": cfg.Name, "enabled": cfg.Enabled, "label": cfg.Label, "fields": cfg.Fields, "updated_at": cfg.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"), "connected": connected, }) } func (h *ConfigHandler) saveConfig(w http.ResponseWriter, r *http.Request, name string) { var body struct { Enabled *bool `json:"enabled"` Label string `json:"label"` Fields map[string]string `json:"fields"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { writeJSON(w, http.StatusBadRequest, errResp("invalid JSON: "+err.Error())) return } enabled := true if body.Enabled != nil { enabled = *body.Enabled } fields := body.Fields if fields == nil { fields = make(map[string]string) } cfg := config.PlatformConfig{ Name: name, Enabled: enabled, Label: body.Label, Fields: fields, } if err := h.store.Set(cfg); err != nil { writeJSON(w, http.StatusInternalServerError, errResp(err.Error())) return } writeJSON(w, http.StatusOK, map[string]interface{}{ "name": name, "enabled": enabled, "label": body.Label, "fields": fields, "status": "saved", }) } func (h *ConfigHandler) deleteConfig(w http.ResponseWriter, r *http.Request, name string) { if err := h.store.Delete(name); err != nil { writeJSON(w, http.StatusNotFound, errResp(err.Error())) return } writeJSON(w, http.StatusOK, map[string]string{"status": "deleted", "name": name}) }