Files
crm.clientright.ru/telegram.php

399 lines
19 KiB
PHP
Raw Normal View History

<?php
/*********************************************************************************
* Endpoint для вызова снаружи вебхуками входящих сообщений в Telegram
* All Rights Reserved.
* Contributor(s): Илья Руденко itsaturn@yandex.ru
********************************************************************************/
error_reporting(E_ALL);
ini_set('display_errors', '1');
include_once 'modules/Users/Users.php';
include_once 'include/utils/CommonUtils.php';
include_once 'include/utils/utils.php';
require_once('include/Webservices/Utils.php');
require_once 'include/Webservices/Create.php';
require_once 'include/Webservices/Revise.php';
require_once 'include/utils/WhatsApp.php';
require_once 'includes/Loader.php';
vimport ('includes.runtime.Globals');
vimport ('includes.runtime.BaseModel');
vimport ('includes.runtime.LanguageHandler');
$str = file_get_contents('php://input');
$logstring = date('Y-m-d H:i:s').' '.$str.PHP_EOL; // Пишем в лог то, что будем обрабатывать
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
$data = json_decode($str, true); // Формируем массив
$message = $data['message']; // Тело сообщения
$firstname = $data['firstname']; // Имя отправителя
$botname = $data['botname']; // Имя отправителя
if (isset($data['mobile'])) {
$lastname = $data['lastname']; // Фамилия отправителя
} else {
$lastname = '-';
}
// Логируем полученный botname для диагностики
$logstring = date('Y-m-d H:i:s').' Получен botname: "'.$botname.'"'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
if (!isset($botname) or empty($botname)) {
// Если ничего не передали, будем считать, что это первый бот
$botname = 'klientprav_bot';
$logstring = date('Y-m-d H:i:s').' botname не передан, устанавливаем по умолчанию: klientprav_bot'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
} else {
if ($botname <> 'klientprav_bot' and $botname <> 'lexpriority_bot' and $botname <> 'clientright_bot') {
// Если что-то передали, но это не один из трех известных ботов, то будем считать, что это первый бот
$logstring = date('Y-m-d H:i:s').' Неизвестный botname: "'.$botname.'", устанавливаем klientprav_bot'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
$botname = 'klientprav_bot';
}
}
$tgid = $data['tgid']; // Telegram ID отправителя
$mime_type = $data['mime_type'];
$file_size = $data['file_size'];
$file_id = $data['file_id'];
$customer = 0;
// Сначала попробуем найти клиента по его tgid
if ($tgid <> 0) {
$query = 'select c.contactid, c.firstname, c.lastname, e.smownerid as userid
from vtiger_contactdetails c
left join vtiger_crmentity e on e.crmid = c.contactid
where e.deleted = 0 and c.phone = ?';
$result = $adb->pquery($query, array($tgid));
if ($adb->num_rows($result) > 0) {
$customer = $adb->query_result($result, 0, 'contactid');
$userid = $adb->query_result($result, 0, 'userid');
$crmid = '12x'.$adb->query_result($result, 0, 'contactid');
$setype = 'Contacts';
$firstname = $adb->query_result($result, 0, 'firstname');
$lastname = $adb->query_result($result, 0, 'lastname');
$logstring = date('Y-m-d H:i:s').' Найден клиент с ID: '.$customer.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
}
}
$user = Users::getActiveAdminUser(); // Получаем пользователя, под которым будем создавать записи
// А если и по телефону не нашлось - тогда будем создавать Контакта
if ($customer == 0) {
$logstring = date('Y-m-d H:i:s').' По телефону не нашли - будем создавать'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
try {
$params = array (
'firstname' => $firstname,
'lastname' => $lastname,
'phone' => $tgid,
'assigned_user_id' => $user
);
if ($botname == 'lexpriority_bot') {
$params['cf_1740'] = '000';
}
//$logstring = date('Y-m-d H:i:s').' Массив: '.json_encode($params).PHP_EOL;
//file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
$contact = vtws_create('Contacts', $params, $user);
$output = 'ID : '.$contact['id'];
$customer = substr($contact['id'], 3);
$crmid = $contact['id'];
$setype = 'Contacts';
$userid = substr($user, 3);
} catch (WebServiceException $ex) {
$output = $ex->getMessage();
}
$logstring = date('Y-m-d H:i:s').' Создание Контакта : '.$output.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
}
// Ну и теперь наконец-то создадим коммент
if ($customer <> 0) {
$msg = '';
$allowed_types = array(
'text/plain',
'image',
'image/png',
'image/jpeg',
'image/jpg',
'application/pdf',
'application/msword',
'application/excel',
'application/vnd.ms-excel',
'application/vnd.oasis.opendocument.text',
'application/vnd.oasis.opendocument.spreadsheet',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
); //Список разрешенных к сохранению типов файлов
$images = array('image', 'image/png', 'image/jpeg', 'image/jpg');
if (isset($file_id)) {
// Передан какой-то файл
$filename = $data['filename'];
// Определяем токен бота для скачивания файла
if ($botname == 'klientprav_bot') {
$bot_token = '6118440594:AAGpqeudXF9wHSZ7vpAsXQ4Jp5XXlUoqB1A';
} elseif ($botname == 'lexpriority_bot') {
$bot_token = '6631721508:AAG0FIXhlprPGeeb_6zh5gjOpNdWzSWIRS8';
} elseif ($botname == 'clientright_bot') {
$bot_token = '7919885676:AAEPfOt-oLl2rR1FhlGDd_yqk6ScXJr43T0';
} else {
// На всякий случай, если botname не определен
$bot_token = '6118440594:AAGpqeudXF9wHSZ7vpAsXQ4Jp5XXlUoqB1A';
$logstring = date('Y-m-d H:i:s').' ВНИМАНИЕ: botname не распознан при определении токена, используем токен klientprav_bot по умолчанию'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
}
$logstring = date('Y-m-d H:i:s').' Для botname="'.$botname.'" выбран токен бота: '.substr($bot_token, 0, 20).'...'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
if ($file_size > 5242880) {
// Размером более 5мб
$msg = 'Передан файл более 5 мб - НЕ загружен!';
$logstring = date('Y-m-d H:i:s').' '.$msg.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
Reply($tgid, 'Файл '.$filename.' не доставлен!'.PHP_EOL.PHP_EOL.'Объем файла не должен превышать 5Мб', $bot_token);
} else {
if (!in_array($mime_type, $allowed_types)) {
// Недопустимого формата
$msg = 'Передан файл недопустимого формата (не Документ, не PDF и не картина) - НЕ загружен!';
$logstring = date('Y-m-d H:i:s').' '.$msg.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
Reply($tgid, 'Файл '.$filename.' не доставлен!'.PHP_EOL.PHP_EOL.'Принимаются только картинки, PDF и документы Word и Excel', $bot_token);
}
}
if (!isset($message) or empty($message)) {
// Если это просто файл, без текста
if ($msg <> '') {
// и при этом файл мы не будем грузить
$message = $msg;
} else {
$message = 'Файл во вложении';
}
} else {
// Если текст сообщения есть
if ($msg <> '') {
// И есть файл, который мы не будем грузить
$message .= PHP_EOL.'======='.PHP_EOL.$msg;
}
}
}
// Проверка на 0 на тот случай, если при создании Контакта был какой-то exception и мы не получили id нового клиента
try {
$params = array (
'commentcontent' => $message,
'related_to' => $crmid,
'channel' => 'Telegram',
'assigned_user_id' => $user
);
//$logstring = date('Y-m-d H:i:s').' Массив: '.json_encode($params).PHP_EOL;
//file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
$comment = vtws_create('ModComments', $params, $user);
$output = 'ID : '.$comment['id'];
// Почему-то при попытке сразу прописать customer при создании коммента, в половине случаев вылетает ошибка
// поэтому сначала просо создаем комментарий, а потом отдельным апдейтом корректируем, что это не просто коммент, а ответ от клиента
$commentid = substr($comment['id'], 3);
$query = 'update vtiger_modcomments set customer = ?, userid = 0 where modcommentsid = ?';
$adb->pquery($query, array($customer, $commentid));
} catch (WebServiceException $ex) {
$output = $ex->getMessage();
}
$logstring = date('Y-m-d H:i:s').' Создание коммента: '.$output.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
if (isset($file_id) and $msg == '') {
// Файл есть и он валидный - надо скачать и загрузить в коммент
// Массив всех доступных токенов для перебора
$all_bot_tokens = array(
'klientprav_bot' => '6118440594:AAGpqeudXF9wHSZ7vpAsXQ4Jp5XXlUoqB1A',
'lexpriority_bot' => '6631721508:AAG0FIXhlprPGeeb_6zh5gjOpNdWzSWIRS8',
'clientright_bot' => '7919885676:AAEPfOt-oLl2rR1FhlGDd_yqk6ScXJr43T0'
);
// Определяем порядок перебора токенов - сначала пробуем тот, который соответствует botname
$tokens_to_try = array();
if (isset($all_bot_tokens[$botname])) {
$tokens_to_try[] = array('name' => $botname, 'token' => $all_bot_tokens[$botname]);
}
// Добавляем остальные токены для перебора
foreach ($all_bot_tokens as $name => $token) {
if ($name != $botname) {
$tokens_to_try[] = array('name' => $name, 'token' => $token);
}
}
$file_path = null;
$success = false;
// Перебираем токены, пока не найдем рабочий
foreach ($tokens_to_try as $bot_info) {
$try_token = $bot_info['token'];
$try_name = $bot_info['name'];
$url = 'https://api.telegram.org/bot'.$try_token.'/getFile';
file_put_contents('logs/tg_inbound.log', date('Y-m-d H:i:s').' Пробуем токен '.$try_name.' для file_id '.$file_id.PHP_EOL, FILE_APPEND);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_POSTFIELDS, array('file_id' => $file_id));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($curl);
$output = json_decode($output, true);
if (curl_errno($curl)) {
$logstring = date('Y-m-d H:i:s').' Ошибка curl для '.$try_name.': '.curl_error($curl).PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
} else {
if ($output['ok']) {
// Успех! Нашли правильный токен
$file_path = $output['result']['file_path'];
$bot_token = $try_token; // Обновляем токен для дальнейшего использования
$success = true;
$logstring = date('Y-m-d H:i:s').' ✅ УСПЕХ! Токен '.$try_name.' сработал. Получен путь: '.$file_path.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
curl_close($curl);
break; // Прерываем цикл, файл найден
} else {
$logstring = date('Y-m-d H:i:s').' ❌ Токен '.$try_name.' не подошел: '.$output['description'].PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
}
}
curl_close($curl);
}
if (!$success) {
$logstring = date('Y-m-d H:i:s').' ⚠️ ВНИМАНИЕ: Ни один токен не смог получить файл!'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
}
if (isset($file_path)) {
// Получили путь закачки файла
$url = 'https://api.telegram.org/file/bot'.$bot_token.'/'.$file_path;
$current_id = $adb->getUniqueID("vtiger_crmentity");
$date_var = date('Y-m-d H:i:s');
$ownerid = getUserId($userid, $customer); // Если у клиента есть активный Проект - достанем оттуда ответственного
$upload_file_path = decideFilePath();
if ($filename == 'image') {
// Нам прислали скриншот без расширения - возьмем то имя, которое ему дала телега
$slash = strpos($file_path, '/');
$filename = substr($file_path, $slash+1);
}
file_put_contents($upload_file_path . $current_id . "_" . $filename, file_get_contents($url));
$logstring = date('Y-m-d H:i:s').' Файл '.$filename.' типа '.$mime_type.' сохранен в storage'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
if (in_array($mime_type, $images)) {
// Если прислали картинку, то преобразуем ее в PDF
$PDFPath = jpg2pdf($upload_file_path . $current_id . "_" . $filename);
// Грохнем ненужную картинку
unlink($upload_file_path . $current_id . "_" . $filename);
// Из полного пути к PDF вытащим чисто имя файла
$file_parts = pathinfo($filename);
$base_name = $file_parts['filename'];
$filename = $base_name . '.pdf';
$mime_type= 'application/pdf';
}
$sql1 = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,createdtime,modifiedtime) values(?,?,?,?,?,?)";
$params1 = array($current_id, $ownerid, $ownerid, 'ModComments Attachment', $adb->formatDate($date_var, true), $adb->formatDate($date_var, true));
$adb->pquery($sql1, $params1);
$logstring = date('Y-m-d H:i:s').' Добавили аттач в crmentity'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
$sql2 = "insert into vtiger_attachments(attachmentsid, name, type, path, storedname) values(?,?,?,?,?)";
$params2 = array($current_id, $filename, $mime_type, $upload_file_path, $filename);
$adb->pquery($sql2, $params2);
$logstring = date('Y-m-d H:i:s').' Добавили аттач в attachments'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
$sql3 = "insert into vtiger_seattachmentsrel(crmid, attachmentsid) values(?,?)";
$adb->pquery($sql3, array($commentid, $current_id));
$sql4 = 'update vtiger_modcomments set filename = ? where modcommentsid = ?';
$adb->pquery($sql4, array($current_id, $commentid));
$logstring = date('Y-m-d H:i:s').' связали аттач с комментом '.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
}
}
// А теперь покажем всплывашку пользователю
// Собираем ссылку на сущность, куда добавлен коммент
$link = 'module='.$setype.'&view=Detail&record='.$customer.'&app=MARKETING';
// Собираем текст уведомления с именем отправителя
$title = $firstname.' '.$lastname.' - новое сообщение'; // Итоговый текст уведомления
$userid = getUserId($userid, $customer); // Если у клиента есть активный Проект - достанем оттуда ответственного
// Ищем непрочтенную всплывашку с этим клиентом
$query = 'select id from vtiger_vdnotifierpro where userid = ? and crmid = ? and title = ? and status = 5';
$result = $adb->pquery($query, array($userid, $customer, $title));
if ($adb->num_rows($result) > 0) {
// Обновляем время в старой всплывашке, чтобы не плодить дубли
$id = $adb->query_result($result, 0, 'id');
$query = 'update vtiger_vdnotifierpro set modifiedtime = ? where id = ?';
$result = $adb->pquery($query, array(date('Y-m-d H:i:s'), $id));
//$logstring = date('Y-m-d H:i:s').' id записи '.$id.PHP_EOL;
//file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
} else {
// Добавляем новую всплывашку
$query = 'insert into vtiger_vdnotifierpro (userid, modulename, crmid, modiuserid, link, title, action, modifiedtime, status) values (?, ?, ?, 0, ?, ?, "", ?, 5)';
$result = $adb->pquery($query, array($userid, $setype, $customer, $link, $title, date('Y-m-d H:i:s')));
}
} else {
$logstring = date('Y-m-d H:i:s').' Почему-то мы не нашли и не создали Контакта'.PHP_EOL;
file_put_contents('logs/tg_inbound.log', $logstring, FILE_APPEND);
}
function getUserId($userid, $contactid) {
global $adb;
$query = 'select e.smownerid as userid
from vtiger_project p
left join vtiger_crmentity e on e.crmid = p.projectid
where e.deleted = 0 and p.linktoaccountscontacts = ? and p.projectstatus <> "completed"';
$result = $adb->pquery($query, array($contactid));
if ($adb->num_rows($result) == 1) {
// Единственный активный Проект - вытащим оттуда ответственного
$output = $adb->query_result($result, 0, 'userid');
} else {
// Активных Проектов нет, а может быть несколько - значит ответственным будет владелец Контакта
$output = $userid;
}
return $output;
}
function Reply($chat_id, $message, $bot_token) {
$params = array(
'chat_id' => $chat_id, // id получателя сообщения
'text' => $message, // текст сообщения
'parse_mode' => 'HTML', // режим отображения сообщения, не обязательный параметр
);
$curl = curl_init();
$url = 'https://api.telegram.org/bot'.$bot_token.'/sendMessage';
curl_setopt($curl, CURLOPT_URL, $url); // адрес api телеграмм
curl_setopt($curl, CURLOPT_POST, true); // отправка данных методом POST
curl_setopt($curl, CURLOPT_TIMEOUT, 10); // максимальное время выполнения запроса
curl_setopt($curl, CURLOPT_POSTFIELDS, $params); // параметры запроса
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // чтобы получить нормальный ответ
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
?>