2025-09-26 10:43:05 +03:00
|
|
|
|
<?php
|
|
|
|
|
|
// get_chat_history.php
|
|
|
|
|
|
// Эндпоинт для получения истории чата
|
|
|
|
|
|
|
|
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
|
|
header('Access-Control-Allow-Origin: *');
|
|
|
|
|
|
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
|
|
|
|
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
|
|
|
|
|
|
|
|
|
|
// Обработка preflight запросов
|
|
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
|
|
|
|
http_response_code(200);
|
|
|
|
|
|
exit();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Включение отчета об ошибках для отладки
|
|
|
|
|
|
error_reporting(E_ALL);
|
|
|
|
|
|
ini_set('display_errors', 1);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// Получение данных из POST запроса
|
|
|
|
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
|
|
|
|
|
|
|
|
if (!$input) {
|
|
|
|
|
|
throw new Exception('Invalid JSON input');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$context = $input['context'] ?? [];
|
|
|
|
|
|
$sessionId = $input['sessionId'] ?? 'default-session';
|
|
|
|
|
|
|
|
|
|
|
|
// Логирование запроса
|
|
|
|
|
|
error_log("Chat History: Request for session {$sessionId}, context: " . json_encode($context));
|
|
|
|
|
|
|
|
|
|
|
|
// URL n8n webhook для получения истории
|
|
|
|
|
|
$n8nHistoryUrl = 'https://n8n.clientright.pro/webhook/5f50933f-f761-455a-9a7d-9fe0909e3f26';
|
|
|
|
|
|
|
|
|
|
|
|
// Подготовка данных для n8n
|
|
|
|
|
|
$payload = [
|
|
|
|
|
|
'context' => $context,
|
|
|
|
|
|
'sessionId' => $sessionId,
|
|
|
|
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
|
|
|
|
'source' => 'crm-history-request'
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// Логирование исходящего запроса
|
|
|
|
|
|
error_log("Chat History: Sending to n8n - URL: {$n8nHistoryUrl}, Payload: " . json_encode($payload));
|
|
|
|
|
|
|
|
|
|
|
|
// Отправка запроса к n8n
|
|
|
|
|
|
$ch = curl_init();
|
|
|
|
|
|
curl_setopt_array($ch, [
|
|
|
|
|
|
CURLOPT_URL => $n8nHistoryUrl,
|
|
|
|
|
|
CURLOPT_POST => true,
|
|
|
|
|
|
CURLOPT_POSTFIELDS => json_encode($payload),
|
|
|
|
|
|
CURLOPT_HTTPHEADER => [
|
|
|
|
|
|
'Content-Type: application/json',
|
|
|
|
|
|
'User-Agent: CRM-History-Request/1.0'
|
|
|
|
|
|
],
|
|
|
|
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
|
|
|
|
CURLOPT_TIMEOUT => 30, // Короткий таймаут для истории
|
|
|
|
|
|
CURLOPT_SSL_VERIFYPEER => true,
|
|
|
|
|
|
CURLOPT_FOLLOWLOCATION => true
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$response = curl_exec($ch);
|
|
|
|
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
|
|
$error = curl_error($ch);
|
|
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
|
|
|
|
|
|
if ($error) {
|
|
|
|
|
|
throw new Exception("cURL error: {$error}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($httpCode !== 200) {
|
|
|
|
|
|
// Если n8n недоступен, возвращаем пустую историю
|
|
|
|
|
|
error_log("Chat History: n8n unavailable (HTTP {$httpCode}), returning empty history");
|
|
|
|
|
|
echo json_encode([
|
|
|
|
|
|
'success' => true,
|
|
|
|
|
|
'history' => [],
|
|
|
|
|
|
'message' => 'История недоступна, начинаем новый диалог',
|
|
|
|
|
|
'source' => 'fallback'
|
|
|
|
|
|
]);
|
|
|
|
|
|
exit();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Логирование сырого ответа для отладки
|
|
|
|
|
|
error_log("Chat History: Raw response from n8n: " . substr($response, 0, 500) . (strlen($response) > 500 ? '...' : ''));
|
|
|
|
|
|
|
|
|
|
|
|
// Парсинг ответа от n8n
|
|
|
|
|
|
$responseData = json_decode($response, true);
|
|
|
|
|
|
if (!$responseData) {
|
|
|
|
|
|
error_log("Chat History: JSON decode failed. Response: " . $response);
|
|
|
|
|
|
throw new Exception('Invalid JSON response from n8n. Response: ' . substr($response, 0, 200));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Логирование ответа
|
|
|
|
|
|
error_log("Chat History: Received response - " . json_encode($responseData));
|
|
|
|
|
|
|
|
|
|
|
|
// Обработка истории
|
|
|
|
|
|
$history = [];
|
|
|
|
|
|
$rawHistory = [];
|
|
|
|
|
|
|
|
|
|
|
|
// Проверяем разные форматы ответа от n8n
|
|
|
|
|
|
if (isset($responseData['history']) && is_array($responseData['history'])) {
|
|
|
|
|
|
$rawHistory = $responseData['history'];
|
|
|
|
|
|
} elseif (isset($responseData[0]['data']) && is_array($responseData[0]['data'])) {
|
|
|
|
|
|
$rawHistory = $responseData[0]['data'];
|
|
|
|
|
|
} elseif (is_array($responseData)) {
|
|
|
|
|
|
$rawHistory = $responseData;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Преобразуем в формат для AI Drawer
|
|
|
|
|
|
foreach ($rawHistory as $item) {
|
|
|
|
|
|
// Проверяем что это валидное сообщение
|
|
|
|
|
|
if (!isset($item['content']) || empty(trim($item['content']))) {
|
|
|
|
|
|
continue; // Пропускаем пустые сообщения
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-22 09:38:38 +03:00
|
|
|
|
// Формируем timestamp в ISO формате для JavaScript
|
|
|
|
|
|
$timestamp = null;
|
|
|
|
|
|
if (isset($item['created_at']) && !empty($item['created_at'])) {
|
|
|
|
|
|
$createdAt = $item['created_at'];
|
|
|
|
|
|
// Если created_at уже в ISO формате (содержит 'T'), используем как есть
|
|
|
|
|
|
if (strpos($createdAt, 'T') !== false) {
|
|
|
|
|
|
// Уже в ISO формате (например, "2025-11-14T06:21:55.207Z"), используем как есть
|
|
|
|
|
|
$timestamp = $createdAt;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Если в другом формате, преобразуем в ISO
|
|
|
|
|
|
$parsedTime = strtotime($createdAt);
|
|
|
|
|
|
if ($parsedTime !== false) {
|
|
|
|
|
|
$timestamp = date('c', $parsedTime); // ISO 8601 формат
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Если не удалось распарсить, используем текущее время
|
|
|
|
|
|
error_log("Chat History: Failed to parse created_at: {$createdAt}, using current time");
|
|
|
|
|
|
$timestamp = date('c');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Если нет created_at, используем текущее время в ISO формате
|
|
|
|
|
|
$timestamp = date('c'); // ISO 8601 формат
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 10:43:05 +03:00
|
|
|
|
$message = [
|
|
|
|
|
|
'type' => isset($item['sender_type']) && $item['sender_type'] === 'user' ? 'user' : 'assistant',
|
|
|
|
|
|
'message' => $item['content'] ?? '',
|
2025-11-22 09:38:38 +03:00
|
|
|
|
'timestamp' => $timestamp,
|
2025-09-26 10:43:05 +03:00
|
|
|
|
'id' => $item['id'] ?? '',
|
|
|
|
|
|
'dialog_id' => $item['dialog_id'] ?? ''
|
|
|
|
|
|
];
|
|
|
|
|
|
$history[] = $message;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Если история пустая, добавляем приветственное сообщение
|
|
|
|
|
|
if (empty($history)) {
|
|
|
|
|
|
$projectName = $context['projectName'] ?? 'проектом';
|
|
|
|
|
|
$history[] = [
|
|
|
|
|
|
'type' => 'assistant',
|
|
|
|
|
|
'message' => "Привет! Я ваш AI ассистент. Работаем с '{$projectName}'. Чем могу помочь?",
|
2025-11-22 09:38:38 +03:00
|
|
|
|
'timestamp' => date('c'), // ISO 8601 формат
|
2025-09-26 10:43:05 +03:00
|
|
|
|
'id' => 'welcome-' . time(),
|
|
|
|
|
|
'dialog_id' => 'new-dialog'
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Возврат истории
|
|
|
|
|
|
echo json_encode([
|
|
|
|
|
|
'success' => true,
|
|
|
|
|
|
'history' => $history,
|
|
|
|
|
|
'count' => count($history),
|
|
|
|
|
|
'sessionId' => $sessionId,
|
|
|
|
|
|
'context' => $context,
|
|
|
|
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
|
|
|
|
'source' => 'n8n'
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
error_log("Chat History Error: " . $e->getMessage());
|
|
|
|
|
|
|
|
|
|
|
|
// В случае ошибки возвращаем пустую историю
|
|
|
|
|
|
echo json_encode([
|
|
|
|
|
|
'success' => false,
|
|
|
|
|
|
'history' => [],
|
|
|
|
|
|
'error' => $e->getMessage(),
|
|
|
|
|
|
'fallback' => true
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
?>
|