Telnyx activities improvements including Queue Wait Time
This commit is contained in:
parent
844589f966
commit
ab151690b1
|
|
@ -120,7 +120,7 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
|
||||
if (CallBridgedPayloadA != null && CallBridgedPayloadB != null)
|
||||
{
|
||||
results.Add(Outcome(TelnyxOutcomeNames.Bridged));
|
||||
results.Add(Outcome(TelnyxOutcomeNames.Bridged, new BridgedCallsOutput(CallBridgedPayloadA, CallBridgedPayloadB)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -146,6 +146,8 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
}
|
||||
}
|
||||
|
||||
public record BridgedCallsOutput(CallBridgedPayload PayloadA, CallBridgedPayload PayloadB);
|
||||
|
||||
public static class BridgeCallsExtensions
|
||||
{
|
||||
public static ISetupActivity<BridgeCalls> WithCallControlIdA(this ISetupActivity<BridgeCalls> setup, Func<ActivityExecutionContext, ValueTask<string?>> value) => setup.Set(x => x.CallControlIdA, value);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,17 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
get => GetState(() => Duration.FromSeconds(20));
|
||||
set => SetState(value);
|
||||
}
|
||||
|
||||
|
||||
[ActivityInput(
|
||||
Hint = "The maximum time to wait for anyone to pickup before giving up.",
|
||||
SupportedSyntaxes = new[] {SyntaxNames.JavaScript, SyntaxNames.Liquid}
|
||||
)]
|
||||
public Duration? MaxQueueWaitTime
|
||||
{
|
||||
get => GetState<Duration>();
|
||||
set => SetState(value);
|
||||
}
|
||||
|
||||
[ActivityInput(
|
||||
Hint = "Enables Answering Machine Detection.",
|
||||
UIHint = ActivityInputUIHints.Dropdown,
|
||||
|
|
@ -121,11 +131,25 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
}
|
||||
|
||||
public override void Build(ICompositeActivityBuilder builder) =>
|
||||
builder.Switch(cases =>
|
||||
{
|
||||
cases.Add(RingGroupStrategy.PrioritizedHunt.ToString(), () => Strategy == RingGroupStrategy.PrioritizedHunt, BuildPrioritizedHuntFlow);
|
||||
cases.Add(RingGroupStrategy.RingAll.ToString(), () => Strategy == RingGroupStrategy.RingAll, BuildRingAllFlow);
|
||||
});
|
||||
builder
|
||||
.StartWith<Fork>(fork => fork.WithBranches("Ring", "Queue Timeout"), fork =>
|
||||
{
|
||||
fork.When("Ring")
|
||||
.While(true, iterate => iterate
|
||||
.Switch(cases =>
|
||||
{
|
||||
cases.Add(RingGroupStrategy.PrioritizedHunt.ToString(), () => Strategy == RingGroupStrategy.PrioritizedHunt, BuildPrioritizedHuntFlow);
|
||||
cases.Add(RingGroupStrategy.RingAll.ToString(), () => Strategy == RingGroupStrategy.RingAll, BuildRingAllFlow);
|
||||
}));
|
||||
|
||||
fork.When("Queue Timeout")
|
||||
.IfFalse(() => IsNullOrZero(MaxQueueWaitTime), whenTrue =>
|
||||
{
|
||||
whenTrue
|
||||
.Timer(() => MaxQueueWaitTime!.Value)
|
||||
.Finish(TelnyxOutcomeNames.NoResponse);
|
||||
});
|
||||
});
|
||||
|
||||
protected override async ValueTask OnExitAsync(ActivityExecutionContext context, object? output)
|
||||
{
|
||||
|
|
@ -163,11 +187,11 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
.When(TelnyxOutcomeNames.Answered)
|
||||
.Then<BridgeCalls>(bridgeCalls =>
|
||||
bridgeCalls.When(TelnyxOutcomeNames.Bridged)
|
||||
.Finish(TelnyxOutcomeNames.Connected));
|
||||
.Finish(activity => activity.WithOutcome(TelnyxOutcomeNames.Connected).WithOutput(context => context.GetInput<BridgedCallsOutput>())));
|
||||
}
|
||||
)
|
||||
)
|
||||
.Finish(TelnyxOutcomeNames.NoResponse);
|
||||
.IfTrue(() => IsNullOrZero(MaxQueueWaitTime), whenTrue => whenTrue.Finish(TelnyxOutcomeNames.NoResponse));
|
||||
|
||||
private void BuildRingAllFlow(IOutcomeBuilder builder) =>
|
||||
builder
|
||||
|
|
@ -181,12 +205,12 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
.WithCallControlIdA(() => CallControlId)
|
||||
.WithCallControlIdB(() => CallAnsweredPayload!.CallControlId), bridge => bridge
|
||||
.When(TelnyxOutcomeNames.Bridged)
|
||||
.Finish(TelnyxOutcomeNames.Connected));
|
||||
.Finish(activity => activity.WithOutcome(TelnyxOutcomeNames.Connected).WithOutput(context => context.GetInput<BridgedCallsOutput>())));
|
||||
|
||||
fork
|
||||
.When("Timeout")
|
||||
.StartIn(() => RingTime)
|
||||
.Finish(TelnyxOutcomeNames.NoResponse);
|
||||
.IfTrue(() => IsNullOrZero(MaxQueueWaitTime), whenTrue => whenTrue.Finish(TelnyxOutcomeNames.NoResponse));
|
||||
|
||||
fork
|
||||
.When("Dial Everyone")
|
||||
|
|
@ -221,6 +245,8 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
return resolvedExtension?.Number ?? extension;
|
||||
}
|
||||
|
||||
private static bool IsNullOrZero(Duration? duration) => duration == null || duration.Value == Duration.Zero;
|
||||
|
||||
object IActivityPropertyDefaultValueProvider.GetDefaultValue(PropertyInfo property) => Duration.FromSeconds(20);
|
||||
}
|
||||
}
|
||||
|
|
@ -122,6 +122,9 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
|
||||
[ActivityOutput] public DialResponse? DialResponse { get; set; }
|
||||
[ActivityOutput] public CallPayload? Output { get; set; }
|
||||
[ActivityOutput] public CallAnsweredPayload? AnsweredOutput { get; set; }
|
||||
[ActivityOutput] public CallHangupPayload? HangupOutput { get; set; }
|
||||
[ActivityOutput] public CallInitiatedPayload? InitiatedOutput { get; set; }
|
||||
|
||||
protected override async ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
|
|
@ -140,13 +143,31 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
|
||||
return payload switch
|
||||
{
|
||||
CallAnsweredPayload => Outcome(TelnyxOutcomeNames.Answered),
|
||||
CallHangupPayload => Outcome(TelnyxOutcomeNames.Hangup),
|
||||
CallInitiatedPayload => Combine(Outcome(TelnyxOutcomeNames.CallInitiated), Suspend()),
|
||||
CallAnsweredPayload answeredPayload => AnsweredOutcome(answeredPayload),
|
||||
CallHangupPayload hangupPayload => HangupOutcome(hangupPayload),
|
||||
CallInitiatedPayload initiatedPayload => Combine(InitiatedOutcome(initiatedPayload), Suspend()),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(payload))
|
||||
};
|
||||
}
|
||||
|
||||
private IActivityExecutionResult AnsweredOutcome(CallAnsweredPayload payload)
|
||||
{
|
||||
AnsweredOutput = payload;
|
||||
return Outcome(TelnyxOutcomeNames.Answered, payload);
|
||||
}
|
||||
|
||||
private IActivityExecutionResult HangupOutcome(CallHangupPayload payload)
|
||||
{
|
||||
HangupOutput = payload;
|
||||
return Outcome(TelnyxOutcomeNames.Hangup, payload);
|
||||
}
|
||||
|
||||
private IActivityExecutionResult InitiatedOutcome(CallInitiatedPayload payload)
|
||||
{
|
||||
InitiatedOutput = payload;
|
||||
return Outcome(TelnyxOutcomeNames.CallInitiated, payload);
|
||||
}
|
||||
|
||||
private async Task<DialResponse> DialAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var connectionId = string.IsNullOrWhiteSpace(ConnectionId) ? _telnyxOptions.CallControlAppId : ConnectionId;
|
||||
|
|
|
|||
|
|
@ -32,8 +32,12 @@ namespace Elsa.Activities.Telnyx.Activities
|
|||
context.SetCallControlId(callPayload.CallControlId);
|
||||
|
||||
if (callPayload is CallInitiatedPayload callInitiatedPayload)
|
||||
{
|
||||
if (!context.HasFromNumber())
|
||||
context.SetFromNumber(callInitiatedPayload.To);
|
||||
|
||||
context.SetCallerNumber(callInitiatedPayload.From);
|
||||
}
|
||||
}
|
||||
|
||||
Model = webhookModel;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ namespace Elsa.Activities.Telnyx.Extensions
|
|||
{
|
||||
private const string CallControlIdVariableName = "TelnyxCallControlId";
|
||||
private const string FromNumberVariableName = "TelnyxFromNumber";
|
||||
private const string CallerNumberVariableName = "TelnyxCallerNumber";
|
||||
|
||||
/// <summary>
|
||||
/// Returns the control ID of the active call session in the workflow if the specified call control ID is null or empty.
|
||||
|
|
@ -50,7 +51,10 @@ namespace Elsa.Activities.Telnyx.Extensions
|
|||
/// <summary>
|
||||
/// Sets a workflow variable with the specified call control ID value.
|
||||
/// </summary>
|
||||
public static void SetFromNumber(this ActivityExecutionContext context, string fromNumber) => context.SetVariable(FromNumberVariableName, fromNumber);
|
||||
public static void SetFromNumber(this ActivityExecutionContext context, string number) => context.SetVariable(FromNumberVariableName, number);
|
||||
|
||||
public static void SetCallerNumber(this ActivityExecutionContext context, string number) => context.SetVariable(CallerNumberVariableName, number);
|
||||
public static string? GetCallerNumber(this ActivityExecutionContext context) => context.GetVariable<string>(CallerNumberVariableName);
|
||||
|
||||
public static bool HasFromNumber(this ActivityExecutionContext context) => context.HasVariable(FromNumberVariableName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,5 +18,6 @@ namespace Elsa.Activities.Telnyx.Models
|
|||
|
||||
public string? FirstName { get; init; }
|
||||
public string? LastName { get; init; }
|
||||
public string? Email { get; init; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Elsa.Activities.Telnyx.Models;
|
||||
using Elsa.Activities.Telnyx.Webhooks.Models;
|
||||
using Elsa.Activities.Telnyx.Webhooks.Payloads.Call;
|
||||
using Elsa.Scripting.JavaScript.Services;
|
||||
|
|
@ -13,6 +14,7 @@ namespace Elsa.Activities.Telnyx.Scripting.JavaScript
|
|||
return new[]
|
||||
{
|
||||
typeof(TelnyxWebhook),
|
||||
typeof(Extension),
|
||||
|
||||
typeof(CallAnsweredPayload),
|
||||
typeof(CallBridgedPayload),
|
||||
|
|
|
|||
|
|
@ -13,5 +13,7 @@ namespace Elsa.Activities.Telnyx.Webhooks.Payloads.Call
|
|||
public string SipHangupCause { get; init; } = default!;
|
||||
public string HangupSource { get; init; } = default!;
|
||||
public string HangupCause { get; init; } = default!;
|
||||
public string From { get; set; } = default!;
|
||||
public string To { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,5 +10,6 @@ namespace Elsa.Activities.Telnyx.Webhooks.Payloads.Call
|
|||
public string Direction { get; init; } = default!;
|
||||
public string State { get; init; } = default!;
|
||||
public string To { get; init; } = default!;
|
||||
public string From { get; init; } = default!;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,5 +13,6 @@ namespace Elsa.Activities.Telnyx.Webhooks.Payloads.Call
|
|||
public CallRecordingUrls RecordingUrls { get; set; } = default!;
|
||||
public Instant RecordingEndedAt { get; set; }
|
||||
public Instant RecordingStartedAt { get; set; }
|
||||
public Duration Duration => RecordingEndedAt - RecordingStartedAt;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue