package notification import ( "database/sql" "encoding/json" "log/slog" "net/http" "git.dustin.coffee/hobokenchicken/dumpsterChat/internal/middleware" "github.com/go-chi/chi/v5" ) type Handler struct { db *sql.DB logger *slog.Logger } func NewHandler(db *sql.DB, logger *slog.Logger) *Handler { return &Handler{db: db, logger: logger} } func (h *Handler) RegisterRoutes(r chi.Router) { r.Put("/{channelID}/notifications", h.Set) r.Get("/me/notifications", h.GetAll) } type setNotificationRequest struct { Level string `json:"level"` } func (h *Handler) Set(w http.ResponseWriter, r *http.Request) { userID, _ := middleware.UserIDFromContext(r.Context()) channelID := chi.URLParam(r, "channelID") var req setNotificationRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, `{"error":"invalid JSON"}`, http.StatusBadRequest) return } if req.Level != "all" && req.Level != "mentions" && req.Level != "none" { http.Error(w, `{"error":"level must be all, mentions, or none"}`, http.StatusBadRequest) return } _, err := h.db.Exec(` INSERT INTO notification_settings (user_id, channel_id, level) VALUES ($1, $2, $3) ON CONFLICT (user_id, channel_id) DO UPDATE SET level = $3 `, userID, channelID, req.Level) if err != nil { h.logger.Error("failed to set notification level", "error", err, "user_id", userID, "channel_id", channelID) http.Error(w, `{"error":"internal error"}`, http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{"status": "ok", "level": req.Level}) } type ChannelSetting struct { ChannelID string `json:"channel_id"` Level string `json:"level"` } func (h *Handler) GetAll(w http.ResponseWriter, r *http.Request) { userID, _ := middleware.UserIDFromContext(r.Context()) rows, err := h.db.Query(` SELECT channel_id, level FROM notification_settings WHERE user_id = $1 `, userID) if err != nil { h.logger.Error("failed to query notification settings", "error", err) http.Error(w, `{"error":"internal error"}`, http.StatusInternalServerError) return } defer rows.Close() settings := make(map[string]string) for rows.Next() { var channelID, level string if err := rows.Scan(&channelID, &level); err != nil { continue } settings[channelID] = level } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(settings) }