feat: enable feed distribution for Reels via /videos endpoint

This commit is contained in:
Michael committed 2026-02-10 11:11:42 +01:00
1 parent a35b9e3d1c
commit 4b5ab1ca16
1 file changed
+16 -72
+16 -72
View File
@@ -519,93 +519,37 @@ export class FacebookService {
throw new Error('No access token found for this page'); throw new Error('No access token found for this page');
} }
const accessToken = page.accessToken; console.log('🎬 Publishing Reel to Facebook Feed & Reels via /videos endpoint:', {
console.log('🎬 Publishing Reel to Facebook:', {
pageId: page.pageId, pageId: page.pageId,
pageName: page.pageName, pageName: page.pageName,
hasDescription: !!description, hasDescription: !!description,
}); });
// Phase 1: START - Initialize the upload // Use the /videos endpoint instead of /video_reels
const startParams = new URLSearchParams({ // This ensures the video appears on the Page Timeline (Feed) AND in Reels (if 9:16)
access_token: accessToken, const params = new URLSearchParams({
upload_phase: 'start', access_token: page.accessToken,
description: description || '',
file_url: videoUrl,
}); });
const startUrl = `${this.baseUrl}/${page.pageId}/video_reels?${startParams.toString()}`; const url = `${this.baseUrl}/${page.pageId}/videos?${params.toString()}`;
console.log('📤 Phase 1: START - Initializing Reel upload'); const response = await fetch(url, {
const startResponse = await fetch(startUrl, {
method: 'POST', method: 'POST',
}); });
if (!startResponse.ok) { if (!response.ok) {
const error = await startResponse.json() as FacebookError; const error = await response.json() as FacebookError;
throw new Error(`Facebook Reel API error (START phase): ${error.error.message} (code: ${error.error.code})`); throw new Error(`Facebook API error publishing video/reel: ${error.error.message} (code: ${error.error.code})`);
} }
const startData = await startResponse.json() as { video_id: string; upload_url: string }; const data = await response.json() as FacebookVideoResponse;
const videoId = startData.video_id; const postId = data.post_id || data.id;
const uploadUrl = startData.upload_url;
console.log('✅ START phase complete, video_id:', videoId); console.log('✅ Reel published successfully to Feed & Reels! ID:', postId);
// Phase 2: UPLOAD - Upload the video to rupload.facebook.com return postId;
// IMPORTANT: file_url must be passed as a header for URL-based uploads
console.log('📤 Phase 2: UPLOAD - Uploading video to:', uploadUrl);
const uploadResponse = await fetch(uploadUrl, {
method: 'POST',
headers: {
'Authorization': `OAuth ${accessToken}`,
'file_url': videoUrl,
},
});
if (!uploadResponse.ok) {
const errorText = await uploadResponse.text();
console.error('❌ UPLOAD phase failed:', errorText);
throw new Error(`Facebook Reel API error (UPLOAD phase): ${errorText}`);
}
console.log('✅ UPLOAD phase complete');
// Phase 3: FINISH - Finalize and publish the Reel
const finishParams = new URLSearchParams({
access_token: accessToken,
upload_phase: 'finish',
video_id: videoId,
video_state: 'PUBLISHED',
});
// Add description if provided
if (description) {
finishParams.append('description', description);
}
const finishUrl = `${this.baseUrl}/${page.pageId}/video_reels?${finishParams.toString()}`;
console.log('📤 Phase 3: FINISH - Publishing Reel');
const finishResponse = await fetch(finishUrl, {
method: 'POST',
});
if (!finishResponse.ok) {
const error = await finishResponse.json() as FacebookError;
throw new Error(`Facebook Reel API error (FINISH phase): ${error.error.message} (code: ${error.error.code})`);
}
const finishData = await finishResponse.json() as { success: boolean; post_id?: string };
if (!finishData.success) {
throw new Error('Facebook Reel publishing failed - success was false');
}
const reelId = finishData.post_id || videoId;
console.log('✅ Reel published successfully! ID:', reelId);
return reelId;
} }
/** /**