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

98 lines
2.2 KiB
Go

package main
import (
"net/http"
"strings"
"time"
)
type ChatSearchResult struct {
ConversationID string `json:"conversationId"`
MessageID string `json:"messageId"`
Body string `json:"body"`
SenderDisplayName string `json:"senderDisplayName"`
CreatedAt time.Time `json:"createdAt"`
}
func (s *Server) handleSearchChatMessages(w http.ResponseWriter, r *http.Request) {
user, ok := userFromContext(r.Context())
if !ok {
writeError(w, http.StatusUnauthorized, "Unauthorized")
return
}
query := strings.TrimSpace(r.URL.Query().Get("q"))
if query == "" {
writeJSON(w, http.StatusOK, map[string]any{
"results": []ChatSearchResult{},
})
return
}
rows, err := s.db.Query(
r.Context(),
`
SELECT DISTINCT ON (m.conversation_id)
m.conversation_id::TEXT,
m.id::TEXT,
m.body,
COALESCE(
NULLIF(u.display_name, ''),
NULLIF(u.username, ''),
u.email,
NULLIF(c.channel_source_name, ''),
c.name,
''
),
m.created_at
FROM messages m
JOIN conversations c ON c.id = m.conversation_id
LEFT JOIN users u ON u.id = m.sender_id
WHERE m.deleted_at IS NULL
AND m.message_type = 'user'
AND (m.expires_at IS NULL OR m.expires_at > now())
AND strpos(lower(m.body), lower($2)) > 0
AND EXISTS (
SELECT 1
FROM conversation_members cm
WHERE cm.conversation_id = c.id
AND cm.user_id = $1
)
ORDER BY m.conversation_id, m.created_at DESC, m.id DESC
LIMIT 50
`,
user.ID,
query,
)
if err != nil {
writeError(w, http.StatusInternalServerError, "Chatnachrichten konnten nicht durchsucht werden")
return
}
defer rows.Close()
results := []ChatSearchResult{}
for rows.Next() {
var result ChatSearchResult
if err := rows.Scan(
&result.ConversationID,
&result.MessageID,
&result.Body,
&result.SenderDisplayName,
&result.CreatedAt,
); err != nil {
writeError(w, http.StatusInternalServerError, "Suchergebnisse konnten nicht gelesen werden")
return
}
results = append(results, result)
}
if err := rows.Err(); err != nil {
writeError(w, http.StatusInternalServerError, "Suchergebnisse konnten nicht vollständig geladen werden")
return
}
writeJSON(w, http.StatusOK, map[string]any{
"results": results,
})
}