-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgenerate.php
More file actions
279 lines (244 loc) · 9.04 KB
/
Copy pathgenerate.php
File metadata and controls
279 lines (244 loc) · 9.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
<?php
// generate.php
if (file_exists('config.php')) {
$config = include('config.php');
} else {
$config['api_key_open_ai'] = null;
}
// Retrieve the API key and AI provider from the config file
$IA_USED = $config['ia_used'];
$API_KEY = $IA_USED === 'gemini' ? $config['api_key_gemini'] : $config['api_key_open_ai'];
// Adjust the model based on the provider
if($IA_USED === 'gemini'){
$GEM_MODEL = ($config['gemini_model'] != null) ? $config['gemini_model'] : 'gemini-1.5-flash-latest';
$MODEL = $GEM_MODEL != null ? $GEM_MODEL : 'gemini-1.5-flash-latest';
} else {
$MODEL = 'gpt-4o-mini';
}
$buildsDir = __DIR__ . '/builds'; // Directory where generated files are stored
// If the API key is not defined, fallback to serving a random build
if (empty($API_KEY)) {
serveRandomBuild($buildsDir);
exit;
}
// Read the data from the request body
$data = json_decode(file_get_contents('php://input'), true);
$description = $data['description'] ?? '';
if (empty($description)) {
respondWithError('No description provided');
exit;
}
// Increment a build number
$buildNumber = incrementBuildCount('build_count.txt');
// Create a prompt to generate a complete HTML file with inline CSS and JS
$prompt = buildPrompt($description);
// Send the prompt to the selected API and get a response
$generatedFiles = getGeneratedFiles($prompt, $API_KEY, $MODEL, $IA_USED);
if (!$generatedFiles) {
respondWithError('Invalid format received from generated files');
exit;
}
// Check if the builds directory exists, otherwise create it
if (!is_dir($buildsDir)) {
mkdir($buildsDir, 0775, true); // Create the directory with 775 permissions
}
// Write the generated files to disk and get their links
$fileLinks = saveGeneratedFiles($generatedFiles, $buildNumber, $buildsDir);
if (empty($fileLinks)) {
respondWithError('Failed to write generated files');
exit;
}
// Return the links of the generated files in JSON format
echo json_encode(['links' => $fileLinks]);
/**
* Sends the prompt to the selected API and retrieves the generated files.
*
* @param string $prompt The prompt to send to the API.
* @param string $API_KEY The API key for authentication.
* @param string $MODEL The model to use for generation.
* @param string $IA_USED The AI provider to use ('openai' or 'gemini').
* @return array|null The generated files or null in case of error.
*/
function getGeneratedFiles($prompt, $API_KEY, $MODEL, $IA_USED) {
if ($IA_USED === 'gemini') {
// Configuration for the Gemini API
$apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/$MODEL:generateContent?key=$API_KEY";
$params = [
'temperature' => 0.7,
'maxTokens' => 300
];
$data = [
"contents" => [
[
"role" => "user",
"parts" => [
[
"text" => $prompt
]
]
]
]
];
$postData = json_encode($data);
} elseif ($IA_USED === 'openai') {
// Configuration for the OpenAI API
$apiUrl = 'https://api.openai.com/v1/chat/completions';
$postData = json_encode([
'model' => $MODEL,
'messages' => [['role' => 'user', 'content' => $prompt]],
'max_tokens' => 10000,
]);
} else {
// Unsupported AI provider
return null;
}
// Initialize cURL
$ch = curl_init($apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
$IA_USED === 'gemini' ? '' : 'Authorization: Bearer ' . $API_KEY,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
// Execute the request
$response = curl_exec($ch);
if (curl_errno($ch)) {
// Handle cURL errors
logError('cURL Error: ' . curl_error($ch));
curl_close($ch);
return null;
}
curl_close($ch);
// Decode the JSON response
if ($IA_USED === 'gemini') {
$response = json_decode($response, true);
// Process the Gemini API response
if (isset($response['candidates'][0]['content']['parts'][0]['text'])) {
// Extract raw content
$rawContent = $response['candidates'][0]['content']['parts'][0]['text'];
// Clean to retrieve JSON encapsulated in text
$cleanedText = str_replace(['```json', '```'], '', $rawContent);
$cleanedContent = trim($cleanedText);
// Decode the JSON to obtain files
$decodedContent = json_decode($cleanedContent, true);
if ($decodedContent && isset($decodedContent['files'][0]['content'])) {
// Process the generated files
return $decodedContent; // Display the extracted files
} else {
// Display an error if the JSON is invalid
echo "Error: Unable to decode cleaned JSON content.";
dd($cleanedContent, false); // Verify the content in case of failure
}
}
} elseif ($IA_USED === 'openai') {
$response = json_decode($response, true);
// Process the OpenAI API response
if (isset($response['choices'][0]['message']['content'])) {
$cleanedResponse = trim($response['choices'][0]['message']['content'], "```json");
$cleanedResponse = trim($cleanedResponse, "```");
return json_decode($cleanedResponse, true);
}
}
// In case of unexpected response format
logError('Unexpected response format', $response);
return null;
}
/**
* Serves a random HTML file from the builds directory if available.
*/
function serveRandomBuild($buildsDir) {
if (is_dir($buildsDir)) {
$files = glob($buildsDir . '/*.html');
if ($files && count($files) > 0) {
$randomFile = $files[array_rand($files)];
$fileLink = '/builds/' . basename($randomFile);
echo json_encode(['links' => [$fileLink]]);
} else {
respondWithError('No builds available.');
}
} else {
respondWithError('Builds directory not found.');
}
}
/**
* Increments the build count stored in a file.
*/
function incrementBuildCount($filePath) {
if (!file_exists($filePath)) {
file_put_contents($filePath, 0);
}
$buildNumber = intval(file_get_contents($filePath)) + 1;
file_put_contents($filePath, $buildNumber);
return $buildNumber;
}
/**
* Builds the prompt to be sent to OpenAI's API.
*/
function buildPrompt($description) {
return "You are a professional web developer. Your task is to generate a complete and valid HTML document based on the following user description: " . $description . ".\n" .
"Please structure the HTML file as follows:\n" .
"- Include a <style> tag inside the <head> section for any required CSS styles.\n" .
"- Include a <script> tag just before the closing </body> tag for any necessary JavaScript functionality.\n" .
"The HTML file should be clean, responsive, and follow best practices in modern web development.\n\n" .
"Return the result in a JSON format with the following structure:\n" .
"```json\n" .
"{\n" .
' "files": [\n' .
' {\n' .
' "file_title": "index.html",\n' .
' "content": "<HTML content>"\n' .
" }\n" .
" ]\n" .
"}\n" .
"```\nMake sure that the 'content' field contains the complete HTML, CSS, and JS all in a single HTML file.";
}
/**
* Saves the generated files to disk and returns their links.
*/
function saveGeneratedFiles($generatedFiles, $buildNumber, $buildsDir) {
$fileLinks = [];
if (!isset($generatedFiles['files'])) {
logError('Invalid format received from the API', $generatedFiles);
return [];
}
foreach ($generatedFiles['files'] as $file) {
$filename = $buildsDir . "/build_$buildNumber" . '_' . $file['file_title'];
$result = file_put_contents($filename, $file['content']);
if ($result === false) {
logError('Failed to write file', ['filename' => $filename]);
return [];
}
$fileLinks[] = "/builds/build_$buildNumber" . '_' . $file['file_title'];
}
return $fileLinks;
}
/**
* Logs errors to a file for debugging purposes.
*/
function logError($message, $context = []) {
$logEntry = [
'error' => $message,
'context' => $context,
'timestamp' => date('Y-m-d H:i:s')
];
file_put_contents('error_log.txt', json_encode($logEntry) . "\n", FILE_APPEND);
}
/**
* Sends an error response in JSON format.
*/
function respondWithError($errorMessage) {
echo json_encode(['error' => $errorMessage]);
}
/**
* Debugging function to dump and optionally terminate the script.
*/
function dd($data, $die = true) {
echo '<pre>';
var_dump($data);
echo '</pre>';
if ($die){
die();
}
}
?>