Add swaggo annotations to all handlers and regenerate full Swagger docs
- Added @Summary/@Router/@Param/@Success/@Security annotations to all API handlers - Regenerated docs/swagger.json, docs/swagger.yaml, docs/docs.go with full endpoint definitions - Fixed generated docs.go to remove unsupported LeftDelim/RightDelim fields
This commit is contained in:
@@ -78,6 +78,16 @@ func gravatarURL(email string) string {
|
||||
return fmt.Sprintf("https://www.gravatar.com/avatar/%s?d=identicon&s=256", hex.EncodeToString(hash[:]))
|
||||
}
|
||||
|
||||
// @Summary Register a new user
|
||||
// @Description Create a new user account
|
||||
// @Tags auth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body registerRequest true "Registration data"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /auth/register [post]
|
||||
func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
|
||||
var req registerRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -123,6 +133,16 @@ func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]string{"id": userID})
|
||||
}
|
||||
|
||||
// @Summary Login with email and password
|
||||
// @Description Authenticate with email and password
|
||||
// @Tags auth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body loginRequest true "Login credentials"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /auth/login/password [post]
|
||||
func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
|
||||
var req loginRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -156,6 +176,11 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]string{"id": userID})
|
||||
}
|
||||
|
||||
// @Summary Logout
|
||||
// @Description End the current session
|
||||
// @Tags auth
|
||||
// @Success 204
|
||||
// @Router /auth/logout [post]
|
||||
func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie(h.cfg.Session.CookieName)
|
||||
if err == nil {
|
||||
@@ -173,6 +198,14 @@ func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary Get current user profile
|
||||
// @Description Get the authenticated user's profile
|
||||
// @Tags auth
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Success 200 {object} UserProfile
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /auth/me [get]
|
||||
func (h *Handler) Me(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -190,6 +223,17 @@ func (h *Handler) Me(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(user)
|
||||
}
|
||||
|
||||
// @Summary Update current user profile
|
||||
// @Description Update the authenticated user's profile
|
||||
// @Tags auth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param body body updateProfileRequest true "Profile update data"
|
||||
// @Success 200 {object} UserProfile
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /auth/me [patch]
|
||||
func (h *Handler) UpdateProfile(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
|
||||
@@ -88,6 +88,16 @@ func (h *WebAuthnHandler) RegisterRoutes(r *http.ServeMux) {
|
||||
r.HandleFunc("POST /auth/webauthn/login/finish", h.LoginFinish)
|
||||
}
|
||||
|
||||
// @Summary Begin passkey registration
|
||||
// @Description Start passkey registration for an authenticated user
|
||||
// @Tags webauthn
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Success 200 {object} object "WebAuthn registration options"
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /auth/webauthn/register/begin [post]
|
||||
// RegisterBegin starts passkey registration for an authenticated user.
|
||||
func (h *WebAuthnHandler) RegisterBegin(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -116,6 +126,16 @@ func (h *WebAuthnHandler) RegisterBegin(w http.ResponseWriter, r *http.Request)
|
||||
json.NewEncoder(w).Encode(options)
|
||||
}
|
||||
|
||||
// @Summary Finish passkey registration
|
||||
// @Description Complete passkey registration
|
||||
// @Tags webauthn
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /auth/webauthn/register/finish [post]
|
||||
// RegisterFinish completes passkey registration.
|
||||
func (h *WebAuthnHandler) RegisterFinish(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -163,6 +183,13 @@ func (h *WebAuthnHandler) RegisterFinish(w http.ResponseWriter, r *http.Request)
|
||||
json.NewEncoder(w).Encode(map[string]string{"status": "registered"})
|
||||
}
|
||||
|
||||
// @Summary Begin passkey login
|
||||
// @Description Start passkey authentication
|
||||
// @Tags webauthn
|
||||
// @Produce json
|
||||
// @Success 200 {object} object "WebAuthn login options"
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /auth/webauthn/login/begin [post]
|
||||
// LoginBegin starts passkey authentication (no auth required).
|
||||
func (h *WebAuthnHandler) LoginBegin(w http.ResponseWriter, r *http.Request) {
|
||||
// Get all registered credentials for the login ceremony
|
||||
@@ -213,6 +240,15 @@ func (h *WebAuthnHandler) LoginBegin(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(options)
|
||||
}
|
||||
|
||||
// @Summary Finish passkey login
|
||||
// @Description Complete passkey authentication
|
||||
// @Tags webauthn
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /auth/webauthn/login/finish [post]
|
||||
// LoginFinish completes passkey authentication.
|
||||
func (h *WebAuthnHandler) LoginFinish(w http.ResponseWriter, r *http.Request) {
|
||||
// Get challenge key from cookie
|
||||
|
||||
@@ -58,6 +58,20 @@ type createCommandRequest struct {
|
||||
|
||||
// ---- handlers ----
|
||||
|
||||
// @Summary Create a slash command
|
||||
// @Description Create a new slash command for a bot
|
||||
// @Tags bot commands
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Param body body createCommandRequest true "Command data"
|
||||
// @Success 201 {object} slashCommandResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /bots/{botID}/commands [post]
|
||||
func (h *CommandHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -131,6 +145,17 @@ func (h *CommandHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusCreated, cmd)
|
||||
}
|
||||
|
||||
// @Summary List bot commands
|
||||
// @Description List all slash commands for a bot
|
||||
// @Tags bot commands
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Success 200 {array} slashCommandResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID}/commands [get]
|
||||
func (h *CommandHandler) ListByBot(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -180,6 +205,17 @@ func (h *CommandHandler) ListByBot(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, cmds)
|
||||
}
|
||||
|
||||
// @Summary Delete a slash command
|
||||
// @Description Delete a slash command
|
||||
// @Tags bot commands
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Param cmdID path string true "Command ID"
|
||||
// @Success 204
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID}/commands/{cmdID} [delete]
|
||||
func (h *CommandHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -217,7 +253,14 @@ func (h *CommandHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// ListByServer returns all slash commands registered in a server (public, no auth).
|
||||
// @Summary List server commands
|
||||
// @Description List all slash commands registered in a server (public)
|
||||
// @Tags bot commands
|
||||
// @Produce json
|
||||
// @Param serverID path string true "Server ID"
|
||||
// @Success 200 {array} slashCommandResponse
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /bots/servers/{serverID}/commands [get]
|
||||
func (h *CommandHandler) ListByServer(w http.ResponseWriter, r *http.Request) {
|
||||
serverID := chi.URLParam(r, "serverID")
|
||||
|
||||
|
||||
@@ -78,6 +78,17 @@ func writeErr(w http.ResponseWriter, status int, msg string) {
|
||||
|
||||
// ---- handlers ----
|
||||
|
||||
// @Summary Create a bot
|
||||
// @Description Create a new bot
|
||||
// @Tags bots
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param body body createBotRequest true "Bot data"
|
||||
// @Success 201 {object} botWithToken
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /bots [post]
|
||||
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -121,6 +132,14 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusCreated, bot)
|
||||
}
|
||||
|
||||
// @Summary List bots
|
||||
// @Description List all bots owned by the current user
|
||||
// @Tags bots
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Success 200 {array} botResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /bots [get]
|
||||
func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -161,6 +180,17 @@ func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, bots)
|
||||
}
|
||||
|
||||
// @Summary Get a bot
|
||||
// @Description Get a bot by ID (owner only)
|
||||
// @Tags bots
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Success 200 {object} botResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID} [get]
|
||||
func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -197,6 +227,20 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, b)
|
||||
}
|
||||
|
||||
// @Summary Update a bot
|
||||
// @Description Update a bot's name, description, or avatar (owner only)
|
||||
// @Tags bots
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Param body body updateBotRequest true "Bot update data"
|
||||
// @Success 200 {object} botResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID} [patch]
|
||||
func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -259,6 +303,16 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, b)
|
||||
}
|
||||
|
||||
// @Summary Delete a bot
|
||||
// @Description Delete a bot (owner only)
|
||||
// @Tags bots
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Success 204
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID} [delete]
|
||||
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -294,6 +348,20 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary Add bot to server
|
||||
// @Description Add a bot to a server
|
||||
// @Tags bots
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Param body body addToServerRequest true "Server data"
|
||||
// @Success 201 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID}/servers [post]
|
||||
func (h *Handler) AddToServer(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -361,6 +429,17 @@ func (h *Handler) AddToServer(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary Remove bot from server
|
||||
// @Description Remove a bot from a server
|
||||
// @Tags bots
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Param serverID path string true "Server ID"
|
||||
// @Success 204
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID}/servers/{serverID} [delete]
|
||||
func (h *Handler) RemoveFromServer(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -405,6 +484,17 @@ func (h *Handler) RemoveFromServer(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary Regenerate bot token
|
||||
// @Description Regenerate a bot's API token (owner only)
|
||||
// @Tags bots
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param botID path string true "Bot ID"
|
||||
// @Success 200 {object} botWithToken
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /bots/{botID}/regenerate-token [post]
|
||||
func (h *Handler) RegenerateToken(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
|
||||
@@ -63,6 +63,18 @@ func (h *Handler) serverIDForChannel(ctx context.Context, channelID string) (str
|
||||
return serverID, err
|
||||
}
|
||||
|
||||
// @Summary Create a channel
|
||||
// @Description Create a new channel in a server
|
||||
// @Tags channels
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param body body createChannelRequest true "Channel data"
|
||||
// @Success 201 {object} channelResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Router /servers/{serverID}/channels [post]
|
||||
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -121,6 +133,17 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(ch)
|
||||
}
|
||||
|
||||
// @Summary List channels
|
||||
// @Description List channels in a server
|
||||
// @Tags channels
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param server_id query string true "Server ID"
|
||||
// @Success 200 {array} channelResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Router /servers/{serverID}/channels [get]
|
||||
func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -174,6 +197,17 @@ func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(channels)
|
||||
}
|
||||
|
||||
// @Summary Get a channel
|
||||
// @Description Get a channel by ID
|
||||
// @Tags channels
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Success 200 {object} channelResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /servers/{serverID}/channels/{channelID} [get]
|
||||
func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -218,6 +252,20 @@ type updateChannelRequest struct {
|
||||
Position *int `json:"position"`
|
||||
}
|
||||
|
||||
// @Summary Update a channel
|
||||
// @Description Update a channel's properties
|
||||
// @Tags channels
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Param body body updateChannelRequest true "Channel update data"
|
||||
// @Success 200 {object} channelResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /servers/{serverID}/channels/{channelID} [patch]
|
||||
func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -279,6 +327,16 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(ch)
|
||||
}
|
||||
|
||||
// @Summary Delete a channel
|
||||
// @Description Delete a channel (server owner only)
|
||||
// @Tags channels
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Success 204
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /servers/{serverID}/channels/{channelID} [delete]
|
||||
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
|
||||
@@ -61,6 +61,18 @@ func generateCode(length int) (string, error) {
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
// @Summary Create an invite
|
||||
// @Description Create an invite code for a server
|
||||
// @Tags invites
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param serverID path string true "Server ID"
|
||||
// @Param body body createInviteRequest false "Invite options"
|
||||
// @Success 201 {object} inviteResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Router /servers/{serverID}/invites [post]
|
||||
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
serverID := chi.URLParam(r, "serverID")
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -163,6 +175,14 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(invite)
|
||||
}
|
||||
|
||||
// @Summary Get invite info
|
||||
// @Description Get information about an invite by code
|
||||
// @Tags invites
|
||||
// @Produce json
|
||||
// @Param code path string true "Invite code"
|
||||
// @Success 200 {object} inviteResponse
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /invites/{code} [get]
|
||||
func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
code := chi.URLParam(r, "code")
|
||||
|
||||
@@ -197,6 +217,18 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(invite)
|
||||
}
|
||||
|
||||
// @Summary Join server via invite
|
||||
// @Description Join a server using an invite code
|
||||
// @Tags invites
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param code path string true "Invite code"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /invites/{code}/join [post]
|
||||
func (h *Handler) Join(w http.ResponseWriter, r *http.Request) {
|
||||
code := chi.URLParam(r, "code")
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
|
||||
@@ -61,6 +61,19 @@ type createMessageRequest struct {
|
||||
ReplyTo *string `json:"reply_to,omitempty"`
|
||||
}
|
||||
|
||||
// @Summary Create a message
|
||||
// @Description Send a message to a channel
|
||||
// @Tags messages
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Param body body createMessageRequest true "Message data"
|
||||
// @Success 201 {object} messageResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Router /channels/{channelID}/messages [post]
|
||||
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
channelID := chi.URLParam(r, "channelID")
|
||||
userID, ok := h.requireChannelAccess(w, r, channelID)
|
||||
@@ -129,6 +142,20 @@ type updateMessageRequest struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// @Summary Update a message
|
||||
// @Description Edit a message (author only)
|
||||
// @Tags messages
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Param messageID path string true "Message ID"
|
||||
// @Param body body updateMessageRequest true "Message update data"
|
||||
// @Success 200 {object} messageResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /channels/{channelID}/messages/{messageID} [patch]
|
||||
func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||
messageID := chi.URLParam(r, "messageID")
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -188,6 +215,16 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(msg)
|
||||
}
|
||||
|
||||
// @Summary Delete a message
|
||||
// @Description Delete a message (author only)
|
||||
// @Tags messages
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Param messageID path string true "Message ID"
|
||||
// @Success 204
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /channels/{channelID}/messages/{messageID} [delete]
|
||||
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
messageID := chi.URLParam(r, "messageID")
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -221,6 +258,18 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary List messages
|
||||
// @Description List messages in a channel with pagination
|
||||
// @Tags messages
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Param limit query int false "Max messages to return (1-100, default 50)"
|
||||
// @Param before query string false "Message ID to fetch messages before"
|
||||
// @Success 200 {array} messageResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Router /channels/{channelID}/messages [get]
|
||||
func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
channelID := chi.URLParam(r, "channelID")
|
||||
userID, ok := h.requireChannelAccess(w, r, channelID)
|
||||
|
||||
@@ -37,11 +37,28 @@ func (h *Handler) RegisterRoutes(r *http.ServeMux) {
|
||||
r.HandleFunc("GET /push/vapid-public-key", h.GetPublicKey)
|
||||
}
|
||||
|
||||
// @Summary Get VAPID public key
|
||||
// @Description Get the VAPID public key for push notification subscriptions
|
||||
// @Tags push
|
||||
// @Produce json
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Router /push/vapid-public-key [get]
|
||||
func (h *Handler) GetPublicKey(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{"publicKey": h.vapidPub})
|
||||
}
|
||||
|
||||
// @Summary Subscribe to push notifications
|
||||
// @Description Subscribe to push notifications
|
||||
// @Tags push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param body body object true "Push subscription with endpoint, p256dh, and auth"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /push/subscribe [post]
|
||||
func (h *Handler) Subscribe(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -75,6 +92,17 @@ func (h *Handler) Subscribe(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]string{"status": "subscribed"})
|
||||
}
|
||||
|
||||
// @Summary Unsubscribe from push notifications
|
||||
// @Description Unsubscribe from push notifications
|
||||
// @Tags push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param body body object true "Endpoint to unsubscribe"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /push/unsubscribe [post]
|
||||
func (h *Handler) Unsubscribe(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
|
||||
@@ -99,6 +99,19 @@ func (h *Handler) requireMessageAccess(w http.ResponseWriter, r *http.Request, m
|
||||
return userID, channelID, serverID, true
|
||||
}
|
||||
|
||||
// @Summary Add a reaction
|
||||
// @Description Add a reaction to a message
|
||||
// @Tags reactions
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param messageID path string true "Message ID"
|
||||
// @Param body body addReactionRequest true "Reaction data"
|
||||
// @Success 201 {object} reactionResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Router /messages/{messageID}/reactions [post]
|
||||
func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||
messageID := chi.URLParam(r, "messageID")
|
||||
userID, channelID, _, ok := h.requireMessageAccess(w, r, messageID)
|
||||
@@ -146,6 +159,17 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(reaction)
|
||||
}
|
||||
|
||||
// @Summary Remove a reaction
|
||||
// @Description Remove a reaction from a message
|
||||
// @Tags reactions
|
||||
// @Security SessionAuth
|
||||
// @Param messageID path string true "Message ID"
|
||||
// @Param emoji path string true "Emoji to remove"
|
||||
// @Success 204
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /messages/{messageID}/reactions/{emoji} [delete]
|
||||
func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
messageID := chi.URLParam(r, "messageID")
|
||||
emoji := chi.URLParam(r, "emoji")
|
||||
@@ -185,6 +209,16 @@ func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary List reactions
|
||||
// @Description List reactions on a message grouped by emoji
|
||||
// @Tags reactions
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param messageID path string true "Message ID"
|
||||
// @Success 200 {array} emojiGroup
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Router /messages/{messageID}/reactions [get]
|
||||
func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
messageID := chi.URLParam(r, "messageID")
|
||||
if _, _, _, ok := h.requireMessageAccess(w, r, messageID); !ok {
|
||||
|
||||
@@ -39,6 +39,18 @@ type tokenResponse struct {
|
||||
LiveKitURL string `json:"livekit_url"`
|
||||
}
|
||||
|
||||
// @Summary Get voice token
|
||||
// @Description Get a LiveKit access token for a voice room
|
||||
// @Tags voice
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param body body tokenRequest true "Room data"
|
||||
// @Success 200 {object} tokenResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /voice/token [post]
|
||||
func (h *Handler) GetToken(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
@@ -94,6 +106,15 @@ func (h *Handler) GetToken(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary Get voice room participants
|
||||
// @Description Get participants in a voice room
|
||||
// @Tags voice
|
||||
// @Produce json
|
||||
// @Param roomID path string true "Room ID"
|
||||
// @Success 200 {array} object
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /voice/rooms/{roomID}/participants [get]
|
||||
func (h *Handler) GetParticipants(w http.ResponseWriter, r *http.Request) {
|
||||
roomID := chi.URLParam(r, "roomID")
|
||||
if roomID == "" {
|
||||
|
||||
@@ -82,6 +82,20 @@ func writeErr(w http.ResponseWriter, status int, msg string) {
|
||||
|
||||
// ---- handlers ----
|
||||
|
||||
// @Summary Create a webhook
|
||||
// @Description Create a new webhook for a channel
|
||||
// @Tags webhooks
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Param body body createWebhookRequest true "Webhook data"
|
||||
// @Success 201 {object} webhookWithToken
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /channels/{channelID}/webhooks [post]
|
||||
// Create creates a new webhook for a channel.
|
||||
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -148,6 +162,17 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusCreated, wh)
|
||||
}
|
||||
|
||||
// @Summary List webhooks
|
||||
// @Description List webhooks for a channel
|
||||
// @Tags webhooks
|
||||
// @Produce json
|
||||
// @Security SessionAuth
|
||||
// @Param channelID path string true "Channel ID"
|
||||
// @Success 200 {array} webhookResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /channels/{channelID}/webhooks [get]
|
||||
// List returns all webhooks for a channel.
|
||||
func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -211,6 +236,16 @@ func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, webhooks)
|
||||
}
|
||||
|
||||
// @Summary Delete a webhook
|
||||
// @Description Delete a webhook
|
||||
// @Tags webhooks
|
||||
// @Security SessionAuth
|
||||
// @Param webhookID path string true "Webhook ID"
|
||||
// @Success 204
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /webhooks/{webhookID} [delete]
|
||||
// Delete removes a webhook.
|
||||
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
userID, ok := middleware.UserIDFromContext(r.Context())
|
||||
@@ -247,6 +282,19 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary Execute a webhook
|
||||
// @Description Execute a webhook to send a message (no auth required)
|
||||
// @Tags webhooks
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param webhookID path string true "Webhook ID"
|
||||
// @Param token path string true "Webhook token"
|
||||
// @Param body body executeWebhookRequest true "Message data"
|
||||
// @Success 201 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /webhooks/{webhookID}/{token} [post]
|
||||
// Execute sends a message to a channel via webhook (no auth required).
|
||||
func (h *Handler) Execute(w http.ResponseWriter, r *http.Request) {
|
||||
webhookID := chi.URLParam(r, "webhookID")
|
||||
|
||||
Reference in New Issue
Block a user