Complete private Monero miner control stack.
Implement Windows agent with RandomX mining and WebSocket fleet reporting, wire dashboard settings into the builder with saved exe paths, and add project README.
This commit is contained in:
113
server/internal/api/handlers.go
Normal file
113
server/internal/api/handlers.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"crypto-miner-server/internal/db"
|
||||
"crypto-miner-server/internal/models"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
db *db.Database
|
||||
}
|
||||
|
||||
func NewHandler(database *db.Database) *Handler {
|
||||
return &Handler{db: database}
|
||||
}
|
||||
|
||||
// GET /api/v1/dashboard/stats
|
||||
func (h *Handler) GetDashboardStats(w http.ResponseWriter, r *http.Request) {
|
||||
stats, err := h.db.GetFleetStats()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeJSON(w, stats)
|
||||
}
|
||||
|
||||
// GET /api/v1/agents
|
||||
func (h *Handler) ListAgents(w http.ResponseWriter, r *http.Request) {
|
||||
agents, err := h.db.ListAgents()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if agents == nil {
|
||||
agents = []*models.Agent{}
|
||||
}
|
||||
writeJSON(w, agents)
|
||||
}
|
||||
|
||||
// GET /api/v1/agents/{id}
|
||||
func (h *Handler) GetAgent(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
agent, err := h.db.GetAgent(id)
|
||||
if err != nil {
|
||||
http.Error(w, "Agent not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
writeJSON(w, agent)
|
||||
}
|
||||
|
||||
// GET /api/v1/agents/{id}/stats
|
||||
func (h *Handler) GetAgentStats(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
limitStr := r.URL.Query().Get("limit")
|
||||
limit := 100
|
||||
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 {
|
||||
limit = l
|
||||
}
|
||||
samples, err := h.db.GetHashrateHistory(id, limit)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if samples == nil {
|
||||
samples = []*models.HashrateSample{}
|
||||
}
|
||||
writeJSON(w, samples)
|
||||
}
|
||||
|
||||
// GET /api/v1/shares
|
||||
func (h *Handler) GetRecentShares(w http.ResponseWriter, r *http.Request) {
|
||||
limitStr := r.URL.Query().Get("limit")
|
||||
limit := 50
|
||||
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 {
|
||||
limit = l
|
||||
}
|
||||
shares, err := h.db.GetRecentShares(limit)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if shares == nil {
|
||||
shares = []*models.Share{}
|
||||
}
|
||||
writeJSON(w, shares)
|
||||
}
|
||||
|
||||
// GET /api/v1/health
|
||||
func (h *Handler) HealthCheck(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
// GET /api/v1/builds
|
||||
func (h *Handler) ListBuilds(w http.ResponseWriter, r *http.Request) {
|
||||
builds, err := h.db.ListBuilds(50)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if builds == nil {
|
||||
builds = []*models.BuildRecord{}
|
||||
}
|
||||
writeJSON(w, builds)
|
||||
}
|
||||
|
||||
func writeJSON(w http.ResponseWriter, v interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(v)
|
||||
}
|
||||
Reference in New Issue
Block a user