252 lines
7.3 KiB
Go
252 lines
7.3 KiB
Go
package v1
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/gochat/gochat/internal/automation"
|
|
"github.com/gochat/gochat/pkg/response"
|
|
)
|
|
|
|
// BotRuleHandler handles bot rule API endpoints.
|
|
// Reference: Chatwoot AutomationRulesController pattern adapted for AgentBot rules.
|
|
type BotRuleHandler struct {
|
|
svc *automation.BotRuleService
|
|
}
|
|
|
|
// NewBotRuleHandler creates a new BotRuleHandler.
|
|
func NewBotRuleHandler(svc *automation.BotRuleService) *BotRuleHandler {
|
|
return &BotRuleHandler{svc: svc}
|
|
}
|
|
|
|
// List retrieves all bot rules for an account.
|
|
// GET /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules_configs
|
|
func (h *BotRuleHandler) List(c *gin.Context) {
|
|
accountID, err := parseUintParam(c, "account_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id")
|
|
return
|
|
}
|
|
|
|
rules, svcErr := h.svc.ListByAccount(c.Request.Context(), accountID)
|
|
if svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"bot_rules": rules,
|
|
"meta": gin.H{"count": len(rules)},
|
|
})
|
|
}
|
|
|
|
// ListByBot retrieves all bot rules for a specific AgentBot.
|
|
// GET /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules
|
|
func (h *BotRuleHandler) ListByBot(c *gin.Context) {
|
|
accountID, err := parseUintParam(c, "account_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id")
|
|
return
|
|
}
|
|
agentBotID, err := parseUintParam(c, "agent_bot_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid agent_bot_id")
|
|
return
|
|
}
|
|
|
|
rules, svcErr := h.svc.ListByAgentBot(c.Request.Context(), accountID, agentBotID)
|
|
if svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"bot_rules": rules,
|
|
"meta": gin.H{"count": len(rules)},
|
|
})
|
|
}
|
|
|
|
// Get retrieves a single bot rule by ID.
|
|
// GET /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules/:id
|
|
func (h *BotRuleHandler) Get(c *gin.Context) {
|
|
id, err := parseUintAnyParam(c, "rule_id", "id", "agent_bot_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
rule, svcErr := h.svc.GetByID(c.Request.Context(), id)
|
|
if svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
response.OK(c, rule)
|
|
}
|
|
|
|
// Create creates a new bot rule for an AgentBot.
|
|
// POST /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules
|
|
func (h *BotRuleHandler) Create(c *gin.Context) {
|
|
accountID, err := parseUintParam(c, "account_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id")
|
|
return
|
|
}
|
|
agentBotID, err := parseUintParam(c, "agent_bot_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid agent_bot_id")
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Name string `json:"name" binding:"required"`
|
|
Description string `json:"description"`
|
|
EventName automation.BotRuleEventType `json:"event_name" binding:"required"`
|
|
Conditions automation.Conditions `json:"conditions"`
|
|
Actions automation.Actions `json:"actions"`
|
|
Status automation.BotRuleStatus `json:"status"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
|
|
return
|
|
}
|
|
|
|
rule := &automation.BotRule{
|
|
AccountID: accountID,
|
|
AgentBotID: agentBotID,
|
|
Name: req.Name,
|
|
Description: req.Description,
|
|
EventName: req.EventName,
|
|
Conditions: req.Conditions,
|
|
Actions: req.Actions,
|
|
Status: req.Status,
|
|
}
|
|
// Default to active if not specified
|
|
if rule.Status == "" {
|
|
rule.Status = automation.BotRuleStatusActive
|
|
}
|
|
|
|
if svcErr := h.svc.Create(c.Request.Context(), rule); svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
response.Created(c, rule)
|
|
}
|
|
|
|
// Update updates an existing bot rule.
|
|
// PUT /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules/:id
|
|
func (h *BotRuleHandler) Update(c *gin.Context) {
|
|
id, err := parseUintAnyParam(c, "rule_id", "id", "agent_bot_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
existing, svcErr := h.svc.GetByID(c.Request.Context(), id)
|
|
if svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
EventName automation.BotRuleEventType `json:"event_name"`
|
|
Conditions automation.Conditions `json:"conditions"`
|
|
Actions automation.Actions `json:"actions"`
|
|
Status automation.BotRuleStatus `json:"status"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
|
|
return
|
|
}
|
|
|
|
// Apply updates
|
|
if req.Name != "" {
|
|
existing.Name = req.Name
|
|
}
|
|
if req.Description != "" {
|
|
existing.Description = req.Description
|
|
}
|
|
if req.EventName != "" {
|
|
existing.EventName = req.EventName
|
|
}
|
|
if req.Conditions != nil {
|
|
existing.Conditions = req.Conditions
|
|
}
|
|
if req.Actions != nil {
|
|
existing.Actions = req.Actions
|
|
}
|
|
if req.Status != "" {
|
|
existing.Status = req.Status
|
|
}
|
|
|
|
if svcErr := h.svc.Update(c.Request.Context(), existing); svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
response.OK(c, existing)
|
|
}
|
|
|
|
// Delete soft-deletes a bot rule.
|
|
// DELETE /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules/:id
|
|
func (h *BotRuleHandler) Delete(c *gin.Context) {
|
|
id, err := parseUintAnyParam(c, "rule_id", "id", "agent_bot_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
if svcErr := h.svc.Delete(c.Request.Context(), id); svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
response.NoContent(c)
|
|
}
|
|
|
|
// ToggleStatus toggles the active/inactive status of a bot rule.
|
|
// PATCH /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules/:id/status
|
|
func (h *BotRuleHandler) ToggleStatus(c *gin.Context) {
|
|
id, err := parseUintAnyParam(c, "rule_id", "id", "agent_bot_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Status automation.BotRuleStatus `json:"status" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
|
|
return
|
|
}
|
|
|
|
if svcErr := h.svc.ToggleStatus(c.Request.Context(), id, req.Status); svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
response.OK(c, gin.H{"id": id, "status": req.Status})
|
|
}
|
|
|
|
// Clone duplicates a bot rule.
|
|
// POST /api/v1/accounts/:account_id/agent_bots/:agent_bot_id/bot_rules/:id/clone
|
|
func (h *BotRuleHandler) Clone(c *gin.Context) {
|
|
id, err := parseUintAnyParam(c, "rule_id", "id", "agent_bot_id")
|
|
if err != nil {
|
|
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
|
|
return
|
|
}
|
|
|
|
cloned, svcErr := h.svc.Clone(c.Request.Context(), id)
|
|
if svcErr != nil {
|
|
handleServiceError(c, svcErr)
|
|
return
|
|
}
|
|
|
|
response.Created(c, cloned)
|
|
}
|