Skip to content

Instantly share code, notes, and snippets.

@emrancu
Last active July 18, 2019 05:59
Show Gist options
  • Save emrancu/0f60d8b1dde42b13ccb6ffa7843d8baf to your computer and use it in GitHub Desktop.
Save emrancu/0f60d8b1dde42b13ccb6ffa7843d8baf to your computer and use it in GitHub Desktop.
<?php
namespace App\Http\Controllers\Gmail;
use App\Http\Controllers\Assets\RequestHandlerController;
use App\Models\Core\Bot;
use App\Models\Core\IntentFlow;
use App\Models\Core\Question;
use App\Models\Elements\CRM\Contact;
use App\Models\Facebook\Audiences\Attribute;
use App\Models\Integrations\CalendarIntegration;
use App\Utilities\NLP\ConfusedQuestions;
use App\Utilities\NLP\NLPHandler;
use function foo\func;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Sentinel;
use App\Models\Facebook\Audiences\Audiences;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Google_Client;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Redirect;
use App\Models\Gmail\GmailBot;
use Webpatser\Uuid\Uuid;
use Illuminate\Support\Str;
class GmailController extends Controller
{
public $client;
public $accessToken;
public $tokenInfo;
public $header;
public $refreshToken;
public $emailAddress;
public $userInfoFromDb;
public $answer;
public $nlpData;
public $intentAnswer;
public $intents = null;
public function __construct()
{
$this->client = new Google_Client();
$this->client->setClientId(config('chatbot.GMAIL_CONFIG.CLIENT_ID'));
$this->client->setClientSecret(config('chatbot.GMAIL_CONFIG.CLIENT_SECRET'));
$this->client->setRedirectUri(config('chatbot.GMAIL_CONFIG.REDIRECT_URL'));
//$this->client->setRedirectUri("https://41579ef5.ngrok.io/api/gmail/token");
$this->client->setDeveloperKey('AIzaSyAoIcllkW9PswynNsc4HrbHIv38Gw1Sh1k');
$this->client->addScope('https://mail.google.com/');
$this->client->addScope('https://www.googleapis.com/auth/calendar');
$this->client->setAccessType('offline');
$this->client->setApprovalPrompt('force');
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index() {
return view("gmail.create");
}
/**
* @param $mail_address
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function dashboard($mail_address)
{
$bot_key = $mail_address;
$botType = Bot::findBotType($bot_key);
return view("gmail.index", compact('bot_key', 'mail_address', 'botType'));
}
/**
* @return bool
* @throws GuzzleException
*/
public function create()
{
$this->accessToken = Cache::get('token') ? Cache::get('token') : $this->getToken();
if ($this->accessToken) {
$this->header = [
'Content-type' => 'application/json',
'Authorization' => 'Bearer ' . $this->accessToken
];
// For watch property
$data = [
"topicName" => "projects/cl-gmail/topics/cl-mail-pusher",
"labelIds" => ["INBOX"]
];
$watchUrl = "https://www.googleapis.com/gmail/v1/users/me/watch";
$watchResult = json_decode(RequestHandlerController::sendRequest($watchUrl, 'post', $this->header, $data));
Cache::put('updatedHistoryId', $watchResult->historyId, $watchResult->expiration);
$user = Sentinel::getUser();
$uniqueBotKey = Str::orderedUuid();
$botData = [
'id' => $uniqueBotKey,
'bot_name' => 'Gmail Bot', //Cache::get('botName'),
'bot_key' => $uniqueBotKey,
'mail_address' => Cache::get('mailAddress'),
'refresh_token' => Cache::get('refreshToken'),
'access_token' => Cache::get('token'),
'updated_history_id' => Cache::get('updatedHistoryId'),
'user_id' => $user->id
];
$checkBot = GmailBot::whereMailAddress( Cache::get('mailAddress'))->first();
if ($checkBot) {
$checkBot->update([
'refresh_token' => Cache::get('refreshToken'),
'access_token' => Cache::get('token'),
]);
Cache::forget('botName');
Cache::forget('mailAddress');
Cache::forget('refreshToken');
Cache::forget('accessToken');
Cache::forget('updatedHistoryId');
Cache::forget('token');
return redirect('gmail-bots')->with(['error' => 'A bot has already been created against this Gmail address.']);
}
GmailBot::create($botData);
Cache::forget('botName');
Cache::forget('mailAddress');
Cache::forget('refreshToken');
Cache::forget('accessToken');
Cache::forget('updatedHistoryId');
Cache::forget('token');
//need appropriate route
//return redirect()->route('dummy route');
return Redirect::to('gmail-bots');
}
return true;
}
/**
* @return bool|\Illuminate\Http\RedirectResponse|string
* @throws GuzzleException
*/
public function getToken()
{
if (!isset($_GET['code'])) {
$auth_url = $this->client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
exit();
} elseif (isset($_GET['code'])) {
$this->tokenInfo = $this->client->fetchAccessTokenWithAuthCode($_GET['code']);
$this->client->setAccessToken($this->tokenInfo);
$this->refreshToken = $this->client->getRefreshToken();
//if refreshToken is null, means bot already exits. So return to home
if ($this->refreshToken == null) {
//need appropriate route
//return redirect()->route('dummy route');
return redirect()->back()->with(['error' => 'Email is already used']);
}
$this->emailAddress = $this->getUserMailAddress($this->tokenInfo['access_token']);
Cache::put('mailAddress', $this->emailAddress, 15);
Cache::put('refreshToken', $this->refreshToken, '15');
Cache::put('accessToken_' . $this->emailAddress, $this->tokenInfo['access_token'], now()->addSeconds($this->tokenInfo['expires_in']));
Cache::put('token', $this->tokenInfo['access_token'], 15);
return redirect()->route('gmail.create');
}
return false;
}
/**
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|JsonResponse|\Illuminate\Http\Response
* @throws GuzzleException
*/
public function webhook(Request $request)
{
try {
//Extracting mail address from webhook notification
$rcvdNotificationData = base64_decode(strtr($request->message['data'], '-_', '+/'));
$mailAndHistoryData = json_decode($rcvdNotificationData);
$userMailId = $mailAndHistoryData->emailAddress;
//Getting user details from db for further use
$this->userInfoFromDb = GmailBot::whereMailAddress($userMailId)->first();
//Checking if the user access_token expires or not
if (!Cache::has('accessToken_' . $userMailId)) {
$this->tokenInfo = $this->client->fetchAccessTokenWithRefreshToken($this->userInfoFromDb->refresh_token);
Cache::put('accessToken_' . $userMailId, $this->tokenInfo['access_token'], now()->addSeconds($this->tokenInfo['expires_in']));
}
$header = [
'Content-type' => 'application/json',
'Authorization' => 'Bearer ' . Cache::get('accessToken_' . $userMailId)
];
//getting all new email data in between two history id
$historyData = $this->getHistoryData($header, $this->userInfoFromDb->updated_history_id);
//updating history id for next webhook operation
$updatedHistoryId = $mailAndHistoryData->historyId;
$this->userInfoFromDb->update(['updated_history_id' => $updatedHistoryId]);
if ($historyData && count($historyData) > 0) {
$this->mailSendingProcedure($historyData, $header);
}
return response('success', '200');
} catch (\Exception $ex) {
return response()->json('success', 200);
}
}
/**
* @param $token
* @return mixed
* @throws GuzzleException
*/
public function getUserMailAddress($token)
{
$header = [
'Content-type' => 'application/json',
'Authorization' => 'Bearer ' . $token
];
$url = "https://www.googleapis.com/gmail/v1/users/me/profile";
$userInfo = json_decode(RequestHandlerController::sendRequest($url, 'get', $header));
$this->emailAddress = $userInfo->emailAddress;
return $this->emailAddress;
}
/**
* @param $header
* @param $updatedHistoryIdFromDb
* @return mixed
* @throws GuzzleException
*/
public function getHistoryData($header, $updatedHistoryIdFromDb)
{
$historyUrl = "https://www.googleapis.com/gmail/v1/users/me/history?historyTypes=messageAdded&startHistoryId=" . $updatedHistoryIdFromDb; // its the 1 step back history id from webhook. get it from db
$historyDataList = json_decode(RequestHandlerController::sendRequest($historyUrl, 'get', $header), true);
return array_get($historyDataList, 'history');
}
/**
* @param $historyData
* @param $header
* @throws \Exception
* @throws GuzzleException
*/
public function mailSendingProcedure($historyData, $header)
{
//listing all new email ids from $historyData
$mailIdsFromHistoryList = array();
foreach ($historyData as $key => $value) {
$mailIdsFromHistoryList[$key] = $value['messages'][0]['id'];
}
for ($i = 0; $i < sizeof($mailIdsFromHistoryList); $i++) {
//mail details work steps
$mailId = $mailIdsFromHistoryList[$i];
//operation by individual mail ids.
$mailUrl = "https://www.googleapis.com/gmail/v1/users/me/messages/" . $mailId;
$mailDetails = RequestHandlerController::sendRequest($mailUrl, 'get', $header);
$decodedMailDetails = json_decode($mailDetails);
if (in_array('INBOX', $decodedMailDetails->labelIds)) {
$mailInfo = $this->extractMailInformation($decodedMailDetails);
if ($mailInfo['inReplyTo'] == null) {
$this->createAudienceForGmailBot($mailInfo);
}
$this->replyOfMail($mailInfo);
}
}
}
/**
* @param $decodedMailDetails
* @return array
* @throws GuzzleException
*/
public function extractMailInformation($decodedMailDetails)
{
//13 variables
$senderNameAndMail = null;
$senderMail = null;
$senderName = null;
$receivedAt = null;
$timeZone = null;
$mailBody = null;
$messageId = null;
$subject = null;
$receiverNameMail = null;
$receiverMail = null;
$threadId = null;
$reference = null;
$inReplyTo = null;
foreach ($decodedMailDetails->payload->headers as $headData) {
switch ($headData->name) {
case 'From':
$senderNameAndMail = $headData->value;
break;
case 'Return-Path':
$senderMail = trim(str_replace(['<', '>'], '', $headData->value));
break;
case 'Date':
$receivedAt = $headData->value;
break;
case 'Message-ID':
$messageId = $headData->value;
break;
case 'Subject':
$subject = $headData->value;
break;
case 'To':
$receiverNameMail = $headData->value;
break;
case 'Delivered-To':
$receiverMail = $headData->value;
break;
case 'References':
$reference = $headData->value;
break;
case 'In-Reply-To':
$inReplyTo = $headData->value;
break;
}
}
//text
$mailBody = base64_decode(strtr($decodedMailDetails->payload->parts[0]->body->data, '-_', '+/'));
//Log::info('raw data: ' . $decodedMailDetails->payload->parts[0]->body->data);
$senderName = trim(str_replace([$senderMail, '<', '>', '"'], '', $senderNameAndMail));
$receiverName = trim(str_replace([$receiverMail, '<', '>', '"'], '', $receiverNameMail));
$timeZone = substr($receivedAt, -5);
$threadId = $decodedMailDetails->threadId;
// Extracting body and signature from mailbody
$bodyAndSignature = $this->mailBodyExtractorFromPythonEndpoint($mailBody);
$decodedBodyAndSignature = json_decode($bodyAndSignature);
$contactNum = $this->getContactNum($decodedBodyAndSignature->signature);
return [
'senderNameAndMail' => $senderNameAndMail,
'senderMail' => $senderMail,
'senderName' => $senderName,
'receivedAt' => $receivedAt,
'mailBody' => trim($decodedBodyAndSignature->body),
'messageId' => $messageId,
'subject' => $subject,
'receiverNameMail' => $receiverNameMail,
'receiverMail' => $receiverMail,
'receiverName' => $receiverName,
'timeZone' => $timeZone,
'threadId' => $threadId,
'reference' => $reference,
'inReplyTo' => $inReplyTo,
'signature' => $decodedBodyAndSignature->signature,
'contact' => $contactNum,
'body_intent' => $decodedBodyAndSignature->appointment
];
}
/**
* @param $SignatureData
* @return mixed
* @throws GuzzleException
*/
public function getContactNum($SignatureData)
{
$signatureHeader = [
'Content-type' => 'appliction/json'
];
$signature = [
"text" => $SignatureData
];
try {
$contactData = json_decode(RequestHandlerController::sendRequest('http://128.199.149.246/closerbot', 'post', $signatureHeader, $signature));
$mobile = null;
if (!empty($contactData->phone_numbers[0])) {
$mobile = $contactData->phone_numbers[0];
}
return $mobile;
} catch (\Exception $e) {
Log::info('Cant extract mobile num: ' . $e);
}
}
/**
* @param $mailBody
* @return null|\Psr\Http\Message\StreamInterface|string
* @throws GuzzleException
*/
public function mailBodyExtractorFromPythonEndpoint($mailBody)
{
$headerForBodyExtraction = [
'Content-type' => 'Application/json'
];
$bodyToExtract = [
'email' => $mailBody
//'email' => addslashes($mailBody)
];
$bodyAndSignature = null;
try {
$bodyAndSignature = RequestHandlerController::sendRequest('http://128.199.149.246/email', 'post', $headerForBodyExtraction, $bodyToExtract);
} catch (\Exception $error) {
Log::info("Error : " . $error);
}
return $bodyAndSignature;
}
/**
* reply of mail in thread for both new mail and replay mail
* @param $mailInfo
* @throws GuzzleException
*/
public function replyOfMail($mailInfo)
{
//saving user info in crm
$this->saveUserInfoToCrm($mailInfo);
$mailToBeSent = $this->mailContentToBeSent($mailInfo);
if($this->answer === null){
Log::info('null answer');
exit();
}
$mailFormat = $this->rfcMailFormat($mailToBeSent, $mailInfo);
$this->client->setAccessToken(Cache::get('accessToken_' . trim($mailInfo['receiverMail'])));
$objGMail = new \Google_Service_Gmail($this->client);
//sending mail
try {
$mime = rtrim(strtr(base64_encode($mailFormat), '+/', '-_'), '=');
$msg = new \Google_Service_Gmail_Message();
$msg->setRaw($mime);
$msg->setThreadId($mailInfo['threadId']);
$sent = $objGMail->users_messages->send("me", $msg);
//Log::info($sent->labelIds[0]);
} catch (\Exception $error) {
Log::info("Can not send email (Error) : " . $error);
}
}
/**
* @param $mailInfo
*/
public function saveUserInfoToCrm($mailInfo)
{
try {
$crm = Contact::whereEmail(trim($mailInfo['senderMail']))->first();
$botId = GmailBot::whereMailAddress(trim($mailInfo['receiverMail']))->first();
if ($crm == null) {
$crmData = [
"alias_id" => Uuid::generate()->string,
"name" => $mailInfo['senderName'],
"designation" => $mailInfo['signature'],
"email" => $mailInfo['senderMail'],
"contact" => $mailInfo['contact'],
"bot_id" => $botId['id']
];
Contact::create($crmData);
}
} catch (\Exception $e) {
Log::info($e);
}
}
/**
* @param $mailInfo
* @return string
* @throws GuzzleException
*/
public function mailContentToBeSent($mailInfo)
{
$gmailBot = GmailBot::whereMailAddress(trim($mailInfo['receiverMail']))->first();
//If intent is set
if (Cache::has('intent_' . $mailInfo['senderMail'] . $mailInfo['threadId'])) {
$this->setStringToEventAns($mailInfo);
$this->setAttribute($mailInfo);
//setting up task for action if there is any
$action = Cache::get('action_' . $mailInfo['senderMail'] . $mailInfo['threadId']);
if (isset($action)) {
//calendar event action added
if (CalendarIntegration::whereBotKey(trim($mailInfo['receiverMail']))->first()) {
if ($action->name == "calendar_event") {
$createEvent = $this->sendDataToCalendarEnd($mailInfo);
$ans = $this->ansOnCreateEventStatus($createEvent, $action, $mailInfo);
return $ans;
}
}
} else {
$this->answer = "Thanks we've taken the information.";
}
$this->clearCache($mailInfo);
return $this->answer;
} // Getting intents from nlpHandler if intent_$mailAddress is not set
elseif (!Cache::has('intent_' . $mailInfo['senderMail'] . $mailInfo['threadId'])) {
//eliminating all the \n in the text
$mailInfo['mailBody'] = trim(str_replace("\n", " ", $mailInfo['mailBody']));
//This part is only for calendar event.
//Intent is coming from mailbody object from python endpoint
//Integration check
if (CalendarIntegration::whereBotKey(trim($mailInfo['receiverMail']))->first()) {
if ($mailInfo['body_intent'] == 'appointment' && $intentFlow = IntentFlow::whereBotId($gmailBot['bot_key'])->whereIntent('appointment')->first()) {
$ans = $this->resultFromRequiredEntity($intentFlow, $mailInfo, $mailInfo['body_intent']);
return $ans;
}
}
//This part works in general case
//Looking for intent
$this->nlpData = new NLPHandler([$mailInfo['mailBody']]);
$this->intents = $this->nlpData->getIntents();
//if found any intent
if (count($this->intents) > 0 && $intentFlow = IntentFlow::whereBotId($gmailBot['bot_key'])->whereIntent(trim($this->intents[0]))->first()) {
$ans = $this->resultFromRequiredEntity($intentFlow, $mailInfo, $this->intents[0]);
return $ans;
} //finding answer in answer table based on user messages if flag is true and didn't find any intent
elseif ($question = Question::whereBotId(trim($gmailBot['bot_key']))->whereMessage(trim($mailInfo['mailBody']))->with('answers')->first()) {
$ans = $this->resultFromFlow($question);
return $ans;
} else {
$ans = $this->resultFromNlu($mailInfo, $gmailBot);
return $ans;
}
}
}
/**
* mailbody to calendar event data formation
* @param $mailInfo
*/
public function setStringToEventAns($mailInfo)
{
$stringResult = $mailInfo['mailBody'];
$result = explode("\n", $stringResult);
foreach ($result as $key => $value) {
//filtering the event requirements only. must 1. format
if (preg_match("/[1-3]\./", $value)) {
$this->intentAnswer[$key] = trim(substr($value, 2));
}
}
Log::info('re ans: ' . json_encode($this->intentAnswer));
}
/**
* saving attributes
* @param $mailInfo
*/
public function setAttribute($mailInfo)
{
$requiredEntities = Cache::get('requiredEntity_' . $mailInfo['senderMail'] . $mailInfo['threadId']);
//saving attribute based on intent
foreach ($requiredEntities as $key => $requiredEntity) {
$psId = trim($mailInfo['senderMail']) . '_' . trim($mailInfo['receiverMail']);
$audience = Audiences::wherePsid($psId)->first();
$attributeData = [
"audiences_id" => $audience['id'],
"audiences_uid" => $audience['uid'],
"attribute_name" => $requiredEntity->attribute_name,
"attribute_value" => $this->intentAnswer[$key],
"attribute_slug" => $requiredEntity->attribute_slug
];
try {
Attribute::create($attributeData);
} catch (\Exception $error) {
Log::info("Error: Attribute cant be saved. " . $error);
}
}
}
/**
* @param $mailInfo
* @return mixed
* @throws GuzzleException
*/
public function sendDataToCalendarEnd($mailInfo)
{
$header = [
'Content-type' => 'application/json'
];
//Log::info('time zone: '.$mailInfo['timeZone']);
$calendarEventData = [
"title" => "Meeting with " . $mailInfo['senderName'],
"description" => '',
"location" => '',
"startTime" => $this->intentAnswer[0],
"endTime" => $this->intentAnswer[1],
"eventDate" => $this->intentAnswer[2],
"timeZone" => $mailInfo['timeZone']
];
Log::info('calendar data: ' . json_encode($calendarEventData));
try {
//sending $calendarEventData to python end for error fixing if there is any
//$urlForDateFormation = "http://128.199.149.246/datetime";
//$formattedCalendarEventData = RequestHandlerController::sendRequest($urlForDateFormation,'post', $header,$calendarEventData);
//event create
$eventUrl = 'https://platform.chatleads.io/api/calendar/createEvent/' . $mailInfo['receiverMail'];
$createEvent = json_decode(RequestHandlerController::sendRequest($eventUrl, 'post', $header, $calendarEventData));
return $createEvent;
} catch (\Exception $e) {
Log::info($e);
}
return false;
}
/**
* @param $createEvent
* @param $action
* @param $mailInfo
* @return string
*/
public function ansOnCreateEventStatus($createEvent, $action, $mailInfo)
{
if ($createEvent->status === 'success') {
$this->clearCache($mailInfo);
return $this->answer = $action->response_message . PHP_EOL;
} elseif ($createEvent->status === 'busy') {
//checking if there is any free slot for next 7 days
if (count($createEvent->availableSlot->slotTimes) < 1) {
$this->clearCache($mailInfo);
$this->answer = $this->getBusyAns($mailInfo);
return $this->answer;
}
$this->answer = $this->getSlotAns($mailInfo);
$this->answer .= 'Date: ' . $createEvent->availableSlot->slotDate . PHP_EOL;
foreach ($createEvent->availableSlot->slotTimes as $slot) {
$this->answer .= 'Start: ' . $slot->start . ' ' . 'End: ' . $slot->end . PHP_EOL;
}
return $this->answer;
} elseif ($createEvent->status === 'failed') {
$this->clearCache($mailInfo);
return $createEvent->message;
}
}
/**
* @param $mailInfo
* @return string
*/
public function getBusyAns($mailInfo)
{
$busyAnswer = 'So I checked ' . $mailInfo['receiverName'] . '\'s calendar and it looks like they are busy for the entire week. Would you like me to follow up in a couple of days with some alternate slots?' . PHP_EOL . PHP_EOL;
$busyAnswer .= 'Looking forward to hearing from you!' . PHP_EOL . PHP_EOL;
return $busyAnswer;
}
/**
* @param $mailInfo
* @return string
*/
public function getSlotAns($mailInfo)
{
$slotAns = 'It looks like ' . $mailInfo['receiverName'] . ' is not available at that time. However, please have a look at these alternative schedules and let me know what works best for you.' . PHP_EOL . PHP_EOL;
$slotAns .= 'I am an A.I based assistant, so it would be best if you were to respond with the number besides the slot that works best for you, and I will set up the meeting.' . PHP_EOL . PHP_EOL;
$slotAns .= 'Hope you have a pleasant day.' . PHP_EOL . PHP_EOL;
return $slotAns;
}
/**
* @param $mailInfo
*/
public function clearCache($mailInfo)
{
Cache::forget('index_' . $mailInfo['senderMail'] . $mailInfo['threadId']);
Cache::forget('requiredEntity_' . $mailInfo['senderMail'] . $mailInfo['threadId']);
Cache::forget('intent_' . $mailInfo['senderMail'] . $mailInfo['threadId']);
Cache::forget('action_' . $mailInfo['senderMail'] . $mailInfo['threadId']);
}
/**
* @param $intentFlow
* @param $mailInfo
* @param $intent
* @return string
*/
public function resultFromRequiredEntity($intentFlow, $mailInfo, $intent)
{
$requiredEntities = json_decode($intentFlow->required_entity);
$action = json_decode($intentFlow->action);
Cache::put('index_' . $mailInfo['senderMail'] . $mailInfo['threadId'], 0, '60');
Cache::put('requiredEntity_' . $mailInfo['senderMail'] . $mailInfo['threadId'], $requiredEntities, '60');
Cache::put('action_' . $mailInfo['senderMail'] . $mailInfo['threadId'], $action, 20);
Cache::put('intent_' . $mailInfo['senderMail'] . $mailInfo['threadId'], $intent, 20);
$this->answer .= 'Pls answer accordingly to set a meet up. For example "1. Start Time" ' . PHP_EOL . PHP_EOL;
foreach ($requiredEntities as $key => $requiredEntity) {
$this->answer .= ($key + 1) . '. ' . $requiredEntity->text . PHP_EOL;
}
return $this->answer;
}
/**
* @param $question
* @return mixed
*/
public function resultFromFlow($question)
{
$answerObject = json_decode($question->answers);
foreach ($answerObject as $key => $answer) {
$val = json_decode($answer->value);
if ($answer->type == 'text') {
$this->answer ['text'][$key] = $val->text;
} else {
$this->answer ['url'][$key] = $val->attachment->payload->url;
}
}
return $this->answer;
}
/**
* @param $mailInfo
* @param $gmailBot
* @return string
* @throws GuzzleException
*/
public function resultFromNlu($mailInfo, $gmailBot)
{
try {
$confusedQuestions = new ConfusedQuestions();
$sortedResponse = $confusedQuestions->getResponseList(trim($mailInfo['mailBody']), trim($gmailBot['bot_key']));
if (count($sortedResponse) > 0 && $sortedResponse[0]['confidence'] > 0) {
$answerObject = $sortedResponse[0]['answers'];
foreach ($answerObject as $key => $answer) {
$val = json_decode($answer['value']);
if ($answer['type'] == 'text') {
$this->answer ['text'][$key] = $val->text;
} else {
$this->answer ['url'][$key] = $val->attachment->payload->url;
}
}
return $this->answer;
} else {
$this->answer = null;
return $this->answer;
}
} catch (\Exception $e) {
Log::info($e);
}
}
/**
* mail body construction
* @param $mailToBeSent
* @param $mailInfo
* @return string
*/
public function rfcMailFormat($mailToBeSent, $mailInfo)
{
$textAns = null;
if (gettype($mailToBeSent) == 'array') {
if (isset($mailToBeSent['text'])) {
foreach ($mailToBeSent['text'] as $textMail) {
$textAns .= $textMail . PHP_EOL;
}
}
}
$Body = 'Hello ' . $mailInfo['senderName'] . ',' . PHP_EOL . PHP_EOL;
$Body .= gettype($mailToBeSent) == 'string' ? $mailToBeSent : $textAns;
$Body .= PHP_EOL . "Thank you";
$mailFormat = 'Content-Type: multipart/mixed; boundary = "separate"' . PHP_EOL;
//mail format
$mailFormat .= 'From: ' . $mailInfo['receiverNameMail'] . PHP_EOL;
$mailFormat .= 'To: ' . $mailInfo['senderMail'] . PHP_EOL;
//reference contains previous 1/2/multiple msg ids before the current msg im sending now
$mailFormat .= 'References: ' . $mailInfo['messageId'] . PHP_EOL;
// in-reply-to contains the message id im replying too
$mailFormat .= 'In-Reply-To: ' . $mailInfo['messageId'] . PHP_EOL;
$mailFormat .= 'Subject: ' . trim($mailInfo['subject']) . PHP_EOL;
$mailFormat .= 'Date: ' . $mailInfo['receivedAt'] . PHP_EOL;
$mailFormat .= 'Message-ID: ' . PHP_EOL;
$mailFormat .= '--separate' . PHP_EOL;
//-----------------text data----------------
$mailFormat .= 'Content-Type: text/plain; charset = utf-8' . PHP_EOL;
$mailFormat .= 'Content-Transfer-Encoding: quoted-printable' . PHP_EOL;
$mailFormat .= $Body . PHP_EOL;
$mailFormat .= '--separate' . PHP_EOL;
//------------------attachment--------------
if (gettype($mailToBeSent) == 'array') {
if (isset($mailToBeSent['url'])) {
foreach ($mailToBeSent['url'] as $urlMail) {
$path_info = pathinfo($urlMail);
$extention = $path_info['extension'];
$fileName = $path_info['filename'];
$mailFormat .= 'Content-Type: message/rfc822' . PHP_EOL;
$mailFormat .= 'Content-Transfer-Encoding: base64' . PHP_EOL;
$mailFormat .= 'Content-Disposition: attachment; filename="' . $fileName . '.' . $extention . '"' . PHP_EOL;
$mailFormat .= chunk_split(base64_encode(file_get_contents($urlMail)), 76, "\n") . PHP_EOL;
$mailFormat .= '--separate' . PHP_EOL;
}
}
}
//---------------end of attachment-------------
$mailFormat .= '--separate--' . PHP_EOL;
return $mailFormat;
}
/**
* Watch property needs to be activated in every 7 days [corn]
* @throws GuzzleException
*/
public function activateWatchPropertyForAllGmailBot()
{
$allBotInfos = GmailBot::get();
if ($allBotInfos) {
foreach ($allBotInfos as $allBotInfo) {
//Checking if the user access_token expires or not
if (!Cache::has('accessToken_' . $allBotInfo->mail_address)) {
$this->tokenInfo = $this->client->fetchAccessTokenWithRefreshToken($allBotInfo->refresh_token);
Cache::put('accessToken_' . $allBotInfo->mail_address, $this->tokenInfo['access_token'], now()->addSeconds($this->tokenInfo['expires_in']));
}
$header = [
'Content-type' => 'application/json',
'Authorization' => 'Bearer ' . Cache::get('accessToken_' . $allBotInfo->mail_address)
];
$data = [
"topicName" => "projects/cl-gmail/topics/cl-mail-pusher",
"labelIds" => ["INBOX"]
];
$watchUrl = "https://www.googleapis.com/gmail/v1/users/" . $allBotInfo->mail_address . "/watch";
RequestHandlerController::sendRequest($watchUrl, 'post', $header, $data);
}
}
}
/**
* @param $mailInfo
* @throws \Exception
*/
public function createAudienceForGmailBot($mailInfo)
{
try {
// Checking if the audience exists in db
$psId = trim($mailInfo['senderMail']) . '_' . trim($mailInfo['receiverMail']);
$audience = Audiences::wherePageId(trim($mailInfo['receiverMail']))->wherePsid($psId)->first();
if ($audience == null) {
//If not create a new audience
$audienceDetails = [
"uid" => Uuid::generate()->string,
"page_id" => $mailInfo['receiverMail'],
"name" => $mailInfo['senderName'],
"psid" => $psId,
"first_name" => '',
"last_name" => '',
"profile_pic" => '',
"locale" => '',
"timezone" => $mailInfo['timeZone'],
"gender" => '',
"device" => null,
"device_os" => null
];
$status = Audiences::create($audienceDetails);
}
} catch (\Exception $e) {
Log::info($e);
}
}
/**
* @param $mailAddress
* @return JsonResponse
* @throws GuzzleException
*/
public function delete($mailAddress)
{
$this->client->revokeToken();
$botInfo = GmailBot::whereMailAddress($mailAddress)->first();
if (!Cache::has('accessToken_' . $botInfo['mail_address'])) {
$this->tokenInfo = $this->client->fetchAccessTokenWithRefreshToken($botInfo->refresh_token);
Cache::put('accessToken_' . $botInfo['mail_address'], $this->tokenInfo['access_token'], now()->addSeconds($this->tokenInfo['expires_in']));
}
$header = [
'Content-type' => 'application/json',
'Authorization' => 'Bearer ' . Cache::get('accessToken_' . $botInfo['mail_address'])
];
//revoking application access
$revokeUrl = "https://accounts.google.com/o/oauth2/revoke?token=" . $botInfo['refresh_token'];
RequestHandlerController::sendRequest($revokeUrl, 'get', $header);
$botInfo->delete();
return response()->json('Deleted',200);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment