Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions packages/Telephony/Actions/CallTransfer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
using System.Threading;
using System.Threading.Tasks;
using AdaptiveExpressions.Properties;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Adaptive.Actions;
using Microsoft.Bot.Connector;
using Newtonsoft.Json;

namespace Microsoft.Bot.Components.Telephony.Actions
Expand Down Expand Up @@ -55,12 +55,17 @@ public CallTransfer([CallerFilePath] string sourceFilePath = "", [CallerLineNumb
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async override Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{
var phoneNumber = this.PhoneNumber?.GetValue(dc.State);
if (dc.Context.Activity.ChannelId == Channels.Telephony)
{
var phoneNumber = this.PhoneNumber?.GetValue(dc.State);

// Create handoff event, passing the phone number to transfer to as context.
HandoffContext = new { TargetPhoneNumber = phoneNumber };

return await base.BeginDialogAsync(dc, options, cancellationToken).ConfigureAwait(false);
// Create handoff event, passing the phone number to transfer to as context.
HandoffContext = new { TargetPhoneNumber = phoneNumber };

return await base.BeginDialogAsync(dc, options, cancellationToken).ConfigureAwait(false);
}

return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
}
}
}
13 changes: 6 additions & 7 deletions packages/Telephony/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,18 @@ Like any other channel, Telephony channel allows you to transfer call to an agen
* PhoneNumber

#### Usage
* Phone Number is not empty and in the E.164 format.
* Phone Number should not be empty and should be in the E.164 format.
* The call transfer action is only valid when called in a conversation on the Telephony channel. The action can be considered a No-op for all other channels.

#### Dialog Flow
* Once the call transfer is completed, the bot is removed from the current conversation and control is transferred to the extenal phone nunber.
* [Open] Do we get back a handoff status on success? Should we wait for the status in our package?
* Once the call transfer is completed, the bot is removed from the current conversation and control is transferred to the external phone number.
* The bot will not get any handoff status on success.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current behavior is

  1. Handoff Success : gets End of Conversation and the call ends
  2. Handoff failure: gets a handoff status with a failed message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes added in failure flow

* Any actions specified after call transfer will not be executed. Treat it like a call end.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the subsequent actions be executed after a failed call transfer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, will will add that in failure flow too.


#### Failures
* [Open] How should the package fail when Phone Number is Empty - should we throw an exception? How can we make sure that the exception message is localize properly?
* [Open] When the phone number is not in a valid E.164 format, how does the call transfer fail?
* [Open] Do we get back a handoff status on failure?

* For all failure cases where the connection is not established, either due to Phone Number being empty, invalid, bogus or just connection failure, an asynchronous "handoff.status" event is sent with value "failed". More details [here](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-design-pattern-handoff-human?view=azure-bot-service-4.0).
* This can be handled either in code as per [this](https://github.com/microsoft/botframework-telephony/blob/main/TransferCallOut.md) or in Composer by adding a trigger -> Activities -> Event Received (Event Activity), with this condition, turn.activity.name == "handoff.status", following which @turn.activity.value can be used for handling the failure case.
* In the failure case, subsequent actions will be executed.

## **Call Recording**
The call recording commands enable bots to request that calls are recorded by the phone provider. The bot can control when to start, stop, pause and resume the recording with these commands. For more information about the call recording capabilities, see [Telephony Advanced Features - Call Recording](https://github.com/microsoft/botframework-telephony/blob/main/CallRecording.md).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://schemas.botframework.com/schemas/ui/v1.0/ui.schema",
"form": {
"label": "Transfer a call",
"subtitle": "Call Transfer",
"label": "Call Transfer",
"subtitle": "Transfers call to the phone number specified (in E.164 format such as +1425123456)",
"order": [
"phoneNumber",
"*"
Expand All @@ -16,7 +16,7 @@
}
},
"menu": {
"label": "Transfer a call",
"label": "Call Transfer",
"submenu": [ "Telephony" ]
},
"flow": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,11 @@ public async Task CallTransfer_HappyPath()
{
await TestUtils.RunTestScript(_resourceExplorerFixture.ResourceExplorer, adapterChannel: Channels.Telephony);
}

[Fact]
public async Task CallTransfer_IgnoredInNonTelephonyChannel()
{
await TestUtils.RunTestScript(_resourceExplorerFixture.ResourceExplorer, adapterChannel: Channels.Msteams);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
{
"$kind": "Microsoft.OnBeginDialog",
"actions": [
{
"$kind": "Microsoft.Telephony.CallTransfer",
"phoneNumber": "+1555443443"
}
]
{
"$kind": "Microsoft.Telephony.CallTransfer",
"phoneNumber": "+15554434432"
},
{
"$kind": "Microsoft.SendActivity",
"activity": "Transfer Initiated!"
}
]
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@
"$schema": "../../../tests.schema",
"$kind": "Microsoft.Test.Script",
"dialog": "CallTransfer_BaseScenario.test",
"script": [
{
"$kind": "Microsoft.Test.UserSays",
"text": "Hello I'm Calculon"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'event'",
"value.TargetPhoneNumber == '+1555443443'"
]
}
]
"script": [
{
"$kind": "Microsoft.Test.UserSays",
"text": "Hello I'm Calculon"
},
{
"$kind": "Microsoft.Test.AssertReplyActivity",
"assertions": [
"type == 'event'",
"value.TargetPhoneNumber == '+15554434432'"
]
},
// Due to this being a mock, after actual call transfer this will not execute
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Transfer Initiated!"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "../../../tests.schema",
"$kind": "Microsoft.Test.Script",
"dialog": "CallTransfer_BaseScenario.test",
"script": [
{
"$kind": "Microsoft.Test.UserSays",
"text": "Hello I'm Calculon"
},
{
"$kind": "Microsoft.Test.AssertReply",
"text": "Transfer Initiated!"
}
]
}