feat(conversations): align chatwoot message serializers
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
"github.com/gochat/gochat/pkg/pagination"
|
||||
"github.com/gochat/gochat/pkg/response"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// MessageHandler handles message-related API endpoints.
|
||||
@@ -43,21 +45,31 @@ func NewMessageHandler(svc *service.MessageService) *MessageHandler {
|
||||
// GET /api/v1/accounts/:account_id/conversations/:conversation_id/messages
|
||||
// Reference: Chatwoot conversations#messages (index)
|
||||
func (h *MessageHandler) List(c *gin.Context) {
|
||||
accountID, err := parseUintParam(c, "account_id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id")
|
||||
return
|
||||
}
|
||||
conversationID, err := parseUintParam(c, "conversation_id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid conversation_id")
|
||||
return
|
||||
}
|
||||
|
||||
p := pagination.Parse(c)
|
||||
|
||||
messages, total, svcErr := h.svc.ListByConversation(c.Request.Context(), conversationID, p.Offset, p.PerPage)
|
||||
conversation, svcErr := h.svc.ResolveConversationForRoute(c.Request.Context(), accountID, conversationID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
|
||||
response.OKWithMeta(c, toInterfaceSlice(messages), p.Page, p.PerPage, total)
|
||||
p := pagination.Parse(c)
|
||||
|
||||
messages, _, svcErr := h.svc.ListByConversation(c.Request.Context(), conversation.ID, p.Offset, p.PerPage)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, serializeMessageIndex(c.Request.Context(), h.svc.DB(), conversation, messages))
|
||||
}
|
||||
|
||||
// @Summary Create a message in a conversation
|
||||
@@ -92,7 +104,7 @@ func (h *MessageHandler) Create(c *gin.Context) {
|
||||
}
|
||||
|
||||
var req service.CreateMessageRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
if err := bindCreateMessageRequest(c, &req); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
|
||||
return
|
||||
}
|
||||
@@ -104,7 +116,12 @@ func (h *MessageHandler) Create(c *gin.Context) {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "conversation_id is required")
|
||||
return
|
||||
}
|
||||
req.ConversationID = conversationID
|
||||
conversation, resolveErr := h.svc.ResolveConversationForRoute(c.Request.Context(), accountID, conversationID)
|
||||
if resolveErr != nil {
|
||||
handleServiceError(c, resolveErr)
|
||||
return
|
||||
}
|
||||
req.ConversationID = conversation.ID
|
||||
}
|
||||
|
||||
message, svcErr := h.svc.Create(c.Request.Context(), accountID, userID, req)
|
||||
@@ -112,7 +129,8 @@ func (h *MessageHandler) Create(c *gin.Context) {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
response.Created(c, message)
|
||||
conversation, _ := h.svc.ResolveConversationForRoute(c.Request.Context(), accountID, req.ConversationID)
|
||||
c.JSON(http.StatusOK, serializeMessage(c.Request.Context(), h.svc.DB(), message, conversation))
|
||||
}
|
||||
|
||||
// @Summary Get a single message
|
||||
@@ -178,7 +196,8 @@ func (h *MessageHandler) Update(c *gin.Context) {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
response.OK(c, message)
|
||||
conversation, _ := h.svc.ResolveConversationForRoute(c.Request.Context(), accountID, message.ConversationID)
|
||||
c.JSON(http.StatusOK, serializeMessage(c.Request.Context(), h.svc.DB(), message, conversation))
|
||||
}
|
||||
|
||||
// @Summary Delete a message
|
||||
@@ -264,7 +283,8 @@ func (h *MessageHandler) Retry(c *gin.Context) {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
response.OK(c, message)
|
||||
conversation, _ := h.svc.ResolveConversationForRoute(c.Request.Context(), accountID, message.ConversationID)
|
||||
c.JSON(http.StatusOK, serializeMessage(c.Request.Context(), h.svc.DB(), message, conversation))
|
||||
}
|
||||
|
||||
// Translate translates a message's content to a target language using LLM.
|
||||
@@ -304,3 +324,34 @@ func (h *MessageHandler) Translate(c *gin.Context) {
|
||||
}
|
||||
response.OK(c, result)
|
||||
}
|
||||
|
||||
func bindCreateMessageRequest(c *gin.Context, req *service.CreateMessageRequest) error {
|
||||
if strings.HasPrefix(c.ContentType(), "multipart/form-data") {
|
||||
if err := c.Request.ParseMultipartForm(32 << 20); err != nil {
|
||||
return err
|
||||
}
|
||||
req.Content = c.PostForm("content")
|
||||
req.MessageType = c.PostForm("message_type")
|
||||
req.ContentType = c.PostForm("content_type")
|
||||
req.SourceID = c.PostForm("source_id")
|
||||
req.EchoID = c.PostForm("echo_id")
|
||||
req.Private = strings.EqualFold(c.PostForm("private"), "true") || c.PostForm("private") == "1"
|
||||
if raw := c.PostForm("content_attributes"); raw != "" {
|
||||
req.ContentAttributes = []byte(raw)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var raw map[string]json.RawMessage
|
||||
if err := c.ShouldBindJSON(&raw); err != nil {
|
||||
return err
|
||||
}
|
||||
bytes, _ := json.Marshal(raw)
|
||||
if err := json.Unmarshal(bytes, req); err != nil {
|
||||
return err
|
||||
}
|
||||
if value, ok := raw["content_attributes"]; ok && string(value) != "null" {
|
||||
req.ContentAttributes = datatypes.JSON(value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user