<?php
// ai_categorize.php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// Handle preflight requests
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
exit(0);
}
// Configuration
// อ่านค่า API key จาก environment variable เพื่อความปลอดภัย
$GOOGLE_AI_API_KEY = getenv('GOOGLE_AI_API_KEY') ?: 'GOOGLE_AI_API_KEY'; // แทนที่ด้วย API Key ของคุณ หรือตั้ง environment variable
$GOOGLE_AI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';
// Simple logger to file for debugging (make sure webserver can write to this path)
/**
* @param $msg
*/
function ai_log($msg)
{
$logfile = '/tmp/ai_categorize.log';
$time = date('Y-m-d H:i:s');
@file_put_contents($logfile, "[$time] ".$msg.PHP_EOL, FILE_APPEND | LOCK_EX);
}
try {
// Check if request method is POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'error' => 'Only POST allowed']);
exit;
}
// Get JSON input
$json = file_get_contents('php://input');
ai_log('Incoming request body: '.substr($json, 0, 2000));
$data = json_decode($json, true);
if (!$data || !isset($data['prompt'])) {
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'Invalid JSON data or missing prompt']);
exit;
}
$prompt = $data['prompt'];
// Prepare data for Google AI Studio API
$postData = [
'contents' => [
[
'parts' => [
[
'text' => $prompt.' Please respond with valid JSON format only, no additional text.'
]
]
]
],
'generationConfig' => [
'temperature' => 0.1,
'topK' => 1,
'topP' => 1,
'maxOutputTokens' => 1024,
'stopSequences' => []
],
'safetySettings' => [
[
'category' => 'HARM_CATEGORY_HARASSMENT',
'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
],
[
'category' => 'HARM_CATEGORY_HATE_SPEECH',
'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
],
[
'category' => 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
],
[
'category' => 'HARM_CATEGORY_DANGEROUS_CONTENT',
'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
]
]
];
// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $GOOGLE_AI_API_URL.'?key='.$GOOGLE_AI_API_KEY);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// Execute request
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErrno = curl_errno($ch);
$curlError = curl_error($ch);
$curlInfo = curl_getinfo($ch);
curl_close($ch);
if ($curlErrno) {
ai_log('cURL error: '.$curlError.' (errno '.$curlErrno.')');
http_response_code(502);
echo json_encode(['success' => false, 'error' => 'cURL error communicating with AI service', 'details' => $curlError]);
exit;
}
ai_log('AI API HTTP code: '.$httpCode.' response snippet: '.substr($response, 0, 2000));
if ($httpCode !== 200) {
ai_log('Upstream API returned HTTP '.$httpCode.'. Raw response: '.substr($response, 0, 2000));
http_response_code(502);
echo json_encode(['success' => false, 'error' => 'Upstream API error', 'http_code' => $httpCode, 'raw_response' => $response]);
exit;
}
// Decode upstream JSON
$responseData = json_decode($response, true);
if (!$responseData) {
ai_log('Failed to json_decode API response');
http_response_code(502);
echo json_encode(['success' => false, 'error' => 'Invalid JSON from AI service', 'raw_response' => $response]);
exit;
}
// Try known response shapes (keep flexible)
$generatedText = null;
if (isset($responseData['candidates'][0]['content']['parts'][0]['text'])) {
$generatedText = $responseData['candidates'][0]['content']['parts'][0]['text'];
} elseif (isset($responseData['output'][0]['content'][0]['text'])) {
$generatedText = $responseData['output'][0]['content'][0]['text'];
} elseif (isset($responseData['result'])) {
// some responses might embed text differently
$generatedText = is_string($responseData['result']) ? $responseData['result'] : json_encode($responseData['result']);
}
if (!$generatedText) {
ai_log('Unexpected API response shape: '.substr(json_encode($responseData), 0, 2000));
http_response_code(502);
echo json_encode(['success' => false, 'error' => 'Unexpected API response format', 'raw_response' => $response]);
exit;
}
// Clean up the response - remove markdown code blocks if present
$generatedText = preg_replace('/```json\s*/', '', $generatedText);
$generatedText = preg_replace('/```\s*$/', '', $generatedText);
$generatedText = trim($generatedText);
// Parse the JSON response from AI
$categories = json_decode($generatedText, true);
if (!$categories) {
// If JSON parsing fails, try to extract JSON object/array from the response
preg_match('/\{[\s\S]*\}/', $generatedText, $matches);
if ($matches) {
$categories = json_decode($matches[0], true);
}
}
if (!$categories) {
ai_log('Failed to parse AI JSON. Generated text: '.substr($generatedText, 0, 2000));
http_response_code(502);
echo json_encode(['success' => false, 'error' => 'Failed to parse AI response as JSON', 'raw_response' => $generatedText]);
exit;
}
// Return successful response
echo json_encode([
'success' => true,
'categories' => $categories,
'raw_response' => $generatedText
]);
} catch (Exception $e) {
// Return error response
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage()
]);
}