teg/backend/chat_unread.go
2026-06-15 20:59:44 +02:00

109 lines
2.8 KiB
Go

package main
import (
"context"
"net/http"
"strings"
)
func (s *Server) markChatConversationRead(
ctx context.Context,
conversationID string,
userID string,
) error {
_, err := s.db.Exec(
ctx,
`
INSERT INTO conversation_members (
conversation_id,
user_id,
last_read_at
)
VALUES ($1, $2, now())
ON CONFLICT (conversation_id, user_id)
DO UPDATE SET last_read_at = EXCLUDED.last_read_at
`,
conversationID,
userID,
)
return err
}
func (s *Server) getChatUnreadCount(ctx context.Context, userID string) (int, error) {
var unreadCount int
err := s.db.QueryRow(
ctx,
`
SELECT COUNT(*)::INT
FROM messages m
JOIN conversations c ON c.id = m.conversation_id
LEFT JOIN conversation_members cm
ON cm.conversation_id = c.id
AND cm.user_id = $1
WHERE m.deleted_at IS NULL
AND (m.expires_at IS NULL OR m.expires_at > now())
AND m.sender_id IS DISTINCT FROM $1::UUID
AND m.created_at > COALESCE(cm.last_read_at, '-infinity'::TIMESTAMPTZ)
AND cm.user_id IS NOT NULL
`,
userID,
).Scan(&unreadCount)
return unreadCount, err
}
func (s *Server) handleGetChatUnreadCount(w http.ResponseWriter, r *http.Request) {
user, ok := userFromContext(r.Context())
if !ok {
writeError(w, http.StatusUnauthorized, "Unauthorized")
return
}
if err := s.ensureTeamGroupConversations(r.Context()); err != nil {
writeError(w, http.StatusInternalServerError, "Team-Gruppenchats konnten nicht vorbereitet werden")
return
}
if err := s.ensureAllUserChannels(r.Context(), user.ID); err != nil {
writeError(w, http.StatusInternalServerError, "Channels konnten nicht vorbereitet werden")
return
}
unreadCount, err := s.getChatUnreadCount(r.Context(), user.ID)
if err != nil {
writeError(w, http.StatusInternalServerError, "Ungelesene Nachrichten konnten nicht geladen werden")
return
}
writeJSON(w, http.StatusOK, map[string]any{
"unreadCount": unreadCount,
})
}
func (s *Server) handleMarkChatConversationRead(w http.ResponseWriter, r *http.Request) {
user, ok := userFromContext(r.Context())
if !ok {
writeError(w, http.StatusUnauthorized, "Unauthorized")
return
}
conversationID := strings.TrimSpace(r.PathValue("id"))
if !s.canAccessConversation(r.Context(), conversationID, user.ID) {
writeError(w, http.StatusForbidden, "Kein Zugriff auf diesen Chat")
return
}
if err := s.markChatConversationRead(r.Context(), conversationID, user.ID); err != nil {
writeError(w, http.StatusInternalServerError, "Lesestatus konnte nicht gespeichert werden")
return
}
unreadCount, err := s.getChatUnreadCount(r.Context(), user.ID)
if err != nil {
writeError(w, http.StatusInternalServerError, "Ungelesene Nachrichten konnten nicht geladen werden")
return
}
writeJSON(w, http.StatusOK, map[string]any{
"unreadCount": unreadCount,
})
}