From a502cd8fd43b35591f37720755b4095502cb28ea Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 2 Jul 2026 14:56:58 -0400 Subject: [PATCH] feat: push notifications for DMs - DM handler now sends push notifications to other conversation members - Cleared stale push subscriptions (old broken VAPID keys) - Auto-subscribe will re-create them on next page load --- cmd/server/main.go | 2 +- internal/dm/handlers.go | 32 +++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index b11d655..b723b2d 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -212,7 +212,7 @@ func main() { }) // Direct messages - dmHandler := dm.NewHandler(database.DB, hub, logger) + dmHandler := dm.NewHandler(database.DB, hub, pushHandler, logger) r.Route("/conversations", func(r chi.Router) { dmHandler.RegisterRoutes(r) }) diff --git a/internal/dm/handlers.go b/internal/dm/handlers.go index e55eed5..610eded 100644 --- a/internal/dm/handlers.go +++ b/internal/dm/handlers.go @@ -12,19 +12,21 @@ import ( "git.dustin.coffee/hobokenchicken/dumpsterChat/internal/gateway" "git.dustin.coffee/hobokenchicken/dumpsterChat/internal/middleware" + "git.dustin.coffee/hobokenchicken/dumpsterChat/internal/push" "github.com/go-chi/chi/v5" ) // Handler handles direct-message conversations. type Handler struct { - db *sql.DB - hub *gateway.Hub - logger *slog.Logger + db *sql.DB + hub *gateway.Hub + pushHandler *push.Handler + logger *slog.Logger } // NewHandler creates a new DM handler. -func NewHandler(db *sql.DB, hub *gateway.Hub, logger *slog.Logger) *Handler { - return &Handler{db: db, hub: hub, logger: logger} +func NewHandler(db *sql.DB, hub *gateway.Hub, pushHandler *push.Handler, logger *slog.Logger) *Handler { + return &Handler{db: db, hub: hub, pushHandler: pushHandler, logger: logger} } // RegisterRoutes registers conversation routes. @@ -408,6 +410,26 @@ func (h *Handler) SendMessage(w http.ResponseWriter, r *http.Request) { }) } + // Push notifications for DM participants + if h.pushHandler != nil { + go func() { + members, err := h.MemberIDs(context.Background(), convID) + if err != nil { + return + } + payload := map[string]interface{}{ + "title": msg.AuthorName, + "body": req.Content, + "url": "/conversations/" + convID, + } + for _, memberID := range members { + if memberID != userID { + h.pushHandler.SendPush(context.Background(), memberID, payload) + } + } + }() + } + w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(msg)