Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
102 lines
3.2 KiB
Go
102 lines
3.2 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type playerStatusRequest struct {
|
|
ScreenID string `json:"screen_id"`
|
|
Timestamp string `json:"ts"`
|
|
Status string `json:"status"`
|
|
ServerConnectivity string `json:"server_connectivity"`
|
|
ServerURL string `json:"server_url"`
|
|
MQTTBroker string `json:"mqtt_broker"`
|
|
HeartbeatEverySeconds int `json:"heartbeat_every_seconds"`
|
|
StartedAt string `json:"started_at"`
|
|
LastHeartbeatAt string `json:"last_heartbeat_at"`
|
|
}
|
|
|
|
func handlePlayerStatus(store playerStatusStore) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
var request playerStatusRequest
|
|
if err := decodeJSON(r, &request); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid_json", "ungueltiger JSON-Body", nil)
|
|
return
|
|
}
|
|
|
|
if strings.TrimSpace(request.ScreenID) == "" {
|
|
writeError(w, http.StatusBadRequest, "screen_id_required", "screen_id ist erforderlich", nil)
|
|
return
|
|
}
|
|
|
|
if strings.TrimSpace(request.Timestamp) == "" {
|
|
writeError(w, http.StatusBadRequest, "timestamp_required", "ts ist erforderlich", nil)
|
|
return
|
|
}
|
|
|
|
if strings.TrimSpace(request.Status) == "" {
|
|
writeError(w, http.StatusBadRequest, "status_required", "status ist erforderlich", nil)
|
|
return
|
|
}
|
|
|
|
if err := validateOptionalRFC3339(request.Timestamp); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid_timestamp", "ts ist kein gueltiger RFC3339-Zeitstempel", nil)
|
|
return
|
|
}
|
|
|
|
if err := validateOptionalRFC3339(request.StartedAt); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid_started_at", "started_at ist kein gueltiger RFC3339-Zeitstempel", nil)
|
|
return
|
|
}
|
|
|
|
if err := validateOptionalRFC3339(request.LastHeartbeatAt); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid_last_heartbeat_at", "last_heartbeat_at ist kein gueltiger RFC3339-Zeitstempel", nil)
|
|
return
|
|
}
|
|
|
|
store.Save(playerStatusRecord{
|
|
ScreenID: request.ScreenID,
|
|
Timestamp: request.Timestamp,
|
|
Status: request.Status,
|
|
ServerConnectivity: request.ServerConnectivity,
|
|
ServerURL: request.ServerURL,
|
|
MQTTBroker: request.MQTTBroker,
|
|
HeartbeatEverySeconds: request.HeartbeatEverySeconds,
|
|
StartedAt: request.StartedAt,
|
|
LastHeartbeatAt: request.LastHeartbeatAt,
|
|
})
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{
|
|
"status": "accepted",
|
|
})
|
|
}
|
|
}
|
|
|
|
func handleGetLatestPlayerStatus(store playerStatusStore) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
screenID := strings.TrimSpace(r.PathValue("screenId"))
|
|
if screenID == "" {
|
|
writeError(w, http.StatusBadRequest, "screen_id_required", "screenId ist erforderlich", nil)
|
|
return
|
|
}
|
|
|
|
record, ok := store.Get(screenID)
|
|
if !ok {
|
|
writeError(w, http.StatusNotFound, "screen_status_not_found", "Fuer diesen Screen liegt noch kein Status vor", nil)
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, record)
|
|
}
|
|
}
|
|
|
|
func validateOptionalRFC3339(value string) error {
|
|
if strings.TrimSpace(value) == "" {
|
|
return nil
|
|
}
|
|
|
|
_, err := time.Parse(time.RFC3339, value)
|
|
return err
|
|
}
|