192 lines
5.8 KiB
PHP
192 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\BackgroundMedia;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
|
|
class AdminBackgroundGenerationController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
// Load a random record with status 'pending_media'
|
|
$pendingMedia = BackgroundMedia::where('status', 'pending_media')
|
|
->whereIn('list_type', ['residential', 'commercial'])
|
|
->inRandomOrder()
|
|
->first();
|
|
|
|
return Inertia::render('admin/background-gen', [
|
|
'pendingMedia' => $pendingMedia,
|
|
]);
|
|
}
|
|
|
|
public function generate(Request $request)
|
|
{
|
|
$request->validate([
|
|
'prompt' => 'required|string|max:1000',
|
|
'media_id' => 'required|exists:background_medias,id',
|
|
]);
|
|
|
|
$prompt = $request->input('prompt');
|
|
|
|
// Call Replicate API
|
|
$replicateResponse = $this->callReplicateAPI($prompt);
|
|
|
|
if (! $replicateResponse || ! isset($replicateResponse['urls']['get'])) {
|
|
return response()->json(['error' => 'Failed to start generation'], 500);
|
|
}
|
|
|
|
// Poll for result
|
|
$result = $this->pollReplicateResult($replicateResponse['urls']['get']);
|
|
|
|
if (! $result || ! isset($result['output'][0])) {
|
|
return response()->json(['error' => 'Generation failed or timed out'], 500);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'image_url' => $result['output'][0],
|
|
]);
|
|
}
|
|
|
|
public function delete($id)
|
|
{
|
|
try {
|
|
$media = BackgroundMedia::where('id', $id)
|
|
->where('status', 'pending_media')
|
|
->first();
|
|
|
|
if (! $media) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => 'Pending media not found or already processed',
|
|
], 404);
|
|
}
|
|
|
|
$media->delete();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Media deleted successfully',
|
|
]);
|
|
} catch (\Exception $e) {
|
|
\Log::error('Error deleting pending media: '.$e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => 'An error occurred while deleting the media',
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function save(Request $request)
|
|
{
|
|
$request->validate([
|
|
'media_id' => 'required|exists:background_medias,id',
|
|
'image_url' => 'required|url',
|
|
'prompt' => 'required|string',
|
|
]);
|
|
|
|
$backgroundMedia = BackgroundMedia::findOrFail($request->input('media_id'));
|
|
|
|
// try {
|
|
// Use MediaEngine to download and store the image
|
|
$media = \App\Helpers\FirstParty\MediaEngine\MediaEngine::addMedia(
|
|
'system-i',
|
|
'image',
|
|
'system_uploaded',
|
|
'replicate',
|
|
null,
|
|
$request->input('image_url'),
|
|
'download'
|
|
);
|
|
|
|
// Update the background media record
|
|
$backgroundMedia->update([
|
|
'status' => 'completed',
|
|
'media_uuid' => $media->uuid,
|
|
'media_url' => \App\Helpers\FirstParty\MediaEngine\MediaEngine::getMediaCloudUrl($media),
|
|
'prompt' => $request->input('prompt'),
|
|
]);
|
|
|
|
return response()->json(['success' => true]);
|
|
// } catch (\Exception $e) {
|
|
// return response()->json(['error' => 'Failed to save media: ' . $e->getMessage()], 500);
|
|
// }
|
|
}
|
|
|
|
private function callReplicateAPI($prompt)
|
|
{
|
|
$apiToken = config('services.replicate.api_token');
|
|
|
|
$data = [
|
|
'input' => [
|
|
'prompt' => $prompt,
|
|
'go_fast' => true,
|
|
'megapixels' => '1',
|
|
'num_outputs' => 1,
|
|
'aspect_ratio' => '1:1',
|
|
'output_format' => 'webp',
|
|
'output_quality' => 80,
|
|
'num_inference_steps' => 4,
|
|
],
|
|
];
|
|
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, 'https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions');
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
'Authorization: Bearer '.$apiToken,
|
|
'Content-Type: application/json',
|
|
'Prefer: wait',
|
|
]);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode !== 201) {
|
|
return false;
|
|
}
|
|
|
|
return json_decode($response, true);
|
|
}
|
|
|
|
private function pollReplicateResult($getUrl)
|
|
{
|
|
$maxAttempts = 30; // 5 minutes max (30 * 10 seconds)
|
|
$attempt = 0;
|
|
|
|
while ($attempt < $maxAttempts) {
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $getUrl);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
'Authorization: Bearer '.config('services.replicate.api_token'),
|
|
]);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode === 200) {
|
|
$result = json_decode($response, true);
|
|
|
|
if ($result['status'] === 'succeeded' && isset($result['output'][0])) {
|
|
return $result;
|
|
} elseif ($result['status'] === 'failed') {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$attempt++;
|
|
sleep(3); // Wait 10 seconds before next poll
|
|
}
|
|
|
|
return false; // Timeout
|
|
}
|
|
}
|