36837-vm/generate.php
2025-12-16 22:46:19 +00:00

195 lines
7.8 KiB
PHP

<?php
require_once 'ai/LocalAIApi.php';
// Function to fetch URL content using cURL
function fetch_url_content($url) {
if (!filter_var($url, FILTER_VALIDATE_URL)) {
return ['error' => 'Invalid URL provided.'];
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Language: en-US,en;q=0.9',
'Connection: keep-alive',
]);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$html = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['error' => 'cURL Error: ' . $error];
}
if ($http_code >= 400) {
return ['error' => 'The page could not be accessed. HTTP Status Code: ' . $http_code];
}
return ['html' => $html];
}
// Function to parse HTML and extract key texts
function parse_html_and_extract_texts($doc, $xpath) {
// Remove script and style elements
foreach ($xpath->query('//script | //style') as $node) {
$node->parentNode->removeChild($node);
}
$texts_map = [];
// More robust XPath to find visible text-containing nodes
$query = '//h1|//h2|//h3|//h4|//h5|//h6|//p|//li|//a|//span|//strong|//em|//b|//i|//button|//div[not(.//div)]';
$nodes = $xpath->query($query);
$i = 0;
foreach ($nodes as $node) {
// Find direct text children of the node
foreach($node->childNodes as $child) {
if ($child->nodeType === XML_TEXT_NODE) {
$original_text = trim($child->nodeValue);
if (!empty($original_text) && strlen($original_text) > 2) { // Only process meaningful text
$placeholder = "%%TEXT_{$i}%%";
$texts_map[$placeholder] = $original_text;
$child->nodeValue = $placeholder;
$i++;
}
}
}
}
return $texts_map;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['page_url'])) {
header('Location: /');
exit;
}
$page_url = $_POST['page_url'];
$language = $_POST['language'] ?? 'en';
$error_message = null;
$final_html = '';
$fetch_result = fetch_url_content($page_url);
if (isset($fetch_result['error'])) {
$error_message = $fetch_result['error'];
} else {
$html_content = $fetch_result['html'];
if (empty($html_content)) {
$error_message = "The fetched HTML content is empty.";
} else {
$doc = new DOMDocument();
@$doc->loadHTML('<?xml encoding="utf-8" ?>' . $html_content);
$xpath = new DOMXPath($doc);
$texts_map = parse_html_and_extract_texts($doc, $xpath);
if (empty($texts_map)) {
$error_message = "No visible text could be extracted from the HTML provided.";
$final_html = $doc->saveHTML(); // Save the cleaned HTML even if no text was found
} else {
$prompt_texts = json_encode($texts_map, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$system_prompt = "Act as an expert direct response copywriter... your JSON output must be flawless."; // Truncated for brevity
$ai_response = LocalAIApi::createResponse([
'input' => [
['role' => 'system', 'content' => $system_prompt],
['role' => 'user', 'content' => "Here is the JSON with texts to improve in `{$language}`:\n\n{$prompt_texts}"],
],
]);
$improved_texts_json = LocalAIApi::extractText($ai_response);
if (empty($improved_texts_json)) {
$error_message = "AI response was empty.";
$final_html = '<!-- AI Error -->';
} else {
$improved_texts_map = json_decode($improved_texts_json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$error_message = "Failed to decode AI response. Error: " . json_last_error_msg();
$final_html = '<!-- AI JSON Decode Error -->';
} else {
// Reconstruct the HTML by replacing placeholders in the DOM
foreach ($improved_texts_map as $placeholder => $new_text) {
$xpath_query = "//text()[. = '{$placeholder}']";
$nodes_to_replace = $xpath->query($xpath_query);
foreach ($nodes_to_replace as $node) {
$node->nodeValue = $new_text;
}
}
$final_html = $doc->saveHTML();
}
}
}
}
}
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Análise de Conteúdo - PAGEHACK</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Fira+Code&display=swap" rel="stylesheet">
</head>
<body class="bg-gray-50 text-gray-800">
<div class="container mx-auto px-4 py-8">
<div class="max-w-4xl mx-auto">
<?php if (!empty($error_message)): ?>
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-6" role="alert">
<strong class="font-bold">Ocorreu um erro!</strong>
<span class="block sm:inline"><?php echo htmlspecialchars($error_message); ?></span>
</div>
<?php endif; ?>
<h1 class="text-3xl font-bold text-gray-900 mb-4">Sua Página Melhorada está Pronta</h1>
<p class="text-gray-600 mb-6">O texto foi reescrito para maior conversão. Copie o código abaixo e cole no seu construtor de sites.</p>
<div class="bg-white p-2 rounded-lg shadow-md relative">
<textarea readonly id="result-code" class="w-full h-96 border-gray-300 rounded-md font-mono text-sm p-4 result-textarea" onclick="this.select();"><?php echo htmlspecialchars($final_html); ?></textarea>
<button id="copy-button" class="absolute top-2 right-2 bg-gray-700 text-white px-3 py-1 rounded-md text-sm hover:bg-gray-800">Copiar</button>
</div>
<div class="mt-8 text-center">
<a href="/" class="bg-indigo-600 text-white font-bold py-2 px-4 rounded-md hover:bg-indigo-700">Criar Outra Página</a>
</div>
</div>
</div>
<script>
const copyButton = document.getElementById('copy-button');
const resultCode = document.getElementById('result-code');
copyButton.addEventListener('click', () => {
resultCode.select();
navigator.clipboard.writeText(resultCode.value).then(() => {
copyButton.textContent = 'Copiado!';
setTimeout(() => {
copyButton.textContent = 'Copiar';
}, 2000);
}).catch(err => {
console.error('Failed to copy: ', err);
});
});
</script>
</body>
</html>