This commit is contained in:
ct
2025-07-04 12:53:08 +08:00
parent 81c38dd9e3
commit b5ac848ba2
6 changed files with 298 additions and 32 deletions

View File

@@ -3,10 +3,12 @@
namespace App\Http\Controllers;
use App\Helpers\FirstParty\Credits\CreditsService;
use App\Helpers\FirstParty\Meme\MemeGenerator;
use App\Jobs\GenerateMemeJob;
use Illuminate\Http\Request;
use App\Models\Category;
use Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class UserAIController extends Controller
{
@@ -14,7 +16,6 @@ public function generateMeme(Request $request)
{
$user = Auth::user();
if (!CreditsService::canSpend($user->id, 2)) {
return response()->json([
'error' => [
@@ -25,24 +26,69 @@ public function generateMeme(Request $request)
CreditsService::spend($user->id, 2);
$meme = MemeGenerator::generateMemeByKeyword($request->prompt);
$meme_media = MemeGenerator::getSuitableMemeMedia($meme, 2);
$jobId = Str::uuid()->toString();
Cache::put("meme_job_status_{$jobId}", 'pending', 300);
$job = new GenerateMemeJob($user->id, $request->prompt, $jobId);
dispatch($job);
return response()->json([
'success' => [
'data' => [
'generate' => [
'info' => $meme,
'caption' => $meme->caption,
'meme' => $meme_media,
'background' => $meme->background_media,
],
'job_id' => $jobId,
'status' => 'pending',
],
],
]);
}
public function checkMemeJobStatus(Request $request)
{
$jobId = $request->job_id;
if (!$jobId) {
return response()->json([
'error' => [
'message' => 'Job ID is required.',
],
], 400);
}
$status = Cache::get("meme_job_status_{$jobId}");
if (!$status) {
return response()->json([
'error' => [
'message' => 'Job not found or expired.',
],
], 404);
}
$response = [
'success' => [
'data' => [
'job_id' => $jobId,
'status' => $status,
],
],
];
if ($status === 'completed') {
$result = Cache::get("meme_job_result_{$jobId}");
if ($result) {
$response['success']['data']['result'] = $result;
}
} elseif ($status === 'failed') {
$error = Cache::get("meme_job_error_{$jobId}");
if ($error) {
$response['success']['data']['error'] = $error;
}
}
return response()->json($response);
}
public function aiHints()
{
$categories = Category::whereNotNull('keywords')

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Jobs;
use App\Helpers\FirstParty\Meme\MemeGenerator;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class GenerateMemeJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 30;
public $tries = 1;
protected $userId;
protected $prompt;
protected $jobId;
public function __construct(int $userId, string $prompt, string $jobId = null)
{
$this->userId = $userId;
$this->prompt = $prompt;
$this->jobId = $jobId ?: Str::uuid()->toString();
$this->queue = 'ai';
}
public function handle(): void
{
try {
Cache::put("meme_job_status_{$this->jobId}", 'processing', 300);
$meme = MemeGenerator::generateMemeByKeyword($this->prompt);
$meme_media = MemeGenerator::getSuitableMemeMedia($meme, 2);
$result = [
'generate' => [
'info' => $meme,
'caption' => $meme->caption,
'meme' => $meme_media,
'background' => $meme->background_media,
],
];
Cache::put("meme_job_result_{$this->jobId}", $result, 300);
Cache::put("meme_job_status_{$this->jobId}", 'completed', 300);
} catch (\Exception $e) {
Cache::put("meme_job_status_{$this->jobId}", 'failed', 300);
Cache::put("meme_job_error_{$this->jobId}", $e->getMessage(), 300);
throw $e;
}
}
public function getJobId(): string
{
return $this->jobId;
}
}