package server import ( "database/sql" "encoding/json" "net/http" "git.dustin.coffee/hobokenchicken/dumpsterChat/internal/middleware" "github.com/go-chi/chi/v5" ) type MemberHandler struct { db *sql.DB } func NewMemberHandler(db *sql.DB) *MemberHandler { return &MemberHandler{db: db} } func (h *MemberHandler) RegisterRoutes(r chi.Router) { r.Get("/members", h.ListMembers) } type memberResponse struct { ID string `json:"id"` Username string `json:"username"` DisplayName string `json:"display_name"` Avatar string `json:"avatar"` Status string `json:"status"` StatusText string `json:"status_text"` } func (h *MemberHandler) ListMembers(w http.ResponseWriter, r *http.Request) { userID, ok := middleware.UserIDFromContext(r.Context()) if !ok { http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized) return } serverID := chi.URLParam(r, "serverID") // Verify the caller is a member var exists bool err := h.db.QueryRowContext(r.Context(), `SELECT EXISTS(SELECT 1 FROM members WHERE user_id = $1 AND server_id = $2)`, userID, serverID).Scan(&exists) if err != nil || !exists { http.Error(w, `{"error":"not a member"}`, http.StatusForbidden) return } rows, err := h.db.QueryContext(r.Context(), ` SELECT u.id, u.username, u.display_name, COALESCE(u.avatar, ''), u.status, COALESCE(u.status_text, '') FROM members m JOIN users u ON u.id = m.user_id WHERE m.server_id = $1 ORDER BY u.username `, serverID) if err != nil { http.Error(w, `{"error":"server error"}`, http.StatusInternalServerError) return } defer rows.Close() members := make([]memberResponse, 0) for rows.Next() { var m memberResponse if err := rows.Scan(&m.ID, &m.Username, &m.DisplayName, &m.Avatar, &m.Status, &m.StatusText); err != nil { continue } members = append(members, m) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(members) }