Rewrite to Go: engine, plugin system, D2R plugin, API, loot filter

This commit is contained in:
Hoid 2026-02-14 09:43:39 +00:00
parent e0282a7111
commit 3b363192f2
60 changed files with 1576 additions and 3407 deletions

93
pkg/api/api.go Normal file
View file

@ -0,0 +1,93 @@
// Package api provides the REST + WebSocket API for the bot dashboard.
//
// Endpoints:
// GET /api/status — bot status, current state, routine, stats
// GET /api/config — current configuration
// PUT /api/config — update configuration
// POST /api/start — start bot with routine
// POST /api/stop — stop bot
// POST /api/pause — pause/resume
// GET /api/routines — list available routines
// GET /api/loot/rules — get loot filter rules
// PUT /api/loot/rules — update loot filter rules
// GET /api/stats — run statistics, items found, etc.
// WS /api/ws — real-time status stream
//
// The API is served by the bot process itself (single binary).
package api
import (
"encoding/json"
"net/http"
"sync"
)
// Status represents the current bot status.
type Status struct {
Running bool `json:"running"`
Paused bool `json:"paused"`
GameState string `json:"gameState"`
Routine string `json:"routine,omitempty"`
Phase string `json:"phase,omitempty"`
RunCount int `json:"runCount"`
ItemsFound int `json:"itemsFound"`
Uptime string `json:"uptime"`
CaptureFPS float64 `json:"captureFps"`
HealthPct float64 `json:"healthPct"`
ManaPct float64 `json:"manaPct"`
}
// Server provides the HTTP API and WebSocket endpoint.
type Server struct {
mu sync.RWMutex
status Status
addr string
mux *http.ServeMux
}
// NewServer creates an API server on the given address.
func NewServer(addr string) *Server {
s := &Server{
addr: addr,
mux: http.NewServeMux(),
}
s.registerRoutes()
return s
}
// Start begins serving the API.
func (s *Server) Start() error {
return http.ListenAndServe(s.addr, s.mux)
}
// UpdateStatus updates the bot status (called by the engine).
func (s *Server) UpdateStatus(status Status) {
s.mu.Lock()
defer s.mu.Unlock()
s.status = status
// TODO: Broadcast to WebSocket clients
}
func (s *Server) registerRoutes() {
s.mux.HandleFunc("GET /api/status", s.handleStatus)
s.mux.HandleFunc("POST /api/start", s.handleStart)
s.mux.HandleFunc("POST /api/stop", s.handleStop)
// TODO: Remaining routes
}
func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) {
s.mu.RLock()
defer s.mu.RUnlock()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(s.status)
}
func (s *Server) handleStart(w http.ResponseWriter, r *http.Request) {
// TODO: Signal engine to start
w.WriteHeader(http.StatusAccepted)
}
func (s *Server) handleStop(w http.ResponseWriter, r *http.Request) {
// TODO: Signal engine to stop
w.WriteHeader(http.StatusAccepted)
}