'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; } ?>