155 lines
5.7 KiB
Go
155 lines
5.7 KiB
Go
package automation
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
applogger "github.com/gochat/gochat/pkg/logger"
|
|
)
|
|
|
|
// BotTriggerConfigService provides CRUD for bot trigger condition configurations.
|
|
// Reference: Chatwoot automation_rule trigger conditions adapted for AgentBot event subscription.
|
|
// TriggerConfigs define when and under what conditions a bot should be triggered on an inbox.
|
|
type BotTriggerConfigService struct {
|
|
db DBProvider
|
|
}
|
|
|
|
// NewBotTriggerConfigService creates a new BotTriggerConfigService.
|
|
func NewBotTriggerConfigService(db DBProvider) *BotTriggerConfigService {
|
|
return &BotTriggerConfigService{db: db}
|
|
}
|
|
|
|
// GetByID retrieves a bot trigger config by ID.
|
|
func (s *BotTriggerConfigService) GetByID(ctx context.Context, id uint) (*BotTriggerConfig, error) {
|
|
var config BotTriggerConfig
|
|
if err := s.db.DB().WithContext(ctx).First(&config, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &config, nil
|
|
}
|
|
|
|
// ListByAccount retrieves all bot trigger configs for an account.
|
|
func (s *BotTriggerConfigService) ListByAccount(ctx context.Context, accountID uint) ([]BotTriggerConfig, error) {
|
|
var configs []BotTriggerConfig
|
|
if err := s.db.DB().WithContext(ctx).
|
|
Where("account_id = ?", accountID).
|
|
Order("id ASC").
|
|
Find(&configs).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return configs, nil
|
|
}
|
|
|
|
// ListByAgentBot retrieves all trigger configs for a specific AgentBot.
|
|
func (s *BotTriggerConfigService) ListByAgentBot(ctx context.Context, accountID uint, agentBotID uint) ([]BotTriggerConfig, error) {
|
|
var configs []BotTriggerConfig
|
|
if err := s.db.DB().WithContext(ctx).
|
|
Where("account_id = ? AND agent_bot_id = ?", accountID, agentBotID).
|
|
Order("id ASC").
|
|
Find(&configs).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return configs, nil
|
|
}
|
|
|
|
// ListActiveByAccountAndEvent retrieves active trigger configs for a given account and event.
|
|
// Used by AgentBotRuleListener to determine which bots should be triggered.
|
|
func (s *BotTriggerConfigService) ListActiveByAccountAndEvent(ctx context.Context, accountID uint, eventName BotRuleEventType) ([]BotTriggerConfig, error) {
|
|
var configs []BotTriggerConfig
|
|
if err := s.db.DB().WithContext(ctx).
|
|
Where("account_id = ? AND event_name = ? AND active = ?", accountID, eventName, true).
|
|
Order("id ASC").
|
|
Find(&configs).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return configs, nil
|
|
}
|
|
|
|
// Create creates a new bot trigger config.
|
|
func (s *BotTriggerConfigService) Create(ctx context.Context, config *BotTriggerConfig) error {
|
|
// Validate conditions before saving (convert TriggerConditions → Conditions for validation)
|
|
conditions := make(Conditions, len(config.Conditions))
|
|
for i, tc := range config.Conditions {
|
|
conditions[i] = Condition(tc)
|
|
}
|
|
if err := ValidateConditions(conditions); err != nil {
|
|
return fmt.Errorf("invalid conditions: %w", err)
|
|
}
|
|
return s.db.DB().WithContext(ctx).Select(
|
|
"AccountID", "AgentBotID", "EventName", "Name", "Description",
|
|
"Conditions", "QueryOperator", "Active",
|
|
).Create(config).Error
|
|
}
|
|
|
|
// Update updates an existing bot trigger config.
|
|
func (s *BotTriggerConfigService) Update(ctx context.Context, config *BotTriggerConfig) error {
|
|
conditions := make(Conditions, len(config.Conditions))
|
|
for i, tc := range config.Conditions {
|
|
conditions[i] = Condition(tc)
|
|
}
|
|
if err := ValidateConditions(conditions); err != nil {
|
|
return fmt.Errorf("invalid conditions: %w", err)
|
|
}
|
|
return s.db.DB().WithContext(ctx).Save(config).Error
|
|
}
|
|
|
|
// Delete soft-deletes a bot trigger config.
|
|
func (s *BotTriggerConfigService) Delete(ctx context.Context, id uint) error {
|
|
return s.db.DB().WithContext(ctx).Delete(&BotTriggerConfig{}, id).Error
|
|
}
|
|
|
|
// ToggleActive toggles the active state of a bot trigger config.
|
|
func (s *BotTriggerConfigService) ToggleActive(ctx context.Context, id uint, active bool) error {
|
|
return s.db.DB().WithContext(ctx).
|
|
Model(&BotTriggerConfig{}).
|
|
Where("id = ?", id).
|
|
Update("active", active).Error
|
|
}
|
|
|
|
// MatchAndTrigger checks all active trigger configs for the given event and account,
|
|
// runs condition filters, and triggers the associated AgentBot for matching configs.
|
|
// Reference: mirrors AutomationRuleService.MatchAndExecute but for trigger config scope.
|
|
// The actual bot action execution is delegated to BotRuleService.MatchAndExecute.
|
|
func (s *BotTriggerConfigService) MatchAndTrigger(ctx context.Context, accountID uint, eventName BotRuleEventType, conversationID uint, eventData map[string]interface{}) ([]uint, error) {
|
|
configs, err := s.ListActiveByAccountAndEvent(ctx, accountID, eventName)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load trigger configs: %w", err)
|
|
}
|
|
|
|
if len(configs) == 0 {
|
|
applogger.L().Debugf("no active trigger configs for account %d event %s", accountID, eventName)
|
|
return nil, nil
|
|
}
|
|
|
|
// Load the conversation for condition matching
|
|
conversation, err := loadConversationForFilter(ctx, s.db.DB(), conversationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load conversation %d: %w", conversationID, err)
|
|
}
|
|
|
|
var matchedBotIDs []uint
|
|
for _, config := range configs {
|
|
// Convert TriggerConditions → Conditions for MatchConditions call
|
|
conditions := make(Conditions, len(config.Conditions))
|
|
for i, tc := range config.Conditions {
|
|
conditions[i] = Condition(tc)
|
|
}
|
|
|
|
matched, err := MatchConditions(ctx, s.db.DB(), conditions, conversation, eventData)
|
|
if err != nil {
|
|
applogger.L().Errorf("condition matching failed for trigger config %d: %v", config.ID, err)
|
|
continue
|
|
}
|
|
if !matched {
|
|
applogger.L().Debugf("trigger config %d did not match conditions for conversation %d", config.ID, conversationID)
|
|
continue
|
|
}
|
|
|
|
applogger.L().Infof("trigger config %d matched for conversation %d, bot %d should be triggered",
|
|
config.ID, conversationID, config.AgentBotID)
|
|
matchedBotIDs = append(matchedBotIDs, config.AgentBotID)
|
|
}
|
|
|
|
return matchedBotIDs, nil
|
|
}
|