package handoff import ( "context" "fmt" ) type ARIClient interface { RedirectChannel(ctx context.Context, channelID string, endpoint string) error ContinueInDialplan(ctx context.Context, channelID, dialplanContext, extension string, priority int) error } type Executor interface { Execute(ctx context.Context, req HandoffRequest) (HandoffResult, error) } type SafeExecutor struct { ARI ARIClient } func (e SafeExecutor) Execute(ctx context.Context, req HandoffRequest) (HandoffResult, error) { result := HandoffResult{RequestID: req.ID, Mode: req.Mode} switch req.Mode { case HandoffModeDisabledStub: result.Status = HandoffStatusStubbed result.MessageKey = "handoff.stub" result.Message = Message(result.MessageKey, req.Language) return result, nil case HandoffModeHangupAfterMessage: result.Status = HandoffStatusCompleted result.MessageKey = "handoff.stub" result.Message = Message(result.MessageKey, req.Language) return result, nil case HandoffModeARIRedirect: result.TransferAttempted = true if e.ARI == nil { return transferFailed(req, "ari client not configured") } if err := e.ARI.RedirectChannel(ctx, req.AsteriskChannelID, req.TargetEndpoint); err != nil { return transferFailed(req, err.Error()) } result.Status = HandoffStatusCompleted result.TransferSucceeded = true result.MessageKey = "handoff.transfer_started" result.Message = Message(result.MessageKey, req.Language) return result, nil case HandoffModeDialplanContinue: result.TransferAttempted = true if e.ARI == nil { return transferFailed(req, "ari client not configured") } if err := e.ARI.ContinueInDialplan(ctx, req.AsteriskChannelID, req.DialplanContext, req.DialplanExtension, req.DialplanPriority); err != nil { return transferFailed(req, err.Error()) } result.Status = HandoffStatusCompleted result.TransferSucceeded = true result.MessageKey = "handoff.transfer_started" result.Message = Message(result.MessageKey, req.Language) return result, nil default: return HandoffResult{RequestID: req.ID, Mode: req.Mode, Status: HandoffStatusFailed, MessageKey: "handoff.denied", Message: Message("handoff.denied", req.Language), Error: "unknown handoff mode"}, fmt.Errorf("unknown handoff mode") } } func transferFailed(req HandoffRequest, msg string) (HandoffResult, error) { result := HandoffResult{RequestID: req.ID, Mode: req.Mode, Status: HandoffStatusFailed, TransferAttempted: true, MessageKey: "handoff.transfer_failed", Message: Message("handoff.transfer_failed", req.Language), Error: SanitizeText(msg, 200)} return result, fmt.Errorf("handoff transfer failed") }