package automation import ( "context" "encoding/json" "fmt" "sync" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/worker" ) type automationWebhookDeliveryJob struct { AccountID uint `json:"account_id"` ConversationID uint `json:"conversation_id"` EventName string `json:"event_name"` URL string `json:"url"` Payload map[string]interface{} `json:"payload"` } type automationTranscriptDeliveryJob struct { AccountID uint `json:"account_id"` ConversationID uint `json:"conversation_id"` Recipient string `json:"recipient"` } type automationTeamEmailDeliveryJob struct { AccountID uint `json:"account_id"` ConversationID uint `json:"conversation_id"` TeamID uint `json:"team_id"` Message string `json:"message"` } var actionDeliveryRegistrations sync.Map // RegisterActionDeliveryJobs wires Chatwoot-style automation external side // effects into the durable worker. Callers may invoke this repeatedly; worker // handlers are idempotently registered per WorkerPool instance. func RegisterActionDeliveryJobs(wp *worker.WorkerPool, db DBProvider) { if wp == nil || db == nil { return } if _, loaded := actionDeliveryRegistrations.LoadOrStore(wp, struct{}{}); loaded { return } runner := &actionDeliveryJobRunner{ db: db, webhookDeliverer: defaultWebhookDelivererFactory(), transcriptDeliverer: defaultTranscriptDelivererFactory(), } wp.Register(TaskTypeAutomationWebhookDelivery, runner.performWebhookDelivery) wp.Register(TaskTypeAutomationTranscriptDelivery, runner.performTranscriptDelivery) wp.Register(TaskTypeAutomationTeamEmailDelivery, runner.performTeamEmailDelivery) } type actionDeliveryJobRunner struct { db DBProvider webhookDeliverer AutomationWebhookDeliverer transcriptDeliverer AutomationTranscriptDeliverer } func (r *actionDeliveryJobRunner) performWebhookDelivery(ctx context.Context, job *model.BackgroundJob) error { var payload automationWebhookDeliveryJob if err := json.Unmarshal(job.Payload, &payload); err != nil { return fmt.Errorf("unmarshal automation webhook job: %w", err) } _, err := r.webhookDeliverer.DeliverWebhook(ctx, AutomationWebhookRequest{ AccountID: payload.AccountID, ConversationID: payload.ConversationID, EventName: payload.EventName, URL: payload.URL, Payload: payload.Payload, }) return err } func (r *actionDeliveryJobRunner) performTranscriptDelivery(ctx context.Context, job *model.BackgroundJob) error { var payload automationTranscriptDeliveryJob if err := json.Unmarshal(job.Payload, &payload); err != nil { return fmt.Errorf("unmarshal automation transcript job: %w", err) } subject, body, err := NewActionService(r.db).buildTranscriptEmail(ctx, payload.AccountID, payload.ConversationID) if err != nil { return err } _, err = r.transcriptDeliverer.DeliverTranscript(ctx, AutomationTranscriptRequest{ AccountID: payload.AccountID, ConversationID: payload.ConversationID, Recipient: payload.Recipient, Subject: subject, Body: body, }) return err } func (r *actionDeliveryJobRunner) performTeamEmailDelivery(ctx context.Context, job *model.BackgroundJob) error { var payload automationTeamEmailDeliveryJob if err := json.Unmarshal(job.Payload, &payload); err != nil { return fmt.Errorf("unmarshal automation team email job: %w", err) } requests, err := NewActionService(r.db).buildTeamEmailRequests(ctx, payload.AccountID, payload.ConversationID, []uint{payload.TeamID}, payload.Message) if err != nil { return err } for _, req := range requests { if _, err := r.transcriptDeliverer.DeliverTranscript(ctx, req); err != nil { return err } } return nil }