| <?php |
|
|
| namespace App\Services; |
|
|
| use Illuminate\Support\Str; |
|
|
| class SocialContentGeneratorService |
| { |
| public function __construct(private OpenAiChatService $openAiChatService) |
| { |
| } |
|
|
| public function generate(string $topic, string $platformHint = 'multi-platform', string $tone = 'friendly-professional'): array |
| { |
| $messages = [ |
| [ |
| 'role' => 'system', |
| 'content' => 'Kamu adalah social media strategist. Selalu jawab valid JSON tanpa markdown dengan schema: {"title":"...","caption":"...","hashtags":["..."],"cta":"..."}. Gunakan Bahasa Indonesia.', |
| ], |
| [ |
| 'role' => 'user', |
| 'content' => "Buat konten untuk {$platformHint}. Tone: {$tone}. Topik: {$topic}. Caption maksimal 480 karakter. Hashtag 6-10 item relevan tanpa spasi.", |
| ], |
| ]; |
|
|
| $raw = $this->openAiChatService->reply($messages); |
| $clean = trim($raw); |
|
|
| if (str_starts_with($clean, '```')) { |
| $clean = preg_replace('/^```(?:json)?\s*|\s*```$/m', '', $clean) ?? $clean; |
| $clean = trim($clean); |
| } |
|
|
| $decoded = json_decode($clean, true); |
| if (! is_array($decoded)) { |
| $decoded = json_decode($this->extractJsonObject($clean) ?? '', true); |
| } |
|
|
| if (! is_array($decoded)) { |
| return [ |
| 'title' => Str::limit($topic, 80), |
| 'caption' => Str::limit($raw !== '' ? $raw : $topic, 500), |
| 'hashtags' => ['#konten', '#bisnis', '#digitalmarketing'], |
| 'cta' => 'Follow untuk konten berikutnya.', |
| 'raw' => $raw, |
| ]; |
| } |
|
|
| $hashtags = collect($decoded['hashtags'] ?? []) |
| ->map(fn ($item) => trim((string) $item)) |
| ->filter() |
| ->take(10) |
| ->map(fn ($item) => str_starts_with($item, '#') ? $item : '#'.$item) |
| ->unique() |
| ->values() |
| ->all(); |
|
|
| $caption = trim((string) ($decoded['caption'] ?? '')); |
| if ($caption === '') { |
| $caption = Str::limit($raw !== '' ? $raw : $topic, 500); |
| } |
|
|
| return [ |
| 'title' => trim((string) ($decoded['title'] ?? Str::limit($topic, 80))), |
| 'caption' => $caption, |
| 'hashtags' => $hashtags, |
| 'cta' => trim((string) ($decoded['cta'] ?? 'Follow untuk konten berikutnya.')), |
| 'raw' => $raw, |
| ]; |
| } |
|
|
| private function extractJsonObject(string $content): ?string |
| { |
| $start = strpos($content, '{'); |
| $end = strrpos($content, '}'); |
|
|
| if ($start === false || $end === false || $end <= $start) { |
| return null; |
| } |
|
|
| return substr($content, $start, $end - $start + 1); |
| } |
| } |
|
|