mirror of
https://github.com/lone-cloud/prism
synced 2026-06-03 08:43:10 -07:00
153 lines
4.5 KiB
Go
153 lines
4.5 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log/slog"
|
|
"net/http"
|
|
"time"
|
|
|
|
"prism/internal/notification"
|
|
"prism/internal/util"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
func (s *Server) handleGetMappings(w http.ResponseWriter, r *http.Request) {
|
|
mappings, err := s.store.GetAllMappings()
|
|
if err != nil {
|
|
s.logger.Error("Failed to get mappings", "error", err)
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(mappings); err != nil {
|
|
slog.Error("Failed to encode response", "error", err)
|
|
}
|
|
}
|
|
|
|
type createMappingRequest struct {
|
|
Endpoint string `json:"endpoint"`
|
|
AppName string `json:"appName"`
|
|
Channel notification.Channel `json:"channel"`
|
|
UpEndpoint *string `json:"upEndpoint,omitempty"`
|
|
}
|
|
|
|
func (s *Server) handleCreateMapping(w http.ResponseWriter, r *http.Request) {
|
|
var req createMappingRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.Endpoint == "" || req.AppName == "" {
|
|
http.Error(w, "Missing required fields", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.Channel == "" {
|
|
req.Channel = notification.ChannelSignal
|
|
}
|
|
|
|
if req.Channel == notification.ChannelWebhook && req.UpEndpoint == nil {
|
|
http.Error(w, "upEndpoint required for webhook channel", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := s.store.Register(req.Endpoint, req.AppName, req.Channel, nil, req.UpEndpoint); err != nil {
|
|
s.logger.Error("Failed to register mapping", "error", err)
|
|
http.Error(w, "Failed to create mapping", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
if err := json.NewEncoder(w).Encode(map[string]string{"status": "created"}); err != nil {
|
|
s.logger.Error("Failed to encode response", "error", err)
|
|
}
|
|
}
|
|
|
|
func (s *Server) handleDeleteMapping(w http.ResponseWriter, r *http.Request) {
|
|
endpoint := chi.URLParam(r, "endpoint")
|
|
if endpoint == "" {
|
|
http.Error(w, "Missing endpoint parameter", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := s.store.RemoveEndpoint(endpoint); err != nil {
|
|
s.logger.Error("Failed to delete mapping", "error", err)
|
|
http.Error(w, "Failed to delete mapping", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
type updateChannelRequest struct {
|
|
Channel notification.Channel `json:"channel"`
|
|
UpEndpoint *string `json:"upEndpoint,omitempty"`
|
|
}
|
|
|
|
func (s *Server) handleUpdateChannel(w http.ResponseWriter, r *http.Request) {
|
|
endpoint := chi.URLParam(r, "endpoint")
|
|
if endpoint == "" {
|
|
http.Error(w, "Missing endpoint parameter", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req updateChannelRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.Channel == notification.ChannelWebhook && req.UpEndpoint == nil {
|
|
http.Error(w, "upEndpoint required for webhook channel", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := s.store.UpdateChannel(endpoint, req.Channel); err != nil {
|
|
s.logger.Error("Failed to update channel", "error", err)
|
|
http.Error(w, "Failed to update channel", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(map[string]string{"status": "updated"}); err != nil {
|
|
s.logger.Error("Failed to encode response", "error", err)
|
|
}
|
|
}
|
|
|
|
func (s *Server) handleGetStats(w http.ResponseWriter, r *http.Request) {
|
|
mappings, err := s.store.GetAllMappings()
|
|
if err != nil {
|
|
s.logger.Error("Failed to get mappings", "error", err)
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
uptime := time.Since(s.startTime)
|
|
|
|
stats := map[string]interface{}{
|
|
"uptime": util.FormatUptime(uptime),
|
|
"uptimeSeconds": int(uptime.Seconds()),
|
|
"mappingsCount": len(mappings),
|
|
"signalCount": countByChannel(mappings, notification.ChannelSignal),
|
|
"webhookCount": countByChannel(mappings, notification.ChannelWebhook),
|
|
"protonEnabled": s.cfg.IsProtonEnabled(),
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(stats); err != nil {
|
|
s.logger.Error("Failed to encode response", "error", err)
|
|
}
|
|
}
|
|
|
|
func countByChannel(mappings []notification.Mapping, channel notification.Channel) int {
|
|
count := 0
|
|
for _, m := range mappings {
|
|
if m.Channel == channel {
|
|
count++
|
|
}
|
|
}
|
|
return count
|
|
}
|