187 lines
5.4 KiB
Go
187 lines
5.4 KiB
Go
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"nukumizu-backend/internal/komari"
|
|
"nukumizu-backend/internal/node"
|
|
"nukumizu-backend/internal/template"
|
|
"nukumizu-backend/postLog"
|
|
"nukumizu-backend/utils"
|
|
)
|
|
|
|
// ServerExecRequest represents the request body for POST /api/server/exec.
|
|
type ServerExecRequest struct {
|
|
UUID []string `json:"uuid"`
|
|
Command string `json:"command"`
|
|
}
|
|
|
|
// ServerInfoValue is the per-server payload returned by GET /api/server/getInfo,
|
|
// mirroring the static server info the Bot prints for /info.
|
|
type ServerInfoValue struct {
|
|
UUID string `json:"uuid"`
|
|
Name string `json:"name"`
|
|
Info *node.Info `json:"info"`
|
|
}
|
|
|
|
// ServerStatusValue is the per-server payload returned by GET /api/server/getStatus,
|
|
// mirroring the live status the Bot prints for /status. Report is null when the
|
|
// node is known but has not delivered a status report yet.
|
|
type ServerStatusValue struct {
|
|
UUID string `json:"uuid"`
|
|
Name string `json:"name"`
|
|
Online bool `json:"online"`
|
|
Report *node.Report `json:"report"`
|
|
}
|
|
|
|
// collectTargetNodes resolves the uuid query parameter into the list of nodes
|
|
// the caller asked for. uuid "all" selects every tracked node; any other uuid
|
|
// selects that single node. A boolean reports whether the uuid was found.
|
|
func collectTargetNodes(tracker *node.Tracker, uuid string) ([]*node.Node, bool) {
|
|
if uuid == "all" {
|
|
return tracker.GetAllNodes(), true
|
|
}
|
|
n, exists := tracker.GetNode(uuid)
|
|
if !exists {
|
|
return nil, false
|
|
}
|
|
return []*node.Node{n}, true
|
|
}
|
|
|
|
// ServerListHandler handles GET /api/server/list.
|
|
func ServerListHandler(w http.ResponseWriter, r *http.Request) {
|
|
if !utils.Auth(w, r, "GET", "bot") {
|
|
return
|
|
}
|
|
|
|
tracker := node.GetTracker()
|
|
if tracker == nil {
|
|
utils.SendErrorResponse(w, http.StatusInternalServerError, "node tracker not initialized")
|
|
return
|
|
}
|
|
|
|
params := template.BuildParamsFromServerList()
|
|
result := template.Render("", params)
|
|
|
|
utils.SendSuccessResponse(w, "", map[string]interface{}{
|
|
"list": result,
|
|
})
|
|
}
|
|
|
|
// ServerGetInfoHandler handles GET /api/server/getInfo?uuid=xxx|all.
|
|
// Returns the static info of the requested server(s) as a uuid-keyed object,
|
|
// mirroring the data the Bot uses for /info.
|
|
func ServerGetInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|
if !utils.Auth(w, r, "GET", "admin") {
|
|
return
|
|
}
|
|
|
|
uuid := r.URL.Query().Get("uuid")
|
|
if uuid == "" {
|
|
utils.SendErrorResponse(w, http.StatusBadRequest, "missing uuid parameter")
|
|
return
|
|
}
|
|
|
|
tracker := node.GetTracker()
|
|
if tracker == nil {
|
|
utils.SendErrorResponse(w, http.StatusInternalServerError, "node tracker not initialized")
|
|
return
|
|
}
|
|
|
|
nodes, found := collectTargetNodes(tracker, uuid)
|
|
if !found {
|
|
utils.SendErrorResponse(w, http.StatusNotFound, fmt.Sprintf("server with uuid %s not found", uuid))
|
|
return
|
|
}
|
|
|
|
result := make(map[string]interface{}, len(nodes))
|
|
for _, n := range nodes {
|
|
result[n.UUID] = ServerInfoValue{UUID: n.UUID, Name: n.Name, Info: n.Info}
|
|
}
|
|
utils.SendSuccessResponse(w, "", result)
|
|
}
|
|
|
|
// ServerGetStatusHandler handles GET /api/server/getStatus?uuid=xxx|all.
|
|
// Returns the live status of the requested server(s) as a uuid-keyed object,
|
|
// mirroring the data the Bot uses for /status.
|
|
func ServerGetStatusHandler(w http.ResponseWriter, r *http.Request) {
|
|
if !utils.Auth(w, r, "GET", "admin") {
|
|
return
|
|
}
|
|
|
|
uuid := r.URL.Query().Get("uuid")
|
|
if uuid == "" {
|
|
utils.SendErrorResponse(w, http.StatusBadRequest, "missing uuid parameter")
|
|
return
|
|
}
|
|
|
|
tracker := node.GetTracker()
|
|
if tracker == nil {
|
|
utils.SendErrorResponse(w, http.StatusInternalServerError, "node tracker not initialized")
|
|
return
|
|
}
|
|
|
|
nodes, found := collectTargetNodes(tracker, uuid)
|
|
if !found {
|
|
utils.SendErrorResponse(w, http.StatusNotFound, fmt.Sprintf("server with uuid %s not found", uuid))
|
|
return
|
|
}
|
|
|
|
result := make(map[string]interface{}, len(nodes))
|
|
for _, n := range nodes {
|
|
result[n.UUID] = ServerStatusValue{UUID: n.UUID, Name: n.Name, Online: n.Online, Report: n.LatestReport}
|
|
}
|
|
utils.SendSuccessResponse(w, "", result)
|
|
}
|
|
|
|
// ServerExecHandler handles POST /api/server/exec.
|
|
func ServerExecHandler(w http.ResponseWriter, r *http.Request) {
|
|
if !utils.Auth(w, r, "POST", "bot") {
|
|
return
|
|
}
|
|
|
|
var req ServerExecRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
utils.SendErrorResponse(w, http.StatusBadRequest, "invalid request body")
|
|
return
|
|
}
|
|
|
|
if len(req.UUID) == 0 {
|
|
utils.SendErrorResponse(w, http.StatusBadRequest, "uuid array is required")
|
|
return
|
|
}
|
|
|
|
if req.Command == "" {
|
|
utils.SendErrorResponse(w, http.StatusBadRequest, "command is required")
|
|
return
|
|
}
|
|
|
|
// Get the Komari client from the global state.
|
|
komariClient := komari.GetClient()
|
|
if komariClient == nil {
|
|
utils.SendErrorResponse(w, http.StatusInternalServerError, "komari client not initialized")
|
|
return
|
|
}
|
|
|
|
taskID, err := komariClient.ExecTask(req.UUID, req.Command)
|
|
if err != nil {
|
|
postLog.Error("Komari exec task failed: " + err.Error())
|
|
utils.SendErrorResponse(w, http.StatusInternalServerError, "failed to execute command: "+err.Error())
|
|
return
|
|
}
|
|
|
|
results, err := komariClient.PollTaskResult(taskID)
|
|
if err != nil {
|
|
postLog.Error("Komari task polling failed: " + err.Error())
|
|
utils.SendErrorResponse(w, http.StatusInternalServerError, "failed to get task result: "+err.Error())
|
|
return
|
|
}
|
|
|
|
utils.SendSuccessResponse(w, "", map[string]interface{}{
|
|
"taskID": taskID,
|
|
"results": results,
|
|
})
|
|
}
|