Fix: AI Blog Assistant retry logic and Subdomain routing for Akademi

This commit is contained in:
Muhammet Güler
2026-02-16 14:55:06 +03:00
parent 0fa8e4e435
commit 7101f7878a
10 changed files with 458 additions and 1 deletions
@@ -0,0 +1,118 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\BlogTopic;
use App\Models\Blog; // Ensure this model exists and has 'status' column
use App\Models\User;
use App\Services\AiBlogService;
use Illuminate\Support\Str;
use Carbon\Carbon;
class GenerateBlogAssistant extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'blog:generate-assistant {--topic= : Specific topic to generate}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate a new AI blog post draft based on active topics.';
/**
* Execute the console command.
*/
public function handle(AiBlogService $aiService)
{
\Illuminate\Support\Facades\Log::info('GenerateBlogAssistant triggered. Args: ' . json_encode($_SERVER['argv'] ?? []));
$this->info('Starting AI Blog Assistant...');
// 1. Select Topic
$topicName = $this->option('topic');
$topic = null;
if ($topicName) {
$topic = BlogTopic::where('name', $topicName)->first();
if (!$topic) {
$this->error("Topic '{$topicName}' not found.");
return 1;
}
} else {
// Find oldest used active topic
$topic = BlogTopic::active()
->orderBy('last_used_at', 'asc') // Nulls first usually, or old dates
->first();
}
if (!$topic) {
$this->warn('No active topics found. Please add topics to blog_topics table.');
return 0;
}
$this->info("Selected Topic: {$topic->name}");
// 2. Generate Content
$this->info('Generating content with Gemini API...');
try {
$contentData = $aiService->generateContent($topic->name, $topic->context);
} catch (\Exception $e) {
$this->error('Content generation failed: ' . $e->getMessage());
return 1;
}
if (empty($contentData) || !isset($contentData['title']) || !isset($contentData['content'])) {
$this->error('Valid content not returned from AI Service.');
return 1;
}
$this->info('Content generated successfully.');
// 3. Generate/Fetch Image
$this->info('Fetching cover image...');
$imagePath = null;
if (isset($contentData['image_prompt'])) {
$imagePath = $aiService->fetchAndSaveImage($topic->name, $contentData['image_title'] ?? $contentData['image_prompt']); // Pollinations uses prompt
}
if (!$imagePath) {
$this->warn('Could not fetch image, proceeding without cover image.');
} else {
$this->info("Image saved to: {$imagePath}");
}
// 4. Create Draft Blog Post
$author = User::first(); // Default to first user (Admin)
$blog = new Blog();
$blog->title = $contentData['title'];
$blog->slug = Str::slug($contentData['title']);
$blog->content = $contentData['content'];
$blog->excerpt = $contentData['excerpt'] ?? Str::limit(strip_tags($contentData['content']), 150);
$blog->meta_title = $contentData['meta_title'] ?? $contentData['title'];
$blog->meta_description = $contentData['meta_description'] ?? $blog->excerpt;
$blog->status = 'draft'; // Verification required
$blog->author_id = $author ? $author->id : 1;
$blog->featured_image = $imagePath;
$blog->published_at = null; // Draft
$blog->tags = $contentData['tags'] ?? [];
// category_id? We might need to guess or default.
// For now leave null or set default if exists.
$blog->save();
// 5. Update Topic Usage
$topic->last_used_at = Carbon::now();
$topic->save();
$this->info("Blog post '{$blog->title}' created as DRAFT (ID: {$blog->id}).");
return 0;
}
}