From ab7f7d9204a1857b707e1626be1d2e8b6e3a8a61 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Tue, 28 Oct 2025 12:15:43 +0000 Subject: [PATCH 1/3] Transitioned from Plan to Build mode Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/rBcOjHB From 718d1535d6b5994cda7d10a315cb6214723b43e2 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Tue, 28 Oct 2025 12:23:37 +0000 Subject: [PATCH 2/3] Fix video story posting to Facebook with proper 3-phase upload Implement the required 3-phase upload process (START, UPLOAD, FINISH) for publishing video stories to Facebook via the Graph API, addressing the "#100 The parameter upload_phase is required" error. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/VJoXNjs --- replit.md | 3 ++ server/services/facebook.ts | 77 +++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/replit.md b/replit.md index 0e1d70e..0062e4e 100644 --- a/replit.md +++ b/replit.md @@ -10,6 +10,9 @@ Preferred communication style: Simple, everyday language. ## Recent Changes +### October 28, 2025 +- **Facebook Video Story Publishing Fix**: Fixed critical bug preventing video story publication. Facebook Graph API requires a 3-phase upload process for video stories: (1) START phase - initialize upload session and get `video_id` + `upload_url`, (2) UPLOAD phase - POST video to rupload.facebook.com endpoint with `file_url` header and OAuth authorization, (3) FINISH phase - finalize and publish story with `video_id`. Previous implementation incorrectly attempted direct upload to `/video_stories` endpoint with `file_url` parameter, causing "#100 The parameter upload_phase is required" error. Fixed by implementing proper 3-phase workflow using remote URL upload method (file_url header), avoiding need for binary chunked uploads. + ### October 17, 2025 - **Docker Deployment Configuration**: Configured Docker Compose for private server deployment with PostgreSQL and application on same network. PostgreSQL exposed on port 4523:4523 for external access. Application runs on internal port 5555 (accessible via Nginx reverse proxy). Both PostgreSQL and app are on nginx_default external network and internal network for communication. Created comprehensive DOCKER.md documentation with setup instructions, network architecture explanation, and troubleshooting guide. diff --git a/server/services/facebook.ts b/server/services/facebook.ts index 207c64c..90395d9 100644 --- a/server/services/facebook.ts +++ b/server/services/facebook.ts @@ -361,27 +361,72 @@ export class FacebookService { } private async publishVideoStory(post: Post, page: SocialPage, media: Media): Promise { - // Video stories can be published directly to the video_stories endpoint + // Video stories require a 3-phase upload process: + // 1. START phase - Initialize the upload and get upload_url + // 2. UPLOAD phase - Upload the video to upload_url using file_url header + // 3. FINISH phase - Finalize and publish the story + const videoUrl = media.originalUrl; - - const params = new URLSearchParams({ - access_token: page.accessToken!, - file_url: videoUrl, + const accessToken = page.accessToken!; + + // Phase 1: START - Initialize the upload + const startParams = new URLSearchParams({ + access_token: accessToken, + upload_phase: 'start', }); - - const url = `${this.baseUrl}/${page.pageId}/video_stories?${params.toString()}`; - - const response = await fetch(url, { + + const startUrl = `${this.baseUrl}/${page.pageId}/video_stories?${startParams.toString()}`; + + const startResponse = await fetch(startUrl, { method: 'POST', }); - - if (!response.ok) { - const error = await response.json() as FacebookError; - throw new Error(`Facebook API error publishing video story: ${error.error.message} (code: ${error.error.code})`); + + if (!startResponse.ok) { + const error = await startResponse.json() as FacebookError; + throw new Error(`Facebook API error (START phase): ${error.error.message} (code: ${error.error.code})`); } - - const data = await response.json() as { success: boolean; post_id: string }; - return data.post_id; + + const startData = await startResponse.json() as { video_id: string; upload_url: string }; + const videoId = startData.video_id; + const uploadUrl = startData.upload_url; + + // Phase 2: UPLOAD - Upload the video using the upload_url + // IMPORTANT: file_url must be passed as a header, not a query parameter + const uploadResponse = await fetch(uploadUrl, { + method: 'POST', + headers: { + 'Authorization': `OAuth ${accessToken}`, + 'file_url': videoUrl, + }, + }); + + if (!uploadResponse.ok) { + const errorText = await uploadResponse.text(); + throw new Error(`Facebook API error (UPLOAD phase): ${errorText}`); + } + + // Phase 3: FINISH - Finalize and publish the story + const finishParams = new URLSearchParams({ + access_token: accessToken, + upload_phase: 'finish', + video_id: videoId, + }); + + const finishUrl = `${this.baseUrl}/${page.pageId}/video_stories?${finishParams.toString()}`; + + const finishResponse = await fetch(finishUrl, { + method: 'POST', + }); + + if (!finishResponse.ok) { + const error = await finishResponse.json() as FacebookError; + throw new Error(`Facebook API error (FINISH phase): ${error.error.message} (code: ${error.error.code})`); + } + + const finishData = await finishResponse.json() as { success: boolean; post_id?: string }; + + // Return the post_id from the finish response + return finishData.post_id || videoId; } } From fed8f38ec471b2c9d6d92a8d8dd5a7e312e738ef Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Tue, 28 Oct 2025 12:23:56 +0000 Subject: [PATCH 3/3] Fix video posting error by ensuring required upload phase parameter is sent Correct the Facebook API integration to include the `upload_phase` parameter when publishing video stories, resolving a common error where video posts fail due to missing required fields in the API request. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/VJoXNjs