platform) { 'facebook' => $this->publishFacebook($post, $credential), 'instagram' => $this->publishInstagram($post, $credential), 'x' => $this->publishX($post, $credential), 'tiktok' => $this->publishTikTok($post, $credential), default => throw new RuntimeException('Platform tidak dikenali: '.$post->platform), }; } private function publishFacebook(SocialPost $post, SocialPlatformCredential $credential): array { $pageId = trim((string) $credential->account_id); $token = trim((string) $credential->access_token); if ($pageId === '' || $token === '') { throw new RuntimeException('Facebook butuh PAGE_ID dan PAGE_ACCESS_TOKEN.'); } $payload = [ 'message' => $post->fullCaption(), 'access_token' => $token, ]; if (! empty($post->image_url)) { $payload['link'] = $post->image_url; } $response = Http::asForm() ->timeout(45) ->post("https://graph.facebook.com/v22.0/{$pageId}/feed", $payload); if (! $response->successful()) { $message = data_get($response->json(), 'error.message', $response->body()); throw new RuntimeException('Facebook publish gagal: '.$response->status().' - '.$message); } return [ 'external_post_id' => (string) data_get($response->json(), 'id', ''), 'payload' => $response->json(), ]; } private function publishInstagram(SocialPost $post, SocialPlatformCredential $credential): array { $igAccountId = trim((string) $credential->account_id); $token = trim((string) $credential->access_token); if ($igAccountId === '' || $token === '') { throw new RuntimeException('Instagram butuh IG_BUSINESS_ACCOUNT_ID dan ACCESS_TOKEN.'); } if (empty($post->image_url)) { throw new RuntimeException('Instagram saat ini butuh image_url publik. Isi URL gambar dulu.'); } $createContainer = Http::asForm() ->timeout(60) ->post("https://graph.facebook.com/v22.0/{$igAccountId}/media", [ 'image_url' => $post->image_url, 'caption' => $post->fullCaption(), 'access_token' => $token, ]); if (! $createContainer->successful()) { $message = data_get($createContainer->json(), 'error.message', $createContainer->body()); throw new RuntimeException('Instagram create media gagal: '.$createContainer->status().' - '.$message); } $creationId = (string) data_get($createContainer->json(), 'id'); if ($creationId === '') { throw new RuntimeException('Instagram creation_id kosong.'); } $publish = Http::asForm() ->timeout(60) ->post("https://graph.facebook.com/v22.0/{$igAccountId}/media_publish", [ 'creation_id' => $creationId, 'access_token' => $token, ]); if (! $publish->successful()) { $message = data_get($publish->json(), 'error.message', $publish->body()); throw new RuntimeException('Instagram media_publish gagal: '.$publish->status().' - '.$message); } return [ 'external_post_id' => (string) data_get($publish->json(), 'id', ''), 'payload' => [ 'creation' => $createContainer->json(), 'publish' => $publish->json(), ], ]; } private function publishX(SocialPost $post, SocialPlatformCredential $credential): array { $token = trim((string) $credential->access_token); if ($token === '') { throw new RuntimeException('X/Twitter butuh ACCESS_TOKEN OAuth2 user context (scope tweet.write).'); } $response = Http::timeout(45) ->withToken($token) ->acceptJson() ->post('https://api.x.com/2/tweets', [ 'text' => $post->fullCaption(), ]); if (! $response->successful()) { $message = data_get($response->json(), 'detail', $response->body()); throw new RuntimeException('X publish gagal: '.$response->status().' - '.$message); } return [ 'external_post_id' => (string) data_get($response->json(), 'data.id', ''), 'payload' => $response->json(), ]; } private function publishTikTok(SocialPost $post, SocialPlatformCredential $credential): array { $token = trim((string) $credential->access_token); if ($token === '') { throw new RuntimeException('TikTok butuh OAuth access token user (scope video.publish).'); } if (empty($post->video_url)) { throw new RuntimeException('TikTok butuh video_url publik. Isi URL video pada form post.'); } $title = trim((string) ($post->title ?: 'Konten terbaru')); if ($title === '') { $title = 'Konten terbaru'; } $response = Http::timeout(90) ->withToken($token) ->acceptJson() ->post('https://open.tiktokapis.com/v2/post/publish/video/init/', [ 'post_info' => [ 'title' => mb_substr($title, 0, 90), 'privacy_level' => 'SELF_ONLY', 'disable_duet' => false, 'disable_comment' => false, 'disable_stitch' => false, ], 'source_info' => [ 'source' => 'PULL_FROM_URL', 'video_url' => $post->video_url, ], ]); if (! $response->successful()) { $message = data_get($response->json(), 'error.message', $response->body()); throw new RuntimeException('TikTok init publish gagal: '.$response->status().' - '.$message); } return [ 'external_post_id' => (string) data_get($response->json(), 'data.publish_id', ''), 'payload' => $response->json(), ]; } }