feat(bots): bot framework polish + store
- /ws/bot endpoint: bot token auth via query param, SHA-256 lookup
- Bot WS actions: SEND_MESSAGE + DELETE_MESSAGE handled in gateway
- Bot messages: bot_id on messages table, bot badge in chat (green + BOT tag)
- Bot store: /bots lists all bots with server count + add-to-server
- Bot manager moved to /bots/manage
- Fix: command routes were double-nested under /bots/{botID}/commands
- Fix: fetchServerCommands route corrected to /bots/servers/...
This commit is contained in:
@@ -159,6 +159,9 @@ type messageResponse struct {
|
||||
AuthorID string `json:"author_id"`
|
||||
AuthorName string `json:"author_username"`
|
||||
DisplayName *string `json:"author_display_name"`
|
||||
AuthorBot bool `json:"author_bot"`
|
||||
BotID *string `json:"bot_id,omitempty"`
|
||||
BotName *string `json:"bot_name,omitempty"`
|
||||
Content string `json:"content"`
|
||||
ReplyTo *string `json:"reply_to,omitempty"`
|
||||
EditedAt *string `json:"edited_at"`
|
||||
@@ -505,18 +508,20 @@ func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
if before != "" {
|
||||
rows, err = h.db.QueryContext(r.Context(), `
|
||||
SELECT m.id, m.channel_id, m.author_id, u.username, u.display_name, m.content, m.reply_to::text, m.edited_at::text, m.pinned, m.created_at::text
|
||||
SELECT m.id, m.channel_id, m.author_id, u.username, u.display_name, m.content, m.reply_to::text, m.edited_at::text, m.pinned, m.created_at::text, m.bot_id, b.name
|
||||
FROM messages m
|
||||
JOIN users u ON m.author_id = u.id
|
||||
LEFT JOIN bots b ON m.bot_id = b.id
|
||||
WHERE m.channel_id = $1 AND m.created_at < (SELECT created_at FROM messages WHERE id = $2)
|
||||
ORDER BY m.created_at DESC
|
||||
LIMIT $3
|
||||
`, channelID, before, limit)
|
||||
} else {
|
||||
rows, err = h.db.QueryContext(r.Context(), `
|
||||
SELECT m.id, m.channel_id, m.author_id, u.username, u.display_name, m.content, m.reply_to::text, m.edited_at::text, m.pinned, m.created_at::text
|
||||
SELECT m.id, m.channel_id, m.author_id, u.username, u.display_name, m.content, m.reply_to::text, m.edited_at::text, m.pinned, m.created_at::text, m.bot_id, b.name
|
||||
FROM messages m
|
||||
JOIN users u ON m.author_id = u.id
|
||||
LEFT JOIN bots b ON m.bot_id = b.id
|
||||
WHERE m.channel_id = $1
|
||||
ORDER BY m.created_at DESC
|
||||
LIMIT $2
|
||||
@@ -534,7 +539,9 @@ func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
var editedAt sql.NullString
|
||||
var createdAt sql.NullString
|
||||
var replyTo sql.NullString
|
||||
err := rows.Scan(&msg.ID, &msg.ChannelID, &msg.AuthorID, &msg.AuthorName, &msg.DisplayName, &msg.Content, &replyTo, &editedAt, &msg.Pinned, &createdAt)
|
||||
var botID sql.NullString
|
||||
var botName sql.NullString
|
||||
err := rows.Scan(&msg.ID, &msg.ChannelID, &msg.AuthorID, &msg.AuthorName, &msg.DisplayName, &msg.Content, &replyTo, &editedAt, &msg.Pinned, &createdAt, &botID, &botName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -544,6 +551,13 @@ func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
if editedAt.Valid {
|
||||
msg.EditedAt = &editedAt.String
|
||||
}
|
||||
if botID.Valid {
|
||||
msg.BotID = &botID.String
|
||||
msg.AuthorBot = true
|
||||
}
|
||||
if botName.Valid {
|
||||
msg.BotName = &botName.String
|
||||
}
|
||||
msg.CreatedAt = createdAt.String
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
@@ -802,9 +816,10 @@ func (h *Handler) Search(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
rows, err := h.db.QueryContext(r.Context(), `
|
||||
SELECT m.id, m.channel_id, m.author_id, u.username, u.display_name, m.content, m.reply_to::text, m.edited_at::text, m.pinned, m.created_at::text,
|
||||
ts_rank(m.search_vector, plainto_tsquery('english', $2)) AS rank
|
||||
ts_rank(m.search_vector, plainto_tsquery('english', $2)) AS rank, m.bot_id, b.name
|
||||
FROM messages m
|
||||
JOIN users u ON m.author_id = u.id
|
||||
LEFT JOIN bots b ON m.bot_id = b.id
|
||||
WHERE m.channel_id = $1 AND m.search_vector @@ plainto_tsquery('english', $2)
|
||||
ORDER BY rank DESC, m.created_at DESC
|
||||
LIMIT $3
|
||||
@@ -822,7 +837,9 @@ func (h *Handler) Search(w http.ResponseWriter, r *http.Request) {
|
||||
var createdAt sql.NullString
|
||||
var replyTo sql.NullString
|
||||
var rank float64
|
||||
err := rows.Scan(&msg.ID, &msg.ChannelID, &msg.AuthorID, &msg.AuthorName, &msg.DisplayName, &msg.Content, &replyTo, &editedAt, &msg.Pinned, &createdAt, &rank)
|
||||
var botID sql.NullString
|
||||
var botName sql.NullString
|
||||
err := rows.Scan(&msg.ID, &msg.ChannelID, &msg.AuthorID, &msg.AuthorName, &msg.DisplayName, &msg.Content, &replyTo, &editedAt, &msg.Pinned, &createdAt, &rank, &botID, &botName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -832,6 +849,13 @@ func (h *Handler) Search(w http.ResponseWriter, r *http.Request) {
|
||||
if editedAt.Valid {
|
||||
msg.EditedAt = &editedAt.String
|
||||
}
|
||||
if botID.Valid {
|
||||
msg.BotID = &botID.String
|
||||
msg.AuthorBot = true
|
||||
}
|
||||
if botName.Valid {
|
||||
msg.BotName = &botName.String
|
||||
}
|
||||
msg.CreatedAt = createdAt.String
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
@@ -1059,9 +1083,10 @@ func (h *Handler) ListPinned(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
rows, err := h.db.QueryContext(r.Context(), `
|
||||
SELECT m.id, m.channel_id, m.author_id, u.username, u.display_name, m.content, m.reply_to::text, m.edited_at::text, m.pinned, m.created_at::text
|
||||
SELECT m.id, m.channel_id, m.author_id, u.username, u.display_name, m.content, m.reply_to::text, m.edited_at::text, m.pinned, m.created_at::text, m.bot_id, b.name
|
||||
FROM messages m
|
||||
JOIN users u ON m.author_id = u.id
|
||||
LEFT JOIN bots b ON m.bot_id = b.id
|
||||
WHERE m.channel_id = $1 AND m.pinned = TRUE
|
||||
ORDER BY m.created_at DESC
|
||||
`, channelID)
|
||||
@@ -1077,7 +1102,9 @@ func (h *Handler) ListPinned(w http.ResponseWriter, r *http.Request) {
|
||||
var editedAt sql.NullString
|
||||
var createdAt sql.NullString
|
||||
var replyTo sql.NullString
|
||||
err := rows.Scan(&msg.ID, &msg.ChannelID, &msg.AuthorID, &msg.AuthorName, &msg.DisplayName, &msg.Content, &replyTo, &editedAt, &msg.Pinned, &createdAt)
|
||||
var botID sql.NullString
|
||||
var botName sql.NullString
|
||||
err := rows.Scan(&msg.ID, &msg.ChannelID, &msg.AuthorID, &msg.AuthorName, &msg.DisplayName, &msg.Content, &replyTo, &editedAt, &msg.Pinned, &createdAt, &botID, &botName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -1087,6 +1114,13 @@ func (h *Handler) ListPinned(w http.ResponseWriter, r *http.Request) {
|
||||
if editedAt.Valid {
|
||||
msg.EditedAt = &editedAt.String
|
||||
}
|
||||
if botID.Valid {
|
||||
msg.BotID = &botID.String
|
||||
msg.AuthorBot = true
|
||||
}
|
||||
if botName.Valid {
|
||||
msg.BotName = &botName.String
|
||||
}
|
||||
msg.CreatedAt = createdAt.String
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user