$model,
'messages' => [
['role' => 'system', 'content' => 'You are a professional journalist writing concise English real-estate news.'],
['role' => 'user', 'content' => $prompt]
],
'temperature' => 0.7,
'max_tokens' => 800
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_TIMEOUT => 30,
]);
$resp = curl_exec($ch);
$err = curl_error($ch);
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($err) return ['error' => "cURL error: $err"];
if ($code >= 400) {
return ['error' => "OpenAI API returned HTTP $code", 'body' => $resp];
}
$d = json_decode($resp, true);
if (!$d) return ['error' => 'Invalid JSON from OpenAI', 'body' => $resp];
return ['ok' => $d];
}
// -------------------- API endpoint (AJAX) --------------------
if (isset($_GET['action']) && $_GET['action'] === 'generate' && $_SERVER['REQUEST_METHOD'] === 'POST') {
// optional simple auth: you can require a secret token from JS if desired
// $client_token = $_POST['t'] ?? '';
// if ($client_token !== 'SOME_SHORT_TOKEN') send_json(['error'=>'unauth'],401);
// cache file based on fixed key (single page). For per-prompt cache you can hash prompt.
$cacheFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'ai_re_news_cache.json';
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $CACHE_SECONDS)) {
$cached = @file_get_contents($cacheFile);
if ($cached !== false) {
send_json(['ok' => true, 'from_cache' => true, 'data' => json_decode($cached, true)]);
}
}
// build prompt
$prompt = <<
false, 'error' => $res['error'], 'raw' => $res['body'] ?? null], 502);
}
$content = $res['ok'];
// locate message text
$text = $content['choices'][0]['message']['content'] ?? ($content['choices'][0]['text'] ?? '');
if (!$text) {
send_json(['ok' => false, 'error' => 'No content from OpenAI', 'raw' => $content], 502);
}
// split into articles by blank lines
$parts = preg_split("/\n\s*\n+/", trim($text));
$articles = [];
foreach ($parts as $p) {
$lines = array_values(array_filter(array_map('trim', preg_split("/\r\n|\n|\r/", $p))));
if (count($lines) === 0) continue;
$headline = $lines[0];
$subtitle = $lines[1] ?? '';
$body = implode(' ', array_slice($lines, 2));
if (!$body) {
// maybe the message used the headline as "Headline: ...", try heuristic split by dot
$body = implode(' ', array_slice($lines, 1));
}
$articles[] = ['headline' => $headline, 'subtitle' => $subtitle, 'body' => $body];
}
// store cache (ignore write errors)
@file_put_contents($cacheFile, json_encode($articles, JSON_UNESCAPED_UNICODE));
send_json(['ok' => true, 'from_cache' => false, 'data' => $articles]);
}
// -------------------- Otherwise: serve the HTML page --------------------
?>
AI-Generated Global Real Estate News (Secure)
🏙️ AI-Generated Global Real Estate News
Press “Generate 5 AI Articles” to create a fresh set of English real estate news (server-side; your API key is NOT exposed).