171 lines
5.8 KiB
Go
171 lines
5.8 KiB
Go
package v1
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/gochat/gochat/internal/service"
|
|
applogger "github.com/gochat/gochat/pkg/logger"
|
|
"github.com/gochat/gochat/pkg/pagination"
|
|
"github.com/gochat/gochat/pkg/response"
|
|
)
|
|
|
|
// CaptainDocumentHandler handles CaptainDocument REST API endpoints.
|
|
// Reference: Chatwoot enterprise/app/controllers/api/v1/captain/documents_controller.rb
|
|
type CaptainDocumentHandler struct {
|
|
svc *service.CaptainDocumentService
|
|
}
|
|
|
|
// NewCaptainDocumentHandler creates a new CaptainDocumentHandler.
|
|
func NewCaptainDocumentHandler(svc *service.CaptainDocumentService) *CaptainDocumentHandler {
|
|
return &CaptainDocumentHandler{svc: svc}
|
|
}
|
|
|
|
// Create creates a new captain document.
|
|
// POST /api/v1/accounts/:account_id/captain_assistants/:assistant_id/documents
|
|
func (h *CaptainDocumentHandler) Create(c *gin.Context) {
|
|
accountID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id")
|
|
return
|
|
}
|
|
assistantID, err := strconv.ParseUint(c.Param("assistant_id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid assistant_id")
|
|
return
|
|
}
|
|
|
|
var req service.CreateDocumentRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
|
|
return
|
|
}
|
|
|
|
doc, err := h.svc.Create(c.Request.Context(), uint(assistantID), uint(accountID), &req)
|
|
if err != nil {
|
|
applogger.L().Errorf("Create captain document: %v", err)
|
|
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to create document")
|
|
return
|
|
}
|
|
|
|
response.Created(c, doc)
|
|
}
|
|
|
|
// Get retrieves a captain document by ID.
|
|
// GET /api/v1/accounts/:account_id/captain_documents/:id
|
|
func (h *CaptainDocumentHandler) Get(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
doc, err := h.svc.Get(c.Request.Context(), uint(id))
|
|
if err != nil {
|
|
applogger.L().Errorf("Get captain document: %v", err)
|
|
response.AbortWithStatusError(c, http.StatusNotFound, response.ErrNotFound, "document not found")
|
|
return
|
|
}
|
|
|
|
response.OK(c, doc)
|
|
}
|
|
|
|
// Update updates an existing captain document.
|
|
// PUT /api/v1/accounts/:account_id/captain_documents/:id
|
|
func (h *CaptainDocumentHandler) Update(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
var req service.UpdateDocumentRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
|
|
return
|
|
}
|
|
|
|
doc, err := h.svc.Update(c.Request.Context(), uint(id), &req)
|
|
if err != nil {
|
|
applogger.L().Errorf("Update captain document: %v", err)
|
|
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to update document")
|
|
return
|
|
}
|
|
|
|
response.OK(c, doc)
|
|
}
|
|
|
|
// Delete deletes a captain document.
|
|
// DELETE /api/v1/accounts/:account_id/captain_documents/:id
|
|
func (h *CaptainDocumentHandler) Delete(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
if err := h.svc.Delete(c.Request.Context(), uint(id)); err != nil {
|
|
applogger.L().Errorf("Delete captain document: %v", err)
|
|
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to delete document")
|
|
return
|
|
}
|
|
|
|
response.NoContent(c)
|
|
}
|
|
|
|
// List retrieves documents for an assistant.
|
|
// GET /api/v1/accounts/:account_id/captain_assistants/:assistant_id/documents
|
|
func (h *CaptainDocumentHandler) List(c *gin.Context) {
|
|
assistantID, err := strconv.ParseUint(c.Param("assistant_id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid assistant_id")
|
|
return
|
|
}
|
|
|
|
p := pagination.Parse(c)
|
|
docs, count, err := h.svc.List(c.Request.Context(), uint(assistantID), p.Offset, p.PerPage)
|
|
if err != nil {
|
|
applogger.L().Errorf("List captain documents: %v", err)
|
|
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to list documents")
|
|
return
|
|
}
|
|
|
|
response.OKWithMeta(c, docs, p.Page, p.PerPage, count)
|
|
}
|
|
|
|
// ProcessDocument triggers document content extraction and embedding generation.
|
|
// POST /api/v1/accounts/:account_id/captain_documents/:id/process
|
|
func (h *CaptainDocumentHandler) ProcessDocument(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
if err := h.svc.ProcessDocument(c.Request.Context(), uint(id)); err != nil {
|
|
applogger.L().Errorf("ProcessDocument: %v", err)
|
|
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to process document")
|
|
return
|
|
}
|
|
|
|
response.OK(c, gin.H{"processed": true})
|
|
}
|
|
|
|
// SyncDocument triggers re-fetching content from the external URL.
|
|
// POST /api/v1/accounts/:account_id/captain_documents/:id/sync
|
|
func (h *CaptainDocumentHandler) SyncDocument(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
if err := h.svc.SyncDocument(c.Request.Context(), uint(id)); err != nil {
|
|
applogger.L().Errorf("SyncDocument: %v", err)
|
|
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to sync document")
|
|
return
|
|
}
|
|
|
|
response.OK(c, gin.H{"synced": true})
|
|
} |