package handlers import ( "encoding/json" "net/http" "strconv" "git.warky.dev/wdevs/whatshooked/pkg/events" "git.warky.dev/wdevs/whatshooked/pkg/logging" ) // GetCachedEvents returns all cached events // GET /api/cache func (h *Handlers) GetCachedEvents(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } cache := h.hookMgr.GetCache() if cache == nil || !cache.IsEnabled() { http.Error(w, "Message cache is not enabled", http.StatusServiceUnavailable) return } // Optional event_type filter eventType := r.URL.Query().Get("event_type") var cachedEvents interface{} if eventType != "" { cachedEvents = cache.ListByEventType(events.EventType(eventType)) } else { cachedEvents = cache.List() } writeJSON(w, map[string]interface{}{ "cached_events": cachedEvents, "count": cache.Count(), }) } // GetCachedEvent returns a specific cached event by ID // GET /api/cache/{id} func (h *Handlers) GetCachedEvent(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } cache := h.hookMgr.GetCache() if cache == nil || !cache.IsEnabled() { http.Error(w, "Message cache is not enabled", http.StatusServiceUnavailable) return } // Extract ID from path id := r.URL.Query().Get("id") if id == "" { http.Error(w, "Event ID required", http.StatusBadRequest) return } cached, exists := cache.Get(id) if !exists { http.Error(w, "Cached event not found", http.StatusNotFound) return } writeJSON(w, cached) } // ReplayCachedEvents replays all cached events // POST /api/cache/replay func (h *Handlers) ReplayCachedEvents(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } cache := h.hookMgr.GetCache() if cache == nil || !cache.IsEnabled() { http.Error(w, "Message cache is not enabled", http.StatusServiceUnavailable) return } logging.Info("Replaying all cached events via API") successCount, failCount, err := h.hookMgr.ReplayCachedEvents() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } writeJSON(w, map[string]interface{}{ "success": true, "replayed": successCount + failCount, "delivered": successCount, "failed": failCount, "remaining_cached": cache.Count(), }) } // ReplayCachedEvent replays a specific cached event // POST /api/cache/replay/{id} func (h *Handlers) ReplayCachedEvent(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } cache := h.hookMgr.GetCache() if cache == nil || !cache.IsEnabled() { http.Error(w, "Message cache is not enabled", http.StatusServiceUnavailable) return } // Extract ID from request body or query param var req struct { ID string `json:"id"` } // Try query param first id := r.URL.Query().Get("id") if id == "" { // Try JSON body if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "Invalid request body", http.StatusBadRequest) return } id = req.ID } if id == "" { http.Error(w, "Event ID required", http.StatusBadRequest) return } logging.Info("Replaying cached event via API", "event_id", id) if err := h.hookMgr.ReplayCachedEvent(id); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } writeJSON(w, map[string]interface{}{ "success": true, "event_id": id, "message": "Event replayed successfully", }) } // DeleteCachedEvent removes a specific cached event // DELETE /api/cache/{id} func (h *Handlers) DeleteCachedEvent(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } cache := h.hookMgr.GetCache() if cache == nil || !cache.IsEnabled() { http.Error(w, "Message cache is not enabled", http.StatusServiceUnavailable) return } id := r.URL.Query().Get("id") if id == "" { http.Error(w, "Event ID required", http.StatusBadRequest) return } logging.Info("Deleting cached event via API", "event_id", id) if err := cache.Remove(id); err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } writeJSON(w, map[string]interface{}{ "success": true, "event_id": id, "message": "Cached event deleted successfully", }) } // ClearCache removes all cached events // DELETE /api/cache func (h *Handlers) ClearCache(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } cache := h.hookMgr.GetCache() if cache == nil || !cache.IsEnabled() { http.Error(w, "Message cache is not enabled", http.StatusServiceUnavailable) return } // Optional confirmation parameter confirm := r.URL.Query().Get("confirm") confirmInt, _ := strconv.ParseBool(confirm) if !confirmInt { http.Error(w, "Add ?confirm=true to confirm cache clearing", http.StatusBadRequest) return } count := cache.Count() logging.Warn("Clearing all cached events via API", "count", count) if err := cache.Clear(); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } writeJSON(w, map[string]interface{}{ "success": true, "cleared": count, "message": "Cache cleared successfully", }) } // GetCacheStats returns cache statistics // GET /api/cache/stats func (h *Handlers) GetCacheStats(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } cache := h.hookMgr.GetCache() if cache == nil || !cache.IsEnabled() { writeJSON(w, map[string]interface{}{ "enabled": false, "count": 0, }) return } // Group by event type cachedEvents := cache.List() eventTypeCounts := make(map[string]int) for _, cached := range cachedEvents { eventTypeCounts[string(cached.Event.Type)]++ } writeJSON(w, map[string]interface{}{ "enabled": true, "total_count": cache.Count(), "by_event_type": eventTypeCounts, }) }