Add PlayAudio Telnyx activity

This commit is contained in:
Sipke Schoorstra 2021-03-26 17:27:35 +01:00
parent c4f8eafba7
commit 80b4b9dc6a
4 changed files with 123 additions and 11 deletions

View file

@ -0,0 +1,104 @@
using System;
using System.Threading.Tasks;
using Elsa.Activities.Telnyx.Client.Models;
using Elsa.Activities.Telnyx.Client.Services;
using Elsa.Activities.Telnyx.Extensions;
using Elsa.ActivityResults;
using Elsa.Attributes;
using Elsa.Design;
using Elsa.Exceptions;
using Elsa.Services;
using Elsa.Services.Models;
using Refit;
namespace Elsa.Activities.Telnyx.Activities
{
[Action(
Category = Constants.Category,
Description = "Play an audio file on the call.",
Outcomes = new[] { OutcomeNames.Done, TelnyxOutcomeNames.CallIsNoLongerActive },
DisplayName = "Play Audio"
)]
public class PlayAudio : Activity
{
private readonly ITelnyxClient _telnyxClient;
public PlayAudio(ITelnyxClient telnyxClient) => _telnyxClient = telnyxClient;
[ActivityProperty(
Label = "Call Control ID",
Hint = "Unique identifier and token for controlling the call",
Category = PropertyCategories.Advanced
)]
public string CallControlId { get; set; } = default!;
[ActivityProperty(
Label = "Audio URL",
Hint = "The URL of a file to be played back at the beginning of each prompt. The URL can point to either a WAV or MP3 file."
)]
public Uri AudioUrl { get; set; } = default!;
[ActivityProperty(
Hint = "Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string.",
Category = PropertyCategories.Advanced
)]
public string? ClientState { get; set; }
[ActivityProperty(
Label = "Command ID",
Hint = "Use this field to avoid duplicate commands. Telnyx will ignore commands with the same Command ID.",
Category = PropertyCategories.Advanced
)]
public string? CommandId { get; set; }
[ActivityProperty(
Hint = "The number of times the audio file should be played. If supplied, the value must be an integer between 1 and 100, or the special string 'infinity' for an endless loop.",
DefaultValue = "1",
Category = PropertyCategories.Advanced
)]
public string? Loop { get; set; } = "1";
[ActivityProperty(
Hint = "When enabled, audio will be mixed on top of any other audio that is actively being played back. Note that `overlay: true` will only work if there is another audio file already being played on the call.",
DefaultValue = false,
Category = PropertyCategories.Advanced
)]
public bool Overlay { get; set; }
[ActivityProperty(
Hint = "Specifies the leg or legs on which audio will be played. If supplied, the value must be either 'self', 'opposite' or 'both'.",
UIHint = ActivityPropertyUIHints.Dropdown,
Options = new[]{ "", "self", "opposite", "both" },
Category = PropertyCategories.Advanced
)]
public string? TargetLegs { get; set; }
protected override async ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context)
{
var request = new PlayAudioRequest(
AudioUrl,
EmptyToNull(ClientState),
EmptyToNull(CommandId),
string.IsNullOrWhiteSpace(Loop) ? null : Loop == "infinity" ? Loop : int.Parse(Loop),
Overlay,
EmptyToNull(TargetLegs)
);
var callControlId = context.GetCallControlAppId(CallControlId);
try
{
await _telnyxClient.Calls.PlayAudioAsync(callControlId, request, context.CancellationToken);
return Done();
}
catch (ApiException e)
{
if (await e.CallIsNoLongerActiveAsync())
return Outcome(TelnyxOutcomeNames.CallIsNoLongerActive);
throw new WorkflowException(e.Content ?? e.Message, e);
}
}
private static string? EmptyToNull(string? value) => value is "" ? null : value;
}
}

View file

@ -4,8 +4,9 @@ using System.Collections.Generic;
namespace Elsa.Activities.Telnyx.Client.Models
{
public record AnswerCallRequest(string? BillingGroupId, string? ClientState, string? CommandId, string? WebhookUrl, string? WebhookUrlMethod);
public record HangupCallRequest(string? ClientState, string? CommandId);
public record GatherUsingAudioRequest(
Uri AudioUrl,
string? ClientState,
@ -17,8 +18,9 @@ namespace Elsa.Activities.Telnyx.Client.Models
int? MinimumDigits,
string? TerminatingDigit,
int? TimeoutMillis,
string? ValidDigits);
string? ValidDigits
);
public record TransferCallRequest(
string To,
string? From,
@ -37,7 +39,7 @@ namespace Elsa.Activities.Telnyx.Client.Models
string? WebhookUrl,
string? WebhookUrlMethod
);
public record DialRequest(
string ConnectionId,
string To,
@ -55,11 +57,19 @@ namespace Elsa.Activities.Telnyx.Client.Models
string? WebhookUrl,
string? WebhookUrlMethod
);
public record BridgeCallsRequest(
string CallControlId,
string? ClientState,
string? CommandId,
string? ParkAfterUnbridge
);
public record PlayAudioRequest(
Uri AudioUrl,
string? ClientState,
string? CommandId,
object? Loop,
bool Overlay,
string? TargetLegs);
}

View file

@ -24,5 +24,8 @@ namespace Elsa.Activities.Telnyx.Client.Services
[Post("/v2/calls/{callControlId}/actions/bridge")]
Task BridgeCallsAsync(string callControlId, [Body]BridgeCallsRequest request, CancellationToken cancellationToken = default);
[Post("/v2/calls/{callControlId}/actions/playback_start")]
Task PlayAudioAsync(string callControlId, [Body]PlayAudioRequest request, CancellationToken cancellationToken = default);
}
}

View file

@ -9,16 +9,11 @@ namespace Elsa.Activities.Telnyx.Extensions
/// <summary>
/// Returns the default call control app ID if the specified value is null or empty.
/// </summary>
public static string GetCallControlId(this ActivityExecutionContext context, string? callControlId)
public static string GetCallControlAppId(this ActivityExecutionContext context, string? callControlId)
{
if (!string.IsNullOrWhiteSpace(callControlId))
return callControlId;
// callControlId = context.GetVariable<string>("CallControlId");
//
// if (!string.IsNullOrWhiteSpace(callControlId))
// return callControlId;
var options = context.GetService<TelnyxOptions>();
callControlId = options.CallControlAppId;