How to capture when a caller joins a Twilio conference? - twilio

Our app brings together several participants into a conference. The Host, uses twilio client, while participants use either phone lines or twilio clients.
The host need to know when each participant joins the conference.
is there a way via the RESTful API to get in real-time who joined the conference?

Here's how to get the participants' numbers:
<?php
// Get the PHP helper library from twilio.com/docs/php/install
require_once('/path/to/twilio-php/Services/Twilio.php'); // Loads the library
// Your Account Sid and Auth Token from twilio.com/user/account
$sid = "ACXXXXX";
$token = "YYYYY";
$client = new Services_Twilio($sid, $token);
$response = new Services_Twilio_Twiml();
if( isset($_REQUEST['ConferenceSid']) ){
$participants = $client->account->conferences->get( $_REQUEST['ConferenceSid'] )->participants;
$cnt = count( $participants );
$response->Say( "There are ".$cnt." callers in this conference" );
foreach ($participants as $participant) {
$call = $client->account->calls->get( $participant->callsid );
$response->Say( $call->from );
}
}
$response->Redirect("conferencemod.xml");
print $response;
?>
Taken from: https://www.twilio.com/blog/2014/09/roll-call-roger-stringer-shows-you-how-to-take-a-headcount-during-a-twilio-conference-call.html
You can probably modify it to return $call->StartTime additionally. That would let the moderator know who called and when their call started. I hope that helps.

Related

Twilio Redirecting the wrong call when using CallSid and trying to update live call

So here's the logic of what I am working on:
Someone calls my Twilio Number I use the dial twiml to forward to a cell phone
I use gather and play a whisper to the operator answering the phone (so his cell phone).
The operator has a choice - press 1 to accept, press 2 (transfers to
a different agent).
step 3 is where I am having trouble I am using the code below:
$call = $twilio->calls($CallSid)
->update([
"method" => "POST",
"url" => "http:www.example.com/directcall.php"
]
);
Here's the problem it is modifying the call but it's redirecting the operators phone number instead of the person who is calling in. So the operator is getting redirected to the other operator and the customer is being hung up on. I tried using the parentcallsid too but that doesn't seem to work either.
Any ideas what I am doing wrong?
so just to be clear I want the flow to work like this:
Customer calls phone number -> redirects to designated operator -> if designated operator presses 2 it redirects the customer to operator 2 and disconnects operator 1 from the call. Is this possible?
Thanks for the help, I greatly appreciate it.
UPDATE PLEASE FIND THE CODE SAMPLES BELOW
Index.php
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
$response = new VoiceResponse();
$twilionumber = ltrim($_POST['To'], '+');
$callernumber=ltrim($_POST['From'], '+');
createCall($phonenumbertouse,$response,$twilionumber);
echo $response;
function createCall($phonenumbertouse,$response,$twilionumber) {
$dial = $response->dial('',['timeout' => '30']);
$dial->number($phonenumbertouse, ['action' => "http://example.com/whisper.php",'method' => 'GET']);
}
WHISPER.PHP
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
$response = new VoiceResponse();
$gather = $response->gather(['action' => "http://example.com/route.php",
'method' => 'GET']);
$gather->say($whisper, ['voice' => 'woman', 'language' => 'en-US']);
echo $response;
?>
route.php
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
use Twilio\Rest\Client;
$response = new VoiceResponse();
$keyedInput=$_REQUEST['Digits'];
$mycallsid=$_REQUEST['ParentCallSid'];
if ($keyedInput == 1){
$response->say('connecting the call');
}
elseif ($keyedInput == 2){
$twilio = new Client($sid, $token);
$call = $twilio->calls($mycallsid)
->update([
"method" => "POST",
"url" => "http://example.com/redirect.php"
]
);
}
elseif ($keyedInput == 3){
$response->say('you selected 3');
}
else {
$response->say('Sorry, I don\'t understand that choice.');
}
echo $response;
?>
**Redirect.php **
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
$response = new VoiceResponse();
$dial = $response->dial('+14151234567',['timeout' => '30']);
echo $response;
?>
Twilio developer evangelist here.
Your issue here is that you are using the wrong CallSid to update.
In this case there are two CallSids at play. When your user dials in to your Twilio number, that call between the user and Twilio has one CallSid. Then, when Twilio creates an outbound call to the operator, that call has a different CallSid.
In your application, when you get the <Gather> response from the operator, the CallSid being sent to your endpoint is the CallSid of the operator's call leg. Instead, you need to find the CallSid of the original call.
You should find that the ParentCallSid parameter is sent to the webhook endpoint as well. That ParentCallSid is the original inbound call's Sid and is what you should use to redirect the caller to another operator.
Edit
OK, so I had a go at building this. I don't normally work in PHP, so I wrote this in Node.js (as Twilio Functions). I got it to work and the answer still seems to me to be "use the ParentCallSid, so hopefully it gives you some idea where you might have gone wrong.
The incoming call
This makes an outbound call to my cell phone number, with a url set to make the whisper to me when I answer the call.
exports.handler = function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
const dial = twiml.dial();
dial.number({ url: "/whisper" }, MY_CELL_PHONE_NUMBER);
callback(null, twiml);
};
<Response>
<Dial><Number url="/whisper">MY_CELL_PHONE_NUMBER</Number></Dial>
</Response>
The whisper
This returns a <Gather> spoken to the person answering the cell phone number. It offers a choice, dial "1" to connect or "2" to hang up, triggering the original caller to dial to another number.
exports.handler = function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
const gather = twiml.gather({ digits: 1, action: "/after-whisper" });
gather.say("Dial 1 to connect, dial 2 to hang up.");
callback(null, twiml);
};
<Response>
<Gather action="/after-whisper" digits="1">
<Say>Dial 1 to connect, dial 2 to hang up.</Say>
</Gather>
</Response>
The Gather action "/after-whisper"
This checks the Digits parameter. If it is "1" it immediately calls back with an empty response, signalling the end of the whisper and leading the call to connect with the original caller.
If the Digits parameter is not "1" then we initialise a Twilio client and make a request to the API to update the call with the sid ParentCallSid to a new URL. Once that is complete we return TwiML that says to <Hangup> the whisper call (which wasn't strictly necessary, but I like the intention).
exports.handler = async function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
if (event.Digits === "1") {
callback(null, twiml);
} else {
const client = context.getTwilioClient();
try {
// Update the parent call with a new URL.
await client.calls(event.ParentCallSid).update({
url: URL_TO_NEXT_TWIML,
});
} catch (error) {
console.log(error);
}
twiml.hangup();
callback(null, twiml);
}
};
The next TwiML
This is the endpoint that the url above relates to, when it gets the callback it just returns a <Dial> to another number, though it could include another whisper and go round this loop again if desired.
exports.handler = async function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
twiml.dial(NEXT_NUMBER_TO_DIAL);
callback(null, twiml);
};
<Response>
<Dial>NEXT_NUMBER_TO_DIAL</Dial>
</Response>

Twilio Device Setup - Registers, Connects to TWiML App, but won't accept calls

Am trying to setup a soft phone in browser, via TWiML app.
I created the following:
A page on my own server which serves TWiML to dial a number, say '+11111111111'.
A TWiML app which points to that page
A Twilio number which points to that app.
A page on my server which creates a Twilio Device associated with the app and buttons to run device.connect() or device.register()
The device is setup correctly, as I can register and connect with no errors.
The app works - the phone rings at +111 when I press "Call Using Twilio" button on the TWiML app page, when I call the number pointing to the TWiML app, and when I press the button on my own page. Yay!
What I cannot figure out:
How to answer the phone using the Twilio Device.
The device registers with no issue, so why doesn't it get incoming calls?
How to call other numbers aside from the one in my app.
I did in device.connect({params: {To: '+2222222222'}}), why doesn't it call that number?
Here are all the relevant pages:
calls.pug:
doctype html
html(lang="en")
head
meta(charset="utf-8")
title Browser Calls
body
input#call(type="submit" value="call")
input#register(type="submit" value="register")
pre
script(src="/js/twilio-sdk/twilio.js")
script(type="module" src="/js/calls.js")
[client] calls.js
const $ = css => document.querySelector(css);
const echo = msg => $('pre').innerText += msg + "\n";
var device;
async function setupDevice(){
let data = await fetch('/token/new');
data = await data.json();
device = new Twilio.Device(data.token);
device.on("error",
err => echo("Twilio.Device Error: " + err.message));
echo ('Device setup complete.')
}
$('#register').addEventListener('click', async e => {
if (!device) await setupDevice();
device.on("registered", conn =>
echo('Ready to accept incoming calls.')
);
device.on("incoming", call =>
echo('Incoming call to device')
);
device.register()
});
$('#call').addEventListener('click', async e => {
if (!device) await setupDevice();
let params = { To: '+22222222222' }
device.connect({ params })
});
[node] token.js
const express = require('express');
const router = express.Router();
const AccessToken = require('twilio').jwt.AccessToken;
const VoiceGrant = AccessToken.VoiceGrant;
const config = require('../config');
router.get('/new', function (req, res) {
const accessToken = new AccessToken(
config.accountSid, config.apiKey, config.apiSecret, {identity: 'SG'}
);
const grant = new VoiceGrant({
outgoingApplicationSid: config.appSid,
incomingAllow: true,
});
accessToken.addGrant(grant);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ token: accessToken.toJwt() }));
});
module.exports = router;
Twilio developer evangelist here.
How to answer the phone using the Twilio Device.
The device registers with no issue, so why doesn't it get incoming calls?
To direct a call to the Device, you need to return TwiML that <Dial>s the <Client> with the ID of your access token ("SG" in this case).
So, if you want calls to your Twilio number to be directed to this client you should update the Twilio number's incoming webhook to point to a URL that returns this:
<Response>
<Dial>
<Client>
<Identity>SG</Identity>
</Client>
</Dial>
</Response>
How to call other numbers aside from the one in my app.
I did in device.connect({params: {To: '+2222222222'}}), why doesn't it call that number?
Currently, it sounds like you point the Device to a TwiML app that responds with static TwiML that dials your example number '+11111111111'. To use the parameters, you will need to make that TwiML dynamic, by returning it from your Node server instead. The parameters are sent to the TwiML endpoint, so you can then use them in the response.
Here is an example Express endpoint that would work for you:
const express = require('express');
const router = express.Router();
const { VoiceResponse } = require("twilio").twiml;
const config = require('../config');
router.use(express.urlencoded({ extended: false }));
router.post("/call", function(res, res) {
const To = req.body;
const twiml = new VoiceResponse();
const dial = twiml.dial({ callerId: config.twilioNumber });
dial.number(To);
res.set("Content-Type", "text/xml");
res.send(twiml.toString());
});
module.exports = router;

Twilio Call disconnects after one ring

Twilio calls gets automatically disconnect after one ring. When it's the case for cell phone, everything works just fine but for the landline having ring back-tone the call gets disconnected after one ring. I have checked the call logs; and the status for each call was completed but the duration of each call was 3sec.
This is the code that I have wrote:
$sid = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$twilio = new Client($sid, $token);
$call = $twilio->calls
->create("+1XXXXXXX", // to
"+1XXXXXX", // from
[
"twiml" => "<Response><Say>Hi, A new order has been made by a customer!</Say></Response>"
]
);

How can i see a list of my Twilio account phone numbers by Twilio API?

I have a twilio account for sending SMS. However, i need guidance on how to see a list of my account phone numbers by calling its API. I have tried to navigate through the different menus in API but i dont see any option to get list of my account phone numbers. Thank you in advance for your guidance.
Twilio developer evangelist here.
If you want to list the phone numbers you have in your Twilio account through the API you need the Incoming Phone Numbers list resource.
You can access this easily with the Twilio rubygem like so:
require 'twilio-ruby'
#client = Twilio::REST::Client.new YOUR_ACCOUNT_SID, YOUR_AUTH_TOKEN
numbers = #client.account.incoming_phone_numbers.list
numbers.each do |number|
# do something with the number
puts number.phone_number
end
Here is a PHP version...
<?php
namespace App\Test;
use Twilio\Rest\Client;
use Twilio\Rest\API\V2010\AccountContext;
use Twilio\Rest\Api\V2010\Account\IncomingPhoneNumberList;
use Twilio\Rest\Api\V2010\Account\IncomingPhoneNumberInstance;
class TestClient {
private $client = null;
public function __construct() {
$sid = $_ENV['TWILIO_SID'];
$token = $_ENV['TWILIO_TOKEN'];
$this->client = new Client($sid, $token);
}
public function getActiveNumbers()
{
$context = $this->client->getAccount();
$activeNumbers = $context->incomingPhoneNumbers;
$activeNumberArray = $activeNumbers->read();
$numbers = [];
foreach($activeNumberArray as $activeNumber) {
error_log('active number = '.$activeNumber->phoneNumber);
$numbers[] = (object)[
'number' => $activeNumber->phoneNumber,
'name' => $activeNumber->friendlyName,
'sid' => $activeNumber->sid
];
}
var_dump($numbers);
return $numbers;
}
}

Retweet and destroy tweet using twitter API

I am developing an application which can send tweets to my twitter profile.
Now I need to implement retweet and delete tweet function. I implement those like following but no success. can any one help me!!
/* Delete tweet function */
$twitteroauthPost = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
$token = $twitteroauthPost->getRequestToken();
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET,$token['oauth_token'], $token['oauth_token_secret']);
$result = $connection->post('statuses/destroy', array('id' => $postId));
/* Retweet function */
$twitteroauthPost = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
$token = $twitteroauthPost->getRequestToken();
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET,$token['oauth_token'], $token['oauth_token_secret']);
$result = $connection->post('statuses/retweet', array('id' => $postId));
Then it return this
(
[request] => /1/statuses/retweet.json
[error] => Could not authenticate you.
)
This error means that the authorization header that gets sent to twitter is not correct. Since you are using a library that's been tested and is widely used I'm guessing that you have got your CONSUMER_KEY or CONSUMER_SECRET wrong. I'd just double check these.

Resources