- Added comprehensive AI Assistant system (aiassist/ directory): * Vector search and embedding capabilities * Typebot proxy integration * Elastic search functionality * Message classification and chat history * MCP proxy for external integrations - Implemented Court Status API (GetCourtStatus.php): * Real-time court document status checking * Integration with external court systems * Comprehensive error handling and logging - Enhanced S3 integration: * Improved file backup system with metadata * Batch processing capabilities * Enhanced error logging and recovery * Copy operations with URL fixing - Added Telegram contact creation API - Improved error logging across all modules - Enhanced callback system for AI responses - Extensive backup file storage with timestamps - Updated documentation and README files - File storage improvements: * Thousands of backup files with proper metadata * Fix operations for broken file references * Project-specific backup and recovery systems * Comprehensive file integrity checking Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
278 lines
14 KiB
PHP
278 lines
14 KiB
PHP
<?php
|
||
/*********************************************************************************
|
||
* Набор методов для работы с Telegram через родное API
|
||
* All Rights Reserved.
|
||
* Contributor(s): Илья Руденко itsaturn@yandex.ru
|
||
********************************************************************************/
|
||
require_once 'include/utils/utils.php';
|
||
|
||
function TelegramSendComment($commentid, $message){
|
||
// Вызывается из /modules/ModComments/actions/SaveAjax.php
|
||
global $adb;
|
||
$isAttach = false;
|
||
|
||
$query = 'SELECT e.setype, c.related_to
|
||
FROM vtiger_modcomments c
|
||
LEFT JOIN vtiger_crmentity e on e.crmid = c.related_to
|
||
where c.modcommentsid = '.$commentid;
|
||
$result = $adb->pquery($query);
|
||
|
||
$output = 'YES';
|
||
|
||
if ($adb->num_rows($result) == 0) {
|
||
$output = 'Комментарий не найден';
|
||
} else {
|
||
// Проверяем наличие файлов через vtiger_seattachmentsrel
|
||
$attachQuery = 'SELECT COUNT(*) as file_count FROM vtiger_seattachmentsrel WHERE crmid = '.$commentid;
|
||
$attachResult = $adb->pquery($attachQuery);
|
||
$fileCount = $adb->query_result($attachResult, 0, "file_count");
|
||
$isAttach = $fileCount > 0;
|
||
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' Проверка файлов для комментария '.$commentid.': найдено '.$fileCount.' файлов, isAttach='.$isAttach.PHP_EOL, FILE_APPEND);
|
||
$setype = $adb->query_result($result, 0, "setype");
|
||
$related_to = $adb->query_result($result, 0, "related_to");
|
||
if ($setype == 'Contacts') {
|
||
// Если коммент отправляется из Контакта
|
||
$query = 'select phone from vtiger_contactdetails where phone > 0 and contactid = '.$related_to;
|
||
$result = $adb->pquery($query);
|
||
if ($adb->num_rows($result) == 0) {
|
||
$output = 'У Контакта отсутствует идентификатор чата в поле Рабочий телефон';
|
||
} else {
|
||
$chat_id = $adb->query_result($result, 0, "phone");
|
||
}
|
||
} else {
|
||
if ($setype == 'Project') {
|
||
// Если коммент отправляется из Проекта
|
||
$query = 'select cf_1826 from vtiger_projectcf where cf_1826 <> "" and projectid = '.$related_to;
|
||
$result = $adb->pquery($query);
|
||
if ($adb->num_rows($result) == 0) {
|
||
$output = 'У Проекта отсутствует телефон';
|
||
} else {
|
||
$chat_id = $adb->query_result($result, 0, "cf_1826");
|
||
}
|
||
} else {
|
||
$output = 'Комментарий к неизвестной сущности';
|
||
}
|
||
}
|
||
}
|
||
|
||
//echo $output.'<br>';
|
||
//echo $query.'<br>';
|
||
|
||
|
||
if ($output <> 'YES') {
|
||
$logstring = date('Y-m-d H:i:s').' Отправка комментария ID: '.$commentid.' не удалать по причине: '.$output.PHP_EOL;
|
||
file_put_contents('logs/tg_outbound.log', $logstring, FILE_APPEND);
|
||
//echo $logstring.'<br>';
|
||
} else {
|
||
if ($setype == 'Contacts') {
|
||
$query = 'select cf_1740 from vtiger_contactscf where contactid = '.$related_to;
|
||
} else
|
||
if ($setype == 'Project') {
|
||
$query = 'select cf.cf_1740
|
||
from vtiger_project p
|
||
left join vtiger_contactscf cf on cf.contactid = p.linktoaccountscontacts
|
||
where p.projectid = '.$related_to;
|
||
}
|
||
file_put_contents('logs/tg_outbound.log', $query.PHP_EOL, FILE_APPEND);
|
||
//echo $query.'<br>';
|
||
|
||
$result = $adb->pquery($query);
|
||
|
||
|
||
$insurance = $adb->query_result($result, 0, "cf_1740");
|
||
//echo 'Вот оно: "'.$insurance.'"<br>';
|
||
if (empty($insurance)) {
|
||
//echo 'Нет<br>';
|
||
$bot_token = '6118440594:AAGpqeudXF9wHSZ7vpAsXQ4Jp5XXlUoqB1A';
|
||
} else {
|
||
//echo 'Есть<br>';
|
||
$bot_token = '6631721508:AAG0FIXhlprPGeeb_6zh5gjOpNdWzSWIRS8';
|
||
}
|
||
|
||
//echo $bot_token.'<br>';
|
||
|
||
//$bot_token = '6118440594:AAGpqeudXF9wHSZ7vpAsXQ4Jp5XXlUoqB1A';
|
||
|
||
$logstring = date('Y-m-d H:i:s').' Отправка комментария ID: '.$commentid.' с токеном: '.$bot_token.' в chat_id'.$chat_id.PHP_EOL;
|
||
file_put_contents('logs/tg_outbound.log', $logstring, FILE_APPEND);
|
||
//echo $logstring.'<br>';
|
||
$logstring = 'Текст: '.$message.PHP_EOL;
|
||
file_put_contents('logs/tg_outbound.log', $logstring, FILE_APPEND);
|
||
//echo $logstring.'<br>';
|
||
|
||
// Заменяем одинарные и двойные кавычки в тексте на апострофы
|
||
$message = str_replace('"', '`', $message);
|
||
$message = str_replace("'", "`", $message);
|
||
// Меняем переносы строк на \n
|
||
$message = preg_replace('/\R/u', '\n', $message);
|
||
|
||
// параметры, которые отправятся в api телеграмм
|
||
$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);
|
||
//echo $url.'<br>';
|
||
|
||
if (curl_errno($curl)) {
|
||
$output = date('Y-m-d H:i:s').' Что-то пошло не так: '.curl_error($curl);
|
||
} else {
|
||
$output = date('Y-m-d H:i:s').' Ответ от Telegram на отправку текста сообщения: '.$output;
|
||
$response = json_decode($output, true);
|
||
$messageid = $response['result']['message_id']; // Выкурили id отправленного сообщения в исчислении Телеграмма
|
||
$updquery = 'update vtiger_modcomments set messageid = ? where modcommentsid = ?';
|
||
$updresult = $adb->pquery($updquery, array($messageid, $commentid));
|
||
}
|
||
file_put_contents('logs/tg_outbound.log', $output.PHP_EOL, FILE_APPEND);
|
||
//echo $output.'<br>';
|
||
|
||
if ($isAttach) {
|
||
// Получаем файлы, связанные с комментарием
|
||
// Используем запрос БЕЗ vtiger_notes, так как для файлов комментариев там нет записей
|
||
$query = 'SELECT a.attachmentsid, a.name, a.type, a.path, a.storedname
|
||
FROM vtiger_seattachmentsrel ar
|
||
LEFT JOIN vtiger_attachments a ON a.attachmentsid = ar.attachmentsid
|
||
LEFT JOIN vtiger_crmentity ce ON ce.crmid = ar.attachmentsid
|
||
WHERE ar.crmid = '.$commentid.' AND ce.setype LIKE "Documents%"';
|
||
|
||
$result = $adb->pquery($query);
|
||
$fileCount = $adb->num_rows($result);
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' [FIXED_VERSION_v2] Найдено файлов для отправки: '.$fileCount.PHP_EOL, FILE_APPEND);
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' Запрос: '.$query.PHP_EOL, FILE_APPEND);
|
||
|
||
if ($fileCount == 0) {
|
||
// Дополнительная диагностика
|
||
$debugQuery = 'SELECT COUNT(*) as cnt FROM vtiger_seattachmentsrel WHERE crmid = '.$commentid;
|
||
$debugResult = $adb->pquery($debugQuery);
|
||
$debugCount = $adb->query_result($debugResult, 0, "cnt");
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: vtiger_seattachmentsrel содержит '.$debugCount.' записей для комментария '.$commentid.PHP_EOL, FILE_APPEND);
|
||
|
||
// Проверим что именно в vtiger_seattachmentsrel
|
||
$debugQuery2 = 'SELECT attachmentsid FROM vtiger_seattachmentsrel WHERE crmid = '.$commentid;
|
||
$debugResult2 = $adb->pquery($debugQuery2);
|
||
if ($adb->num_rows($debugResult2) > 0) {
|
||
$attachmentId = $adb->query_result($debugResult2, 0, "attachmentsid");
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: attachmentsid='.$attachmentId.PHP_EOL, FILE_APPEND);
|
||
|
||
// Проверим vtiger_crmentity
|
||
$debugQuery3 = 'SELECT crmid, setype FROM vtiger_crmentity WHERE crmid = '.$attachmentId;
|
||
$debugResult3 = $adb->pquery($debugQuery3);
|
||
if ($adb->num_rows($debugResult3) > 0) {
|
||
$crmid = $adb->query_result($debugResult3, 0, "crmid");
|
||
$setype = $adb->query_result($debugResult3, 0, "setype");
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: vtiger_crmentity crmid='.$crmid.', setype='.$setype.PHP_EOL, FILE_APPEND);
|
||
|
||
// Проверим условие LIKE
|
||
$likeMatch = (strpos($setype, 'Documents') === 0) ? 'YES' : 'NO';
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: setype LIKE "Documents%" = '.$likeMatch.PHP_EOL, FILE_APPEND);
|
||
|
||
// Попробуем выполнить упрощенный запрос
|
||
$simpleQuery = 'SELECT COUNT(*) as cnt FROM vtiger_seattachmentsrel ar LEFT JOIN vtiger_crmentity ce ON ce.crmid = ar.attachmentsid WHERE ar.crmid = '.$commentid.' AND ce.setype LIKE "Documents%"';
|
||
$simpleResult = $adb->pquery($simpleQuery);
|
||
$simpleCount = $adb->query_result($simpleResult, 0, "cnt");
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: Упрощенный запрос нашел '.$simpleCount.' записей'.PHP_EOL, FILE_APPEND);
|
||
} else {
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: НЕТ записи в vtiger_crmentity для attachmentsid='.$attachmentId.PHP_EOL, FILE_APPEND);
|
||
}
|
||
}
|
||
}
|
||
|
||
curl_setopt($curl, CURLOPT_URL, 'https://api.telegram.org/bot'.$bot_token.'/sendDocument'); // адрес api телеграмм
|
||
curl_setopt($curl, CURLOPT_HEADER, false);
|
||
|
||
if ($adb->num_rows($result) > 0) {
|
||
for ($i = 0; $i < $adb->num_rows($result); $i++) {
|
||
$attachmentsid = $adb->query_result($result, $i, 'attachmentsid');
|
||
$origname = $adb->query_result($result, $i, 'name');
|
||
$mimetype = $adb->query_result($result, $i, 'type');
|
||
$path = $adb->query_result($result, $i, 'path');
|
||
$storedname = $adb->query_result($result, $i, 'storedname');
|
||
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: Файл '.$i.': attachmentId='.$attachmentsid.', name='.$origname.', path='.$path.', storedname='.$storedname.PHP_EOL, FILE_APPEND);
|
||
|
||
// Определяем URL файла - строим S3 URL из path и storedname
|
||
$fileUrl = '';
|
||
if (!empty($path) && !empty($storedname)) {
|
||
if (strpos($path, 's3://') === 0) {
|
||
// Новый формат: s3://bucket/path
|
||
$bucket = str_replace('s3://', '', $path);
|
||
$fileUrl = 'https://s3.twcstorage.ru/' . $bucket . '/' . $storedname;
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: Строим S3 URL из path+storedname (s3://): '.$fileUrl.PHP_EOL, FILE_APPEND);
|
||
} else {
|
||
// Старый формат: обычный path
|
||
$fileUrl = 'https://s3.twcstorage.ru/f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c/' . $path . '/' . $storedname;
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' DEBUG: Строим S3 URL из path+storedname (обычный): '.$fileUrl.PHP_EOL, FILE_APPEND);
|
||
}
|
||
} else {
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' ERROR: Не удалось определить URL файла для attachmentId='.$attachmentsid.', path='.$path.', storedname='.$storedname.PHP_EOL, FILE_APPEND);
|
||
continue;
|
||
}
|
||
|
||
if (!empty($fileUrl)) {
|
||
// Отправляем файл как бинарные данные (и для S3, и для локальных файлов)
|
||
if (strpos($fileUrl, 'http') === 0) {
|
||
// S3 файл - скачиваем содержимое и создаем временный файл
|
||
$tempFile = tempnam(sys_get_temp_dir(), 'tg_file_');
|
||
$fileContent = file_get_contents($fileUrl);
|
||
if ($fileContent !== false) {
|
||
file_put_contents($tempFile, $fileContent);
|
||
$arrayQuery = array(
|
||
'chat_id' => $chat_id,
|
||
'caption' => $origname,
|
||
'document' => curl_file_create($tempFile, $mimetype, $origname)
|
||
);
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' Создан временный файл для S3: '.$tempFile.', размер: '.strlen($fileContent).' байт'.PHP_EOL, FILE_APPEND);
|
||
} else {
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' Ошибка скачивания S3 файла: '.$fileUrl.PHP_EOL, FILE_APPEND);
|
||
continue;
|
||
}
|
||
} else {
|
||
// Локальный файл
|
||
$arrayQuery = array(
|
||
'chat_id' => $chat_id,
|
||
'caption' => $origname,
|
||
'document' => curl_file_create($fileUrl, $mimetype, $origname)
|
||
);
|
||
}
|
||
|
||
curl_setopt($curl, CURLOPT_POSTFIELDS, $arrayQuery);
|
||
$output = curl_exec($curl);
|
||
|
||
// Удаляем временный файл если он был создан
|
||
if (isset($tempFile) && file_exists($tempFile)) {
|
||
unlink($tempFile);
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' Временный файл удален: '.$tempFile.PHP_EOL, FILE_APPEND);
|
||
}
|
||
|
||
if (curl_errno($curl)) {
|
||
$output = date('Y-m-d H:i:s').' Что-то пошло не так при отправке файла '.$origname.' : '.curl_error($curl);
|
||
} else {
|
||
$output = date('Y-m-d H:i:s').' Ответ от Telegram на отправку файла: '.$output;
|
||
}
|
||
file_put_contents('logs/tg_outbound.log', $output.PHP_EOL, FILE_APPEND);
|
||
} else {
|
||
file_put_contents('logs/tg_outbound.log', date('Y-m-d H:i:s').' Не удалось определить путь к файлу: '.$origname.PHP_EOL, FILE_APPEND);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
curl_close($curl);
|
||
|
||
}
|
||
|
||
return $output;
|
||
}
|
||
|
||
?>
|