Merge pull request #80 from R0m1k3/dev

Dev
This commit is contained in:
LogiFlow authored and GitHub committed 2025-10-28 13:24:35 +01:00
commit 7cdc4423e9
2 files changed
+64 -16

No files matched your search

+3
View File
@@ -10,6 +10,9 @@ Preferred communication style: Simple, everyday language.
## Recent Changes ## 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 ### 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. - **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.
+61 -16
View File
@@ -361,27 +361,72 @@ export class FacebookService {
} }
private async publishVideoStory(post: Post, page: SocialPage, media: Media): Promise<string> { private async publishVideoStory(post: Post, page: SocialPage, media: Media): Promise<string> {
// 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 videoUrl = media.originalUrl;
const accessToken = page.accessToken!;
const params = new URLSearchParams({
access_token: page.accessToken!, // Phase 1: START - Initialize the upload
file_url: videoUrl, const startParams = new URLSearchParams({
access_token: accessToken,
upload_phase: 'start',
}); });
const url = `${this.baseUrl}/${page.pageId}/video_stories?${params.toString()}`; const startUrl = `${this.baseUrl}/${page.pageId}/video_stories?${startParams.toString()}`;
const response = await fetch(url, { const startResponse = await fetch(startUrl, {
method: 'POST', method: 'POST',
}); });
if (!response.ok) { if (!startResponse.ok) {
const error = await response.json() as FacebookError; const error = await startResponse.json() as FacebookError;
throw new Error(`Facebook API error publishing video story: ${error.error.message} (code: ${error.error.code})`); 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 }; const startData = await startResponse.json() as { video_id: string; upload_url: string };
return data.post_id; 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;
} }
} }