108 lines
2.5 KiB
Go
108 lines
2.5 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
|
|
LEFT JOIN conversation_members viewer_membership
|
|
ON viewer_membership.conversation_id = c.id
|
|
AND viewer_membership.user_id = $1
|
|
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 m.created_at > COALESCE(
|
|
viewer_membership.last_cleared_at,
|
|
'-infinity'::TIMESTAMPTZ
|
|
)
|
|
AND (
|
|
EXISTS (
|
|
SELECT 1
|
|
FROM conversation_members cm
|
|
WHERE cm.conversation_id = c.id
|
|
AND cm.user_id = $1
|
|
)
|
|
OR c.is_public = true
|
|
)
|
|
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,
|
|
})
|
|
}
|