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:
@@ -22,6 +22,7 @@ func NewHandler(db *sql.DB) *Handler {
|
||||
|
||||
// RegisterRoutes registers authenticated bot routes under the given router.
|
||||
func (h *Handler) RegisterRoutes(r chi.Router) {
|
||||
r.Get("/store", h.Store)
|
||||
r.Post("/", h.Create)
|
||||
r.Get("/", h.List)
|
||||
r.Get("/{botID}", h.Get)
|
||||
@@ -547,3 +548,54 @@ func (h *Handler) RegenerateToken(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
writeJSON(w, http.StatusOK, b)
|
||||
}
|
||||
|
||||
// ---- Store (public listing) ----
|
||||
|
||||
type storeBotResponse struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Avatar *string `json:"avatar"`
|
||||
Description string `json:"description"`
|
||||
ServerCount int `json:"server_count"`
|
||||
OwnerID string `json:"owner_id"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
// Store returns all bots with their server count (visible to any authenticated user).
|
||||
func (h *Handler) Store(w http.ResponseWriter, r *http.Request) {
|
||||
rows, err := h.db.QueryContext(r.Context(), `
|
||||
SELECT b.id, b.name, b.avatar, b.description, b.owner_id, b.created_at::text,
|
||||
COUNT(bs.server_id) AS server_count
|
||||
FROM bots b
|
||||
LEFT JOIN bot_servers bs ON bs.bot_id = b.id
|
||||
GROUP BY b.id, b.name, b.avatar, b.description, b.owner_id, b.created_at
|
||||
ORDER BY server_count DESC, b.name
|
||||
`)
|
||||
if err != nil {
|
||||
writeErr(w, http.StatusInternalServerError, "server error")
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
bots := make([]storeBotResponse, 0)
|
||||
for rows.Next() {
|
||||
var b storeBotResponse
|
||||
var avatar sql.NullString
|
||||
var createdAt sql.NullString
|
||||
if err := rows.Scan(&b.ID, &b.Name, &avatar, &b.Description, &b.OwnerID, &createdAt, &b.ServerCount); err != nil {
|
||||
writeErr(w, http.StatusInternalServerError, "server error")
|
||||
return
|
||||
}
|
||||
if avatar.Valid {
|
||||
b.Avatar = &avatar.String
|
||||
}
|
||||
b.CreatedAt = createdAt.String
|
||||
bots = append(bots, b)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
writeErr(w, http.StatusInternalServerError, "server error")
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, bots)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user