Files
gochat/internal/handler/webhook/webhook_handler.go
T
2026-06-04 15:44:48 +08:00

64 lines
1.7 KiB
Go

package webhook
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/gochat/gochat/internal/channel"
"github.com/gochat/gochat/internal/model"
)
// WebhookHandler processes incoming webhook events from external channels.
type WebhookHandler struct {
registry *channel.ChannelRegistry
}
// NewHandler creates a new WebhookHandler.
func NewHandler(registry *channel.ChannelRegistry) *WebhookHandler {
return &WebhookHandler{registry: registry}
}
// Handle processes an incoming webhook request.
// The URL pattern is /webhooks/:channel_type/:inbox_id
// The handler looks up the ChannelProvider for the given channel_type
// and delegates processing to that provider's ProcessIncoming method.
func (h *WebhookHandler) Handle(c *gin.Context) {
channelType := c.Param("channel_type")
inboxIDStr := c.Param("inbox_id")
provider, err := h.registry.Get(channel.ChannelType(channelType))
if err != nil || provider == nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "unknown channel type: " + channelType,
})
return
}
inboxID, err := strconv.ParseUint(inboxIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid inbox_id"})
return
}
rawPayload, err := c.GetRawData()
if err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to read payload"})
return
}
// Construct an Inbox stub for the provider.
inbox := &model.Inbox{Base: model.Base{ID: uint(inboxID)}}
msg, err := provider.ProcessIncoming(c.Request.Context(), inbox, rawPayload)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"status": "processed",
"conversation_id": msg.ConversationID,
})
}