<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
//use AppBundle\Controller\SecurityController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Twilio\Rest\Client;
use AppBundle\Helpers\MailerHelper;
use Twilio\Rest\Client as Twilio;
use Doctrine\ORM\EntityManagerInterface;
use AppBundle\Helpers\Constants;
use AppBundle\Shame\Shame;
class GenericController extends Controller
{
/**
* @Route("/", name="index")
* @param Request $request
* @return string
*/
public function indexAction(Request $request)
{
return $this->render('Default/index.html.twig');
$shame = new Shame($this);
return (new JsonResponse($shame->getUsers()));
}
private function init() {
$this->shame = new Shame($this);
}
public function getP($name)
{
try {
return $this->getParameter($name);
} catch (\Exception $e) {
}
try {
return $this->getParameter(strtoupper($name));
} catch (\Exception $e) {
}
try {
return $this->getParameter(strtolower($name));
} catch (\Exception $e) {
exit($e->getMessage() . " Both upper and lower case variable names were attempted");
}
}
/**
* @Route("/generic/call", name="generic-call")
* @param Request $request
* @return string
*
* Receive a Call
*
*/
public function callAction(Request $request)
{
$To = $request->get('Called');
$From = $request->get('Caller');
$Digits = $request->get('Digits');
$shame = new Shame($this);
$shame->callLog($request);
$response = new Response();
if ((!$To) or (!$From)) {
$response->setStatusCode(Response::HTTP_BAD_REQUEST);
return $response;
}
$main_greeting =
'<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="/generic/call" finishOnKey="#" timeout="5">
<Say voice="alice">Hello! You have reached the Support Desk.
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Pause length="10"/>
<Say voice="alice">
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Say voice="alice">
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Pause length="10"/>
</Gather>
<Say voice="alice">Thank you for calling, goodbye.</Say>
</Gather>
</Response>';
$alt_greeting =
'<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="/generic/call" finishOnKey="#" timeout="5">
<Say voice="alice">I\'m sorry, that was not a valid support issue number.
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Pause length="10"/>
<Say voice="alice">
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Say voice="alice">
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Pause length="10"/>
</Gather>
<Say voice="alice">Thank you for calling, goodbye.</Say>
</Gather>
</Response>';
$alt2_greeting =
'<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="/generic/call" finishOnKey="#" timeout="5">
<Say voice="alice">I\'m sorry, that was not a valid selection.
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Pause length="10"/>
<Say voice="alice">
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Say voice="alice">
If you have a support issue number please enter it now
followed by the pound sign.</Say>
<Pause length="10"/>
</Gather>
<Say voice="alice">Thank you for calling, goodbye.</Say>
</Gather>
</Response>';
if ( ($Digits === false) or ($Digits == '') or ($Digits == '*') ) {
$response->setContent($main_greeting);
return $response;
}
if (strlen($Digits) > 1) {
$team_id = $shame->getTicketTeam($Digits);
if (!$team_id) {
if (empty($Digits)) {
$response->setContent($alt_greeting);
return $response;
}
}
} else {
$team_id=$Digits;
}
switch ($team_id) {
case 1: $team = 'A Team';break;
case 2: $team = 'B Team';break;
case 3: $team = 'C Team';break;
case 4: $team = 'D Team';break;
default:
$response->setContent($alt2_greeting);
return $response;
}
$text = "Incoming Call\nTeam: $team\n";
$response = new Response();
$data = [
'CallStatus',
'CallDuration',
'CallerName',
'Caller',
'CallerCity',
'CallerCountry',
'CallerState',
'CallerZip',
];
foreach ($data as $datum) {
if ($request->get($datum)) {
$text .= "$datum:".$request->get($datum) . "\n";
}
}
$this->send($team_id, $text);
$shame->callLog($request, 0, $team_id, 0);
$twiml =
'<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>https://chargebacks911.com/Apps/generichotlinegreeting.mp3?x=2</Play>
<Enqueue waitUrl="/generic/hold-music">' . $team . '</Enqueue>
</Response>';
$response->setContent($twiml);
return $response;
}
/**
* @Route("/generic/recording-events", name="generic-recording-events")
* @param Request $request
* @return string
*
* Receive a Callback Event
*
*/
public function recordingEventAction(Request $request)
{
$response = new Response();
$dir = $request->get('RecordingDuration');
$shame = new Shame($this);
$team_id = $shame->getCallTeam($request->get('CallSID'));
if ($dir > 20) {
$text = "Call Recording ($dir seconds)\n";
$text .= $request->get('RecordingUrl');
$this->send($team_id, $text);
}
return $response->setContent("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
}
/**
* @Route("/generic/dial-status-events", name="generic-dial-status-events")
* @param Request $request
* @return Response
*
* Receive a Callback Event
*
*/
public function dialEventAction(Request $request)
{
$response = new Response();
return $response->setContent("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
}
/**
* @Route("/generic/call-status-events", name="generic-call-status-events")
* @param Request $request
* @return string
*
* Receive a Callback Event
*
*/
public function callEventAction(Request $request)
{
$response = new Response();
$shame = new Shame($this);
$shame->callLog($request);
return $response->setContent("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
}
/**
* @Route("/generic/hold-music")
* @param Request $request
* @return string
*
* Hold Music
*
*/
public function holdMusicAction(Request $request)
{
$response = new Response();
$shame = new Shame($this);
$shame->callLog($request);
// Send a Text and Initiate agent dialing before returning hold music to play.
$data = [
'CallStatus',
'CallerName',
'Caller',
'CallerCity',
'CallerCountry',
'CallerState',
'CallerZip',
'CurrentQueueSize',
'QueuePosition',
'QueueTime',
'AvgQueueTime',
];
$text = "Caller in Queue!\n";
foreach ($data as $datum) {
if ($request->get($datum)) {
$text .= "$datum:".$request->get($datum) . "\n";
}
}
$twilio_sid = getenv('GENERIC_SID');
$twilio_token = getenv('GENERIC_TOKEN');
$twilio = new Twilio($twilio_sid, $twilio_token);
$whatsapp_sid = getenv('WHATSAPP_SID');
$whatsapp_token = getenv('WHATSAPP_TOKEN');
$whatsapp = new Twilio($whatsapp_sid, $whatsapp_token);
$who = $shame->getUsers();
$activeCounter = 0;
$oncallCounter = 0;
$team_id = $shame->getCallTeam($request->get('CallSid'));
if (!$team_id) {
$team_id = 0;
}
foreach ($who as $he) {
$phone = $he['phone'];
$name = $he['name'];
$team = $he['team_id'];
if ($team == $team_id) {
$isActive = $he['is_active'];
$isOncall = $he['is_oncall'];
if ($isActive or $isOncall) {
$activeCounter++;
if ($this->isWhatsApp($phone)) {
$what = $whatsapp->messages->create(
$phone,
array(
'from' => $this->getp("TN_WHATSAPP_SUPPORTDESK"),
'body' => $text,
)
);
} else {
$twilio->messages->create(
$phone,
array(
'from' => $this->getp("TN_GENERIC_SUPPORTDESK"),
'body' => $text
)
);
}
}
if ($isOncall) {
$oncallCounter++;
$phone = str_replace('whatsapp:','',$phone);
$call = $twilio->calls
->create($phone, // to
$this->getp("TN_GENERIC_SUPPORTDESK"), // from
array("url" => "https://apichost.com/generic/agent")
);
}
}
}
$everyone = [];
if ($oncallCounter == 0) {
// get the team members
foreach ($who as $he) {
$phone = $he['phone'];
$name = $he['name'];
$team = $he['team_id'];
if ($team == $team_id) {
$everyone[] = $phone;
}
}
$text = "WARNING - NO ONE IS ON-CALL - SO I'M CALLING EVERYBODY!!\n\n" . $text;
foreach ($everyone as $phone) {
if ($this->isWhatsApp($phone)) {
$what = $whatsapp->messages->create(
$phone,
array(
'from' => $this->getp("TN_WHATSAPP_SUPPORTDESK"),
'body' => $text,
)
);
} else {
$twilio->messages->create(
$phone,
array(
'from' => $this->getp("TN_GENERIC_SUPPORTDESK"),
'body' => $text
)
);
}
}
foreach ($everyone as $phone) {
$phone = str_replace('whatsapp:','',$phone);
$call = $twilio->calls
->create($phone, // to
$this->getp("TN_GENERIC_SUPPORTDESK"), // from
array("url" => "https://apichost.com/generic/agent")
);
}
}
return $response->setContent('<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>' . $this->getp("GENERIC_HOLDMUSIC") . '</Play>
</Response>');
}
/**
* @Route("/generic/agent-hold-music")
* @param Request $request
* @return string
*
* Agent Hold Music
*/
public function agentHoldMusicAction(Request $request)
{
$response = new Response();
return $response->setContent('<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>' . $this->getp("GENERIC_HOLDMUSIC") . '</Play>
</Response>');
}
/**
* @Route("/generic/agent")
* @param Request $request
* @return string
*
* Agent grab caller in Queue
*
*/
public function agentAction(Request $request)
{
$response = new Response();
$shame = new Shame($this);
$team_id = $shame->getUserTeam($request->get('Called'));
$team = $shame->getTeamName($team_id);
if ($request->get('Digits')) {
return $response->setContent('<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial record="record-from-ringing-dual"
recordingStatusCallback="/generic/recording-events"
recordingStatusCallbackEvent="completed"
method="GET">
<Queue>' . $team . '</Queue>
</Dial>
</Response>');
} else {
return $response->setContent('<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather>
<Say>I have a call for you. Please press 1 at any time to access the queue. If you hear music, then the queue is empty. You may stay on the line and if someone calls they will be transferred to you immediately.</Say>
</Gather>
<Say>Goodbye!</Say>
</Response>');
}
}
public function isWhatsApp($phone) {
return strpos($phone,'whatsapp') === 0;
}
public function send($team_id, $text)
{
$shame = new Shame($this);
$shame->storeText($text);
$this->output = '';
$twilio_sid = getenv('GENERIC_SID');
$twilio_token = getenv('GENERIC_TOKEN');
$twilio = new Twilio($twilio_sid, $twilio_token);
$whatsapp_sid = getenv('WHATSAPP_SID');
$whatsapp_token = getenv('WHATSAPP_TOKEN');
$whatsapp = new Twilio($whatsapp_sid, $whatsapp_token);
$who = $shame->getUsers();
$cnt = 0;
foreach ($who as $he) {
$phone = $he['phone'];
$name = $he['name'];
$team = $he['team_id'];
if ($team == $team_id) { // ($data == 'generic-supportdesk-active') { // add teams later
$isActive = $he['is_active'];
$isOncall = $he['is_oncall'];
if ($isActive or $isOncall) {
$cnt++;
if (!strpos($text, "from $name")) {
if ($this->isWhatsApp($phone)) {
$what = $whatsapp->messages->create(
$phone,
array(
'from' => $this->getp("TN_WHATSAPP_SUPPORTDESK"),
'body' => $text,
)
);
} else {
$twilio->messages->create(
$phone,
array(
'from' => $this->getp("TN_GENERIC_SUPPORTDESK"),
'body' => $text
)
);
}
}
}
}
}
return $cnt;
}
public function sendTo($text, $recipients)
{
//$shame->storeText($text);
$twilio_sid = getenv('GENERIC_SID');
$twilio_token = getenv('GENERIC_TOKEN');
$twilio = new Twilio($twilio_sid, $twilio_token);
$whatsapp_sid = getenv('WHATSAPP_SID');
$whatsapp_token = getenv('WHATSAPP_TOKEN');
$whatsapp = new Twilio($whatsapp_sid, $whatsapp_token);
foreach ($recipients as $phone) {
if ($this->isWhatsApp($phone)) {
$what = $whatsapp->messages->create(
$phone,
array(
'from' => $this->getp("TN_WHATSAPP_SUPPORTDESK"),
'body' => $text,
)
);
} else {
$twilio->messages->create(
$phone,
array(
'from' => $this->getp("TN_GENERIC_SUPPORTDESK"),
'body' => $text
)
);
}
}
}
/*
*
* SMS & WhatsApp
*
*/
/**
* @Route("/generic/text", name="generic-text")
* @param Request $request
* @return string
*
* Handle an incoming text command
* Or
* Receive a 2FA text from Twilio or Nexmo and update the 2FA table
*
*/
public function textAction(Request $request)
{
/*
Twilio sends To, From and Body
Nexmo sends to, msisdn, and text
*/
$shame = new Shame($this);
$To = $request->get('to');
$Body = $request->get('text');
$From = $request->get('msisdn');
if (!$To) {
$To = $request->get('To');
$Body = $request->get('Body');
$From = $request->get('From');
}
// $To = '+' . ltrim($To, "+"); // allow GET testing
//
// $From = '+' . ltrim($From, "+");
$response = new Response();
if ((!$To) or (!$Body)) {
$response->setStatusCode(Response::HTTP_BAD_REQUEST);
return $response;
}
switch ($To) {
// Hotlines
case $this->getp("TN_GENERIC_SUPPORTDESK"):
case $this->getp("TN_WHATSAPP_SUPPORTDESK"):
/** @var Shame $shame
*
*/
$userMeta = $shame->getUser($From);
if ($userMeta != false) {
// shortcuts
switch (strtoupper($Body)) {
case "SI":
$Body = "show issues";
break;
case "ST":
$Body = "show teams";
break;
case "SC":
$Body = "show calls";
break;
case "SU":
$Body = "show users";
break;
case "SP":
$Body = "show users";
break;
case "who":
$Body = "W";
break;
}
$bArr = explode(' ', $Body . ' 0 0 0 0 0 0');
if (empty($bArr[0])) {
exit(Constants::SMS_INVALID);
}
$arg = $bArr[1] ? $bArr[1] : $From;
if ((strtoupper($bArr[0]) == 'A') or (strtoupper($bArr[0]) == 'O')) {
$userMeta = $shame->getUser($arg);
}
if ($userMeta === false) {
// this is a new user, add this person
//$shame->storeUser($arg);
exit(Constants::SMS_NO_FEATURE);
}
switch (strtoupper($bArr[0])) {
case 'ISSUES':
$this->text($shame->showIssues());
break;
case 'TEAMS':
$this->text($shame->showTeams());
break;
case 'CALLS':
$this->text($shame->showCalls());
break;
case 'USERS':
$this->text($shame->showUsers());
break;
case 'PRODUCTS':
$this->text($shame->showProducts());
break;
case 'EMAIL':
case 'EMAILS':
case 'MAIL':
$this->text($shame->showEmail($bArr[1]));
break;
case 'SHOW':
switch (strtoupper($bArr[1])) {
case 'ISSUES':
$this->text($shame->showIssues());
break;
case 'TEAMS':
$this->text($shame->showTeams());
break;
case 'CALLS':
$this->text($shame->showCalls());
break;
case 'USERS':
$this->text($shame->showUsers());
break;
case 'PRODUCTS':
$this->text($shame->showProducts());
break;
case 'EMAIL':
case 'EMAILS':
case 'MAIL':
$this->text($shame->showEmail($bArr[2]));
break;
}
break;
case '?': // Reply with Help Twig
$this->text($this->renderView('help.html.twig'));
break;
case 'H': // Reply with Long Help Twig
case 'HELP':
$this->text($this->renderView('longhelp.html.twig'));
break;
case 'I': // Assign/Reopen Issue
case 'ISSUE': // ISSUE 222 3
$user = $shame->getUserName($From);
if (!$user) {
$user = $From;
}
$team = $shame->getTeamName($bArr[2]);
if ($team === false) {
$this->text("Invalid Team");
}
$op = $shame->getTicketOP($bArr[1]);
if ($op === false) {
$this->text("Invalid Issue ID");
}
$shame->assignIssue($bArr[1],$bArr[2]);
$this->generic_send("###############\nIssue ".$bArr[1]. " $op has been opened and assigned the $team team");
$this->text("OK");
break;
case 'A': // Active Team
$this->text ($shame->setActive($arg));
break;
case 'X': // Exit Active Team
$this->text($shame->setInActive($arg));
break;
case 'O': // OnCall Team
$this->text($shame->setOnCall($arg));
break;
case 'N': // Not OnCall
$this->text($shame->setNotOnCall($arg));
break;
case 'C': // Close Issue
case 'CLOSE': // Close Issue
$this->text($shame->closeIssue($bArr[1]));
break;
case 'W': // Who's OnCall and Active
case 'E': // Who's Everyone
if (strtoupper($bArr[0])=='W') {
$output = "Who is Active/On Call\n";
} else {
$output = "List of All Users\n";
}
$who = $shame->getUsers();
foreach ($who as $he) {
$name = '('.$he['name'].')';
if (true) { // ($data == $ACTIVE) { // break this into teams
$isActive = $he['is_active'];
$isOncall = $he['is_oncall'];
if (($isActive or $isOncall) or strtoupper($bArr[0])=='E') {
$output .= "\n$name - ";
if ($isActive) {
$output .= "Active ";
} else {
$output .= "- ";
}
if ($isOncall) {
$output .= "Call";
} else {
$output .= "-";
}
}
}
}
if (strtoupper($bArr[0])=='W') {
$output .= "\n\nSend E for Everyone";
}
$this->text($output);
break;
case 'R':
case 'REPLY': // REPLY 22 Hey!
// Get the sender of issue $bArr[1], then email the body of the email to him and then treat it like default text too
$m = new MailerHelper();
$user = $shame->getUserName($From);
if (!$user) {
$user = $From;
}
$team = $shame->getUserTeamName($From);
$email = $shame->getTicketOP($bArr[1]);
$issue_id = $bArr[1];
if ($email !== false) {
$body = "$Body<br/><br/>This is a mobile response from $user<br/><br/>Reply or call " . $this->getp('TN_GENERIC_SUPPORT') . " using PIN " . $issue_id;
$subject = 'Support (' . $issue_id . ') - ' . $user;
$shame->storeEmail($team, $subject, $body, $email, $issue_id);
$response = $m->sendEmail([$email],
$this->getp('EM_GENERIC_SUPPORT'), $subject,
$body);
$cnt = $this->generic_send("Msg from $user:\n$Body");
$this->text("SendEmail: $response");
} else {
exit(Constants::SMS_NO_OP);
}
break;
default:
if (strlen($Body) > 1) {
$user = $shame->getUserName($From);
if (!$user) {
$user = $From;
}
switch ($To) {
case $this->getp("TN_GENERIC_SUPPORTDESK"):
case $this->getp("TN_WHATSAPP_SUPPORTDESK"):
$cnt = $this->generic_send("Msg from $user:\n$Body");
break;
default:
$response->setStatusCode(Response::HTTP_BAD_REQUEST);
return $response;
}
$sent = $this->output;
$this->text("Sent to:\n$sent\n\n");
} else {
exit(Constants::SMS_NO_FEATURE);
}
}
exit(Constants::SMS_OK);
} else {
exit(Constants::SMS_ACCESS_DENIED);
}
default:
exit(Constants::SMS_NO_RESPONSE);
}
}
public function generic_send($text)
{
$shame = new Shame($this);
$shame->storeText($text);
$this->output = '';
$twilio_sid = getenv('GENERIC_SID');
$twilio_token = getenv('GENERIC_TOKEN');
$twilio = new Twilio($twilio_sid, $twilio_token);
$whatsapp_sid = getenv('WHATSAPP_SID');
$whatsapp_token = getenv('WHATSAPP_TOKEN');
$whatsapp = new Twilio($whatsapp_sid, $whatsapp_token);
$who = $shame->getUsers();
$cnt = 0;
foreach ($who as $he) {
$phone = $he['phone'];
$name = $he['name'];
if (true) { // Texts or announcements should be sent to all teams
$isActive = $he['is_active'];
$isOncall = $he['is_oncall'];
if ($isActive or $isOncall) {
$cnt++;
if (!strpos($text, "from $name")) {
$this->output .= "$name\n";
// If the user is a WhatsApp user, do it thataway
if ($this->isWhatsApp($phone)) {
$what = $whatsapp->messages->create(
$phone,
array(
'from' => $this->getp("TN_WHATSAPP_SUPPORTDESK"),
'body' => $text,
)
);
} else {
$twilio->messages->create(
$phone,
array(
'from' => $this->getp("TN_GENERIC_SUPPORTDESK"),
'body' => $text
)
);
}
}
}
}
}
return $cnt;
}
function text($text)
{
$output = '';
$ctr=0;
if (gettype($text) == 'array') {
foreach ($text as $t) {
$ctr++;
//$output .= "($ctr)";
if (gettype($t) == 'array') {
foreach ($t as $ff => $tt) {
if (!is_numeric($ff)) {
$output .= $tt . ' ';
}
}
} else {
$output .= $t;
}
$output = trim($output) . "\n";
}
$text = str_replace(['<','>'],['(',')'],$output);
}
exit('<?xml version="1.0" encoding="UTF-8"?><Response><Message><Body>' . $text . '</Body></Message></Response>');
}
/**
* @Route("/generic-whatsapp/message", name="whatsapp-message")
* @param Request $request
* @return string
*
* ApiVersion "2010-04-01"
* SmsSid "SM850e0407f4a2d0258258d56ec0dbe4b3"
* SmsStatus "received"
* SmsMessageSid "SM850e0407f4a2d0258258d56ec0dbe4b3"
* NumSegments "1"
* From "whatsapp:+17273072253"
* To "whatsapp:+14155238886"
* MessageSid "SM850e0407f4a2d0258258d56ec0dbe4b3"
* Body "Forks"
* AccountSid "AC6e2afd53042aa7c31f655fa9c64c47ce"
* NumMedia "0"
*
*/
public function messageAction(Request $request)
{
return $this->textAction($request);
}
/**
* @Route("/generic-whatsapp/events", name="whatsapp-events")
* @param Request $request
* @return string
*
* Receive a Callback Event
*
*/
public function whatsappEventAction(Request $request)
{
return (new Response("OK"));
}
}