How to get Call Status(Connected, Busy, No answered & Ringing) from Amazon Connect Streams API? - amazon-connect

I am using Amazon Connect Streams API [https://github.com/amazon-connect/amazon-connect-streams/blob/master/Documentation.md] and we have different call status in Amazon Connect e.g. call connected, call missed/no answered!
how can i get call status of the following call dispositions (busy, connected, in progress, ringing, no answered) from within Streams API?
I am using
function subscribeToContactEvents(contact) {
console.log("Subscribing to events for contact");
contact.onMissed(handleOnMissed);
contact.onConnected(handleOnConnected);
contact.onEnded(handleOnEnded);
}
function handleOnMissed(contact){
console.log("[contact.onMissed] Call is Missed. Contact status is " + contact.getStatus().type);
}
function handleOnConnected(contact) {
console.log("[contact.onConnected] Call is ACW. Contact status is " + contact.getStatus().type);
}
function handleOnEnded(contact) {
console.log("[contact.onEnded] Call has ended. Contact status is " + contact.getStatus().type);
}

There are two steps to this, first you need to subscribe to agent events then you trigger based on things happening to the agent. So for example...
connect.agent(async function (agent) {
agent.onStateChange(function (agentState){
console.log("Agent State Changed to: " + agentState.newState);
});
});
You can do similar subscribing to contact events.
connect.contact(function (contact) {
activeContact = contact;
contact.onRefresh(function (contact) {/* do stuff */});
contact.onIncoming(function (contact) {/* do stuff */});
contact.onAccepted(function (contact) {/* do stuff */});
contact.onMissed(function (contact) {/* do stuff */});
});
Subscribing to events is covered here... https://github.com/amazon-connect/amazon-connect-streams/blob/master/Documentation.md#event-subscription

Related

Twilio-Client always returns connection status as open on outbound call even if the recipient has not accepted the call yet

I am trying to get the status of outbound call made through Twilio Client(js) v 1.10.1. But the .status() method returns the value as "open" even if the call is in ringing state. I tried adding enableRingingState: true as a parameter while initializing the Twilio.Device and also set the answerOnBridge="true" while creating the TwiMl Dial verb at server side.
As per the official documentation, js sdk should be returning these status "pending", "connecting", "ringing", "open", "closed".
This is required to showing "calling..." until the call is picked and start the timer(mm:ss) in my dialer in browser as soon the call is picked.
Note: Tried the same with Twilio's Quickstart guide code as well.
/**** Pseudo Code is like below ***/
// FRONT END CODE
let device = require('twilio-client').Device;
let outboundCall = '';
const twilioInit = () => {
// axios call to get capability {token} from service
device = device.setup(token,
{
allowIncomingWhileBusy: true,
enableRingingState: true
});
device.ready(function () {
console.log("Twilio ready");
device.identity = "Ratan";
console.log("Twilio Device ", device);
});
device.error(function (error) {
console.log("error in twilio ", error);
if (error.message == "JWT Token Expired") {
alert("token expired");
}
// If token has expired, dispatch an action to get new token.
});
}
// on phone icon click i am calling the below method
const makeOutboundCall = () => {
outboundCall = device.connect({
To: '+911234567890' // This is not the real phone number, I use number from list of Twilio verified numbers
});
outboundCall.on('ringing', function (hasEarlyMedia) {
console.log("ringing");
});
// Then tracking the status of this outboundCall object in setInterval function with a interval of one second by outboundCall.status() and clearing the..
// ..setInterval once the call disconnects
}
// BACK END CODE - SERVER SIDE (WEBHOOK)
#RequestMapping(value="/callCustomers", produces= "text/xml")
public String callByBrowserToMobile(#RequestParam String ApplicationSid, #RequestParam String ApiVersion,
#RequestParam String Called, #RequestParam String Caller,
#RequestParam String CallStatus, #RequestParam String To,
#RequestParam String From, #RequestParam String CallSid,
#RequestParam String Direction, #RequestParam String AccountSid) {
Number number = new Number.Builder(To).build();
Dial dial = new Dial.Builder().answerOnBridge(true).number(number).callerId(myTwilioNumber).build();
VoiceResponse response = new VoiceResponse.Builder().dial(dial).build();
logger.info(response.toXml());
return response.toXml();
}
The call is placed correctly but the issue is only with tracking outbound call status with twilio js library so that i can start call timer in UI once the call is picked by recipient.
Twilio developer evangelist here.
Edit: Found out what the issue was
When using <Dial answerOnBridge="true"> to make the ringing events available, the <Dial> needs to be the first TwiML that Twilio sees when it starts the call. When you are using a free trial account Twilio plays a message at the start of the call which acts as the first TwiML that is seen, so the answerOnBridge attribute doesn't take effect and you don't get the ringing events as you'd expect.
To fix this particular issue you will need to upgrade your account so that Twilio no longer reads out the trial account message at the start of the call.
Original answer:
I wouldn't use setInterval to poll the status of the call. Instead, I would listen to the events on the connection object. So your makeOutboundCall function should look a bit like this:
const makeOutboundCall = () => {
outboundCall = device.connect({
To: TO_NUMBER
});
outboundCall.on("ringing", (hasEarlyMedia) => {
console.log("The call has started and the other phone is ringing.");
});
outboundCall.on("accept", (connection) => {
console.log("The other person answered the phone!");
});
outboundCall.on("disconnect", () => {
console.log("The other person hung up.");
});
}
Let me know if that helps at all.

putting an outgoing call from a twilio client to a phone on hold(Get phone side call Sid)

I am trying to implement 'hold call' functionality into my system. I have looked at this question and some twilio docs, and recommended way to do this is to dequeue the call, which will automatically play the hold music, and then retrieve from queue when hold is complete(un-hold).
This works perfectly fine, when I have an incoming call from a mobile, to my twilio client, and I can dequeue the call, and all works fine.
However when I do it with the outgoing call from the twilio client to the mobile, if I update the call to issue dequeue instruction, I get to hear the hold music on the client side itself, and the phone gets disconnected. I suppose this is because I have set the client leg of the call on hold. So the question is how do I get the call sid for the mobile leg of the call.
I have tried querying CallResource by ParentCallId, but that does not return anything in the case of outgoing calls. Any ideas?
Call is initiated on the client with:
var params = {
To: num
};
console.log('Calling ' + num + '...');
Twilio.Device.connect(params);
The connect API callback uses a simple Dial verb.
Client code for saving callid on connect:
Twilio.Device.connect(function (conn) {
if (conn._direction === 'OUTGOING') {
$scope.outgoing_call_sid = conn.parameters.CallSid;
$scope.number = conn.message.To;
} else {
$scope.incoming_call_sid = conn.parameters.CallSid;
$scope.number = conn.parameters.From;
}
$scope.message = 'In call with ' + $scope.number;
$scope.status = 'InCall';
});
Client code on hold button click:
$scope.hold = function () {
$scope.status = 'Hold';
$scope.message = 'Putting on hold...';
if ($scope.outgoing_call_sid) {
return $http.get(serviceBase + 'api/twilio/hold?callid=' + $scope.outgoing_call_sid);
}
};
Server side Hold API call:
public IHttpActionResult Hold(string callid) { /
//callid = GetLegCallId(callid); //Try to replace with child call
CallResource.Update(new UpdateCallOptions(callid) { Url = ConfigurationManager.AppSettings["ngrokUrl"] + "/api/twilio/enqueue", Method = HttpMethod.Get });
return Ok();
}
Code for getting any child calls:
public string GetLegCallId(string callId)
{
var calls = CallResource.Read(new ReadCallOptions() { ParentCallSid = callId });
if (calls.GetEnumerator().Current != null)
return calls.GetEnumerator().Current.Sid;
}
My bad. Twilio wasnt the issue. Issue was with usage of calls.GetEnumerator().Current != null.
Should do MoveNext on the Enumerator, before Current will have a value. Resolved by doing that. Stupid:(

Unable to join chat channel

When trying to join a channel in the twilio code I've been working with, it comes up with the error saying that it "Cannot read property 'getChannelByUniqueName' of null". The chat works but when I try to open it up on a different browser, like firefox instead of chrome, it says the error "Channel with provided unique name already exist". Can anyone help with this problem?
// Initialize the Chat client
chatClient = new Twilio.Chat.Client(data.token);
joinChannels(chatClient);
});
function joinChannels(chatClient) {
chatClient.getSubscribedChannels();
joinChannel('generalss','Generals Chat Channel');
}
function joinChannel(channelName, channelFriendlyName) {
console.log(channelName);
console.log(chatClient);
print('Attempting to join "' + channelName + '" chat channel...');
var promise = chatClient.getChannelByUniqueName(channelName);
promise.then(function(channel) {
console.log('Found ' + channelName + ' channel:');
channels[channelName] = channel;
console.log(channels);
setupChannel();
}).catch(function() {
// If it doesn't exist, let's create it
chatClient.createChannel({
uniqueName: channelName,
friendlyName: channelFriendlyName
}).then(function(channel) {
channels[channelName] = channel;
setupChannel(channelName);
});
});
}
Twilio developer evangelist here.
It looks to me like you aren't passing the chatClient to your joinChannel method (and secondly that the client might not be fully initialised yet).
I would initialise the client with the following, which uses the create method that returns a promise that resolves when the Client is ready.
// Initialize the Chat client
new Twilio.Chat.Client.create(data.token).then(function(chatClient) {
joinChannels(chatClient);
});
});
Then, make sure you pass the client through to the joinChannel method:
function joinChannels(chatClient) {
chatClient.getSubscribedChannels();
joinChannel(chatClient, 'generalss','Generals Chat Channel');
}
function joinChannel(chatClient, channelName, channelFriendlyName) {
// the rest...
}
Let me know if that helps at all.

How do you create a Twilio Video API Ended Event Hook?

I can't seem to figure out how to add an "ended" event hook after the "disconnected" event.
I wanted to hide the "End Call" button then notify the other participant via sockets so I can also hide their "End Call" button and do other stuff.
Here are my attempts:
My starting code was from https://github.com/TwilioDevEd/video-quickstart-node/blob/master/public/quickstart.js#L27
My attempts are
1. adding a "then" after stopping the conversation and calling a custom function
webRTCActiveConversation.on('disconnected', function (conversation) {
console.log("Connected to Twilio. Listening for incoming Invites as '" + webRTCConversationsClient.identity + "'");
//results to "conversation.localMedia.stop(...).then is not a function"
conversation.localMedia.stop().then(conversationEnded);
webRTCActiveConversation = null;
});
2. adding an "ended" event hook (somehow this was never triggered):
webRTCActiveConversation.on('ended', function (conversation) {
console.log('conversation has ended...');
//should hide end call button then socket emit to hide the end call button on the other connected client
webRTCActiveConversation = null;
});
3. Adding DOM manipulation and socket emit under disconnect event hook (Disconnects call from this client, DOM manipulation and socket event are working, but Twilio connection has not been disconnected on the other connected client)
webRTCActiveConversation.on('disconnected', function (conversation) {
console.log("disconnect call" + webRTCConversationsClient.identity + "'");
conversation.localMedia.stop();
//hide end call button
var el = document.getElementById('button-end-audio-call');
el.className += " hide-state";
//socket emit to hide the end call button on the other connected client
socket.emit('notifyEndCallRequest');
webRTCActiveConversation = null;
});
I did a workaround for the meantime, I modified my attempt no.3 and it worked. I'm sure this is not the best way to do this as there is an "ended" event hook I can't figure out how to trigger, but it solved my issue (both participants got disconnected to the call).
//when the conversation ends, stop capturing local video
webRTCActiveConversation.on('disconnected', function (conversation) {
console.log("disconnect call '" + webRTCConversationsClient.identity + "'");
conversation.localMedia.stop();
webRTCActiveConversation = null;
//delay DOM manipulation and socket emit
setTimeout(function(){
var el = document.getElementById('button-end-audio-call');
el.className += " app-state-hidden";
//socket emit to hide the end call button on the other connected client
socket.emit('notifyEndCallRequest');
}, 3000);
});
Still hopeful for how others handle such case :p

Laravel PubSubHubbub i have subscribed but couldn't receive updates

I am trying to get real time feed updates using the Pubsubhubbup and Laravel, i have created 2 functions one for subscribe and the other one is a callback function.
when the subscribe function called it worked and the callback function receives a confirmation from the hub and respond with the hub_challenge code, all this works OK but the callback function doesn't receive any feed updates after that although it should receive it from the hub when there are updates but this is not happen !!
can you help to find what is the problem ??
thanks for your time.
the functions
public function subscribe(Feed $feed)
{
$hub_url = "http://pubsubhubbub.appspot.com";
$callback_url = url('feed/getFeedUpdates');
$subscriber = new Subscriber($hub_url, $callback_url);
$subscriber->subscribe($feed->feed_url);
Flash::success('Feed has been saved.');
return redirect('feed');
}
public function getFeedUpdates(Request $request)
{
// Subscribe Confirmation
if ($request->has('hub_mode') && $request->hub_mode == 'subscribe') {
$response = new Response($request->hub_challenge, 200);
$response->header('Content-Type', 'text/plain');
return $response;
} else { // Receive Updates
$updates = file_get_contents("php://input");
// put the updates to the database
}
}

Resources