Twilio REST API sequential Dialling - php

I really can't figure out why my code isn't working because Twilio's debugger isnt giving me errors so I don't know what to do...I am trying to make Sequential dialing in REST api using Twilio so it should keep calling numbers in order until one person picks up..Below is my code I have written so far. I am using sessions to keep track of the calls.
File Name:dial.php
<?php
session_start();
require 'Services/Twilio.php';
$version = "2010-04-01";
$arr = array('4167641123','6478604321','9058553456');
$sid = '....';
$token = '...';
$from = '....';
$to = '416.....';
$callback = 'www.site.com/dial.php';
$client = new Services_Twilio($sid, $token, $version);
//if this is our very first call then CallStatus should be empty so it means we can use the emptiness of this variable
//to trigger our very first call
if (!(isset($_REQUEST['CallStatus'])))
{
try {
$call = $client->account->calls->create(
$from,
$arr[0],
'http://demo.twilio.com/welcome/voice/',
array('Timeout' => 1,
'StatusCallback' => $callback)
);
var_dump($call);
} catch (Exception $e) {
var_dump($e);
}
}
// if the CallStatus variable is not empty then the else statement will execute
else
{
//if this part of code runs for the first time, it means this is our 2nd call because the 1st person did not pick up
//this means the second number in the array will be called
//each time this statement runs it adds a 1 to the index of the array but if the last index number called was the final and
//last number in the array, then this statement wont run and instead session at the bottom if statement will be initialized to 0
//so that if this script is ran again it will start off from the first number in the array
if (!($_SESSION['X']>=count($arr)-1) && isset($_REQUEST['CallStatus']) && ($_REQUEST['CallStatus']=='failed'|| $_REQUEST['CallStatus']=='no-answer' || $_REQUEST['CallStatus']=='busy'))
{
$_SESSION['X']=$_SESSION['X']+1;
try {
$call = $client->account->calls->create(
$from,
$arr[SESSION['X']],
'http://demo.twilio.com/welcome/voice/',
array('Timeout' => 1,
'StatusCallback' => $callback)
);
var_dump($call);
} catch (Exception $e) {
var_dump($e);
}
}
//initializes the session to 0 because if we have reached to this else statement,
//then it means the if statement above did not run and we have already called the last person
//in the phone number array so we are at an end and we must close the program
//by leaving session at 0 for the next trial to run properly
else
{
$_SESSION['X']=0;
}
}
I have this other file same, sequential diallnig written using php and twilio's Dial verb, the Dial verb's parameters allow it to pass the array index but in my case I don't know how to pass the array index parameter....any ideas?
<?php
// Set the numbers to call
$numbers = array("<number to call 1>", "<number to call 2>", "<number to call n>");
$number_index = isset($_REQUEST['number_index']) ? $_REQUEST['number_index'] : "0";
$DialCallStatus = isset($_REQUEST['DialCallStatus']) ? $_REQUEST['DialCallStatus'] : "";
header("content-type: text/xml");
// Check the status of the call and
// that there is a valid number to call
if($DialCallStatus!="completed" && $number_index<count($numbers)){
?>
<Response>
<Dial action="attempt_call.php?number_index=<?php echo $number_index+1 ?>">
<Number url="screen_for_machine.php">
<?php echo $numbers[$number_index] ?>
</Number>
</Dial>
</Response>
<?php
} else {
?>
<Response>
<Hangup/>
</Response>
<?php
}
?>

Your code has syntax errors and such.
For example SESSION['X']=0; is not doing what you might have thought it is doing. If that's a session variable, it should be written as $_SESSION['X']=0;.
To spot these issues, enable error reporting to the highest level, then log errors to a file and then watch that file. It will give you some hints.
See Error Handling and Logging Docs.

Related

twilio play hold music and redirecting to dial

Aim: I want that when the call is created it should play music instead of ringing and noone is available to pick call . after playing music it should say it.
after that it should redirect to feedback page
Now: call is created and mp3 is played when we pick the call and feedback page is running when it is dialling the call
So I want a solution to handle this
<?php
if (($nowtime >= $start_time) && ($nowtime <= $end_time)){
$the_mnum = $con ->load_field($the_id, 'the_mnum');
//$m= $the_mnum;
//echo $the_mnum;
?> <Say voice="woman">
We are directing your call to the therapist.
</Say>
<?php
$check_therapist = true;
$_SESSION["the_mnum"] = $the_mnum;
break;
}
}
if ($check_therapist){
$version = '';
$sid = '';
$token = '';
$client = new Services_Twilio($sid, $token, $version);
$call = $client->account->calls->create("+1", $the_mnum, "wekaw1.mp3", array());
echo $call->sid;
?>
<Redirect>feedback.php</Redirect>
<?php } else {?>
<Say voice="woman">
No listener is available right now.
We will give you a call back shortly when we have available listener.
</Say>
<?php } ?>
</Response>
In order to play hold music instead of rings before 2 numbers are connected you need to use <Enqueue> and <Queue> combined and initiate a call via our Rest API.
The following is an example implementation in PHP.
You need to assign the file below to your phone number. This code will <enqueue> the call and initiate a call forwarding to your number. This will also initiate a request to the second file that you need to create (modify_leg.php).
In some file first.php:
$name = $_POST['CallSid'];
echo '<Response><Enqueue>'.$name.'</Enqueue></Response>';
// Make sure to include php-helper library
require('../Services/Twilio.php'); // Loads the library
$account_sid = 'ACxxxxxxxxxxxxxxxxx';
$auth_token = 'aaxxxxxxxxxxx';
$from_number = '+1xxxxxx';
$to_number = '+1xxxxxxxx';
$client = new Services_Twilio($account_sid, $auth_token);
$message = $client->account->calls->create($from_number, $to_number, 'http://Your-FQDN/modify_leg.php?callSid='.$name);
Now in (modify_leg.php) you will pass $_GET[callSid] so it will actually connect both calls once you answer the phone and the caller will listen to music until you actually pick up the call.
<?php
$who = $_GET['callSid'];
?>
<Response>
<Dial><Queue><?php echo $who ?></Queue></Dial>
</Response>

file_get_contents occasionally causes warning, but still fetches data

My script is working most of the times, but in every 8th try or so I get an error. I'll try and explain this. This is the error I get (or similar):
{"gameName":"F1 2011","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/81163/movie_max.webm?t=1447354814","gameId":"44360","finalPrice":1499,"genres":"Racing"}
{"gameName":"Starscape","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/900679/movie_max.webm?t=1447351523","gameId":"20700","finalPrice":999,"genres":"Action"}
Warning: file_get_contents(http://store.steampowered.com/api/appdetails?appids=400160): failed to open stream: HTTP request failed! in C:\xampp\htdocs\GoStrap\game.php on line 19
{"gameName":"DRAGON: A Game About a Dragon","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/2038811/movie_max.webm?t=1447373449","gameId":"351150","finalPrice":599,"genres":"Adventure"}
{"gameName":"Monster Mash","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/900919/movie_max.webm?t=1447352342","gameId":"36210","finalPrice":449,"genres":"Casual"}
I'm making an application that fetches information on a random Steam game from the Steam store. It's quite simple.
The script takes a (somewhat) random ID from a text file (working for sure)
The ID is added to the ending of an URL for the API, and uses file_get_contents to fetch the file. It then decodes json. (might be the problem somehow)
Search for my specified data. Final price & movie webm is not always there, hence the if(!isset())
Decide final price and ship back to ajax on index.php
The error code above suggests that I get the data I need in 4 cases, and an error once. I only wanna receive ONE json string and return it, and only in-case $game['gameTrailer'] and $game['final_price'] is set.
This is the php (it's not great, be kind):
<?php
//Run the script on ajax call
if(isset($_POST)) {
fetchGame();
}
function fetchGame() {
$gameFound = false;
while(!$gameFound) {
////////// ID-picker //////////
$f_contents = file("steam.txt");
$url = $f_contents[mt_rand(0, count($f_contents) - 1)];
$answer = explode('/',$url);
$gameID = $answer[4];
$trimmed = trim($gameID);
////////// Fetch game //////////
$json = file_get_contents('http://store.steampowered.com/api/appdetails?appids='.$trimmed);
$game_json = json_decode($json, true);
if(!isset($game_json[$trimmed]['data']['movies'][0]['webm']['max']) || !isset($game_json[$trimmed]['data']['price_overview']['final'])) {
continue;
}
$gameFound = true;
////////// Store variables //////////
$game['gameName'] = $game_json[$trimmed]['data']['name'];
$game['gameTrailer'] = $game_json[$trimmed]['data']['movies'][0]['webm']['max'];
$game['gameId'] = $trimmed;
$game['free'] = $game_json[$trimmed]['data']['is_free'];
$game['price'] = $game_json[$trimmed]['data']['price_overview']['final'];
$game['genres'] = $game_json[$trimmed]['data']['genres'][0]['description'];
if ($game['free'] == TRUE) {
$game['final_price'] = "Free";
} elseif($game['free'] == FALSE || $game['final_price'] != NULL) {
$game['final_price'] = $game['price'];
} else {
$game['final_price'] = "-";
}
}
////////// Return to AJAX (index.php) //////////
echo
json_encode(array(
'gameName' => $game['gameName'],
'gameTrailer' => $game['gameTrailer'],
'gameId' => $game['gameId'],
'finalPrice' => $game['final_price'],
'genres' => $game['genres'],
))
;
}
?>
Any help will be appreciated. Like, are there obvious reason as to why this is happening? Is there a significantly better way? Why is it re-iterating itself at least 4 times when it seems to have fetched that data I need? Sorry if this post is long, just trying to be detailed with a lacking php/json-vocabulary.
Kind regards, John
EDIT:
Sometimes it returns no error, just multiple objects:
{"gameName":"Prime World: Defenders","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/2028642/movie_max.webm?t=1447357836","gameId":"235360","finalPrice":899,"genres":"Casual"}
{"gameName":"Grand Ages: Rome","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/5190/movie_max.webm?t=1447351683","gameId":"23450","finalPrice":999,"genres":"Simulation"}

Facebook api , Recursive Function and 500 error

this is my first project using facebook api and facebook PHP sdk , basically i'm trying to get all user statuses. I wrote a script that should work , but i got an 500 error (even if i changed max execution times or set time limit (0)), but only when i use a recursive function inside, take a look to the code :
$request = new FacebookRequest(
$session,
'GET',
'/me/statuses'
);
$response = $request->execute();
$graphObject = $response->getGraphObject();
$x = $graphObject->getProperty('data');
$y = $x->asArray(); //now i got an array
$paging = $graphObject->getProperty('paging'); // i pick paging with "next" and "prevoiuos "
$paged = $paging->asArray(); //as array
$counter = 0 ;
foreach ($y as $el){
echo ('<h3>'.$y[$counter]->message.'</h3>');
echo "<br/>";
echo "<br/>";
$counter++;
}
$next = $paged['next']; // now i got url for load 20 more statuses
$response = file_get_contents($next); // get content of url
//recoursive function every time i use looper with content of next
function looper($response){
$array = json_decode($response, true);
$secondarray = ($array['data']);
$paging = ($array['paging']); // again i pick url for load next statuses
$next = $paging['next'];// again i pick url for load next statuses
$nextResponse = file_get_contents($next);// again i pick url for load next statuses and i will use this.
$counter2 = 0 ;
foreach ($secondarray as $el){ // put on page next 20 statuses
echo ('<h3>'. $secondarray[$counter2]['message'] .'</h3>');
echo "<br/>";
echo "<br/>";
$counter2++;
}
if ( is_null($nextResponse) == false ){ // if in next call i got 20 more statuses(not empty) call again this function
looper($nextResponse);
} else { echo "last message" ; die();} //else stop.
}
looper($response);
}
If i dont recall the function (basically i comment out the if statement) script works fine and prints 20+20 statuses , else it give me 500 internal error.
As i said i tried changin max execution time or set_time_limit(0), but nothing happens.
I'm not sure if problem is my hosting (godaddy) , or if my script is not good / not efficent. any help?
Thanks Nico
I think I found your issue. You are asigning $nextResponse the value returned by file_get_contents. See http://php.net/manual/es/function.file-get-contents.php it returns false in case of content couldnt be retrieved. Try checking for false instead of null:
..........
if ( false != $nextResponse ){ // if in next call i got 20 more statuses(not empty) call again this function
looper($nextResponse);
} else { echo "last message" ; die();} //else stop.

PHP waiting for correct response with cURL

I don't know how to make this.
There is an XML Api server and I'm getting contents with cURL; it works fine. Now I have to call the creditCardPreprocessors state. It has 'in progress state' too and PHP should wait until the progess is finished. I tried already with sleep and other ways, but I can't make it. This is a simplified example variation of what I tried:
function process_state($xml){
if($result = request($xml)){
// It'll return NULL on bad state for example
return $result;
}
sleep(3);
process_state($xml);
}
I know, this can be an infite loop but I've tried to add counting to exit if it reaches five; it won't exit, the server will hang up and I'll have 500 errors for minutes and Apache goes unreachable for that vhost.
EDIT:
Another example
$i = 0;
$card_state = false;
// We're gona assume now the request() turns back NULL if card state is processing TRUE if it's done
while(!$card_state && $i < 10){
$i++;
if($result = request('XML STUFF')){
$card_state = $result;
break;
}
sleep(2);
}
The recursive method you've defined could cause problems depending on the response timing you get back from the server. I think you'd want to use a while loop here. It keeps the requests serialized.
$returnable_responses = array('code1','code2','code3'); // the array of responses that you want the function to stop after receiving
$max_number_of_calls = 5; // or some number
$iterator = 0;
$result = NULL;
while(!in_array($result,$returnable_responses) && ($iterator < $max_number_of_calls)) {
$result = request($xml);
$iterator++;
}

Having trouble getting the right idea

well i'm writing a php code to edit tags and data inside those tags but i'm having big trouble getting my head around the thing.
basically i have an xml file similar to this but bigger
<users>
<user1>
<password></password>
</user1>
</users>
and the php code i'm using to try and change the user1 tag is this
function mod_user() {
// Get global Variables
global $access_level;
// Pull the data from the form
$entered_new_username = $_POST['mod_user_new_username'];
$entered_pass = $_POST['mod_user_new_password'];
$entered_confirm_pass = $_POST['mod_user_confirm_new_password'];
$entered_new_roll = $_POST['mod_user_new_roll'];
$entered_new_access_level = $_POST['mod_user_new_access_level'];
// Grab the old username from the last page as well so we know who we are looking for
$current_username = $_POST['mod_user_old_username'];
// !!-------- First thing is first. we need to run checks to make sure that this operation can be completed ----------------!!
// Check to see if the user exist. we just use the normal phaser since we are only reading and it's much easier to make loop through
$xml = simplexml_load_file('../users/users.xml');
// read the xml file find the user to be modified
foreach ($xml->children() as $xml_user_get)
{
$xml_user = ($xml_user_get->getName());
if ($xml_user == $entered_new_username){
// Set array to send data back
//$a = array ("error"=>103, "entered_user"=>$new_user, "entered_roll"=>$new_roll, "entered_access"=>$new_access_level);
// Add to session to be sent back to other page
// $_SESSION['add_error'] = $a;
die("Username Already exist - Pass");
// header('location: ../admin.php?page=usermanage&task=adduser');
}
}
// Check the passwords and make sure they match
if ($entered_pass == $entered_confirm_pass) {
// Encrypt the new password and unset the old password variables so they don't stay in memory un-encrytped
$new_password = hash('sha512', $entered_pass);
unset ($entered_pass, $entered_confirm_pass, $_POST['mod_user_new_password'], $_POST['mod_user_confirm_pass']);
}
else {
die("passwords did not match - Pass");
}
if ($entered_new_access_level != "") {
if ($entered_new_access_level < $access_level){
die("Access level is not sufficiant to grant access - Pass");
}
}
// Now to load up the xml file and commit changes.
$doc = new DOMDocument;
$doc->formatOutput = true;
$doc->perserveWhiteSpace = false;
$doc->load('../users/users.xml');
$old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0);
// For initial debugging - to be deleted
if ($old_user == $current_username)
echo "old username found and matches";
// Check the variables to see if there is something to change in the data.
if ($entered_new_username != "") {
$xml_old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0)->replaceChild($entered_new_username, $old_user);
echo "Username is now: " . $current_username;
}
if ($new_pass != "") {
$current_password = $doc->getElementsByTagName($current_user)->item(0)->getElementsByTagName('password')->item(0)->nodeValue;
//$replace_password = $doc
}
}
when run with just the username entered for change i get this error
Catchable fatal error: Argument 1 passed to DOMNode::replaceChild() must be an instance of DOMNode, string given, called in E:\xampp\htdocs\CGS-Intranet\admin\html\useraction.php on line 252 and defined in E:\xampp\htdocs\CGS-Intranet\admin\html\useraction.php on line 201
could someone explain to me how to do this or show me how they'd do it.. it might make a little sense to me to see how it's done :s
thanks
$entered_new_username is a string so you'll need to wrap it with a DOM object, via something like$doc->createElement()
$xml_old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0)->replaceChild($doc->createElement($entered_new_username), $old_user);
This may not be quite right, but hopefully it points you in the correct direction.
alright got it writing and replacing the node that i want but i have ran into other issues i have to work out (IE: it's replacing the whole tree rather then just changing the node name)
anyway the code i used is
// For initial debugging - to be deleted
if ($old_user == $current_username)
echo "old username found and matches";
// Check the variables to see if there is something to change in the data.
if ($entered_new_username != "") {
try {
$new_node_name = $doc->createElement($entered_new_username);
$old_user->parentNode->replaceChild($new_node_name, $old_user);
}
catch (DOMException $e) {
echo $e;
}
echo "Username is now: " . $current_username;
}
if ($new_pass != "") {
$current_password = $doc->getElementsByTagName($current_user)->item(0)->getElementsByTagName('password')->item(0)->nodeValue;
//$replace_password = $doc
}
$doc->save('../users/users.xml');

Categories