UNPKG

@memberjunction/actions-bizapps-social

Version:

Social Media Actions for MemberJunction - Twitter, LinkedIn, Facebook, Instagram, TikTok, YouTube, HootSuite, Buffer

284 lines 11.5 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { RegisterClass } from '@memberjunction/global'; import { FacebookBaseAction } from '../facebook-base.action.js'; import { LogStatus, LogError } from '@memberjunction/core'; import axios from 'axios'; import { BaseAction } from '@memberjunction/actions'; /** * Schedules a post to be published on a Facebook page at a future time. * Posts can be scheduled from 10 minutes to 6 months in the future. */ let FacebookSchedulePostAction = class FacebookSchedulePostAction extends FacebookBaseAction { /** * Get action description */ get Description() { return 'Schedules a post to be published on a Facebook page at a specified future time (10 minutes to 6 months in advance)'; } /** * Define the parameters for this action */ get Params() { return [ ...this.commonSocialParams, { Name: 'PageID', Type: 'Input', Value: null, }, { Name: 'Content', Type: 'Input', Value: null, }, { Name: 'ScheduledTime', Type: 'Input', Value: null, }, { Name: 'Link', Type: 'Input', Value: null, }, { Name: 'MediaFiles', Type: 'Input', Value: null, }, { Name: 'Tags', Type: 'Input', Value: null, }, { Name: 'PlaceID', Type: 'Input', Value: null, }, { Name: 'TargetingRestrictions', Type: 'Input', Value: null, }, { Name: 'AllowReschedule', Type: 'Input', Value: false, } ]; } /** * Execute the action */ async InternalRunAction(params) { const { Params, ContextUser } = params; try { // Validate required parameters const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID'); const pageId = this.getParamValue(Params, 'PageID'); const scheduledTime = this.getParamValue(Params, 'ScheduledTime'); if (!companyIntegrationId) { return { Success: false, Message: 'CompanyIntegrationID is required', ResultCode: 'INVALID_TOKEN' }; } if (!pageId) { return { Success: false, Message: 'PageID is required', ResultCode: 'MISSING_REQUIRED_PARAM' }; } if (!scheduledTime) { return { Success: false, Message: 'ScheduledTime is required', ResultCode: 'MISSING_REQUIRED_PARAM' }; } // Initialize OAuth if (!await this.initializeOAuth(companyIntegrationId, params)) { return { Success: false, Message: 'Failed to initialize Facebook OAuth connection', ResultCode: 'INVALID_TOKEN' }; } // Validate scheduled time const scheduledDate = new Date(scheduledTime); const now = new Date(); const minScheduleTime = new Date(now.getTime() + 10 * 60 * 1000); // 10 minutes from now const maxScheduleTime = new Date(now.getTime() + 180 * 24 * 60 * 60 * 1000); // 6 months from now if (isNaN(scheduledDate.getTime())) { return { Success: false, Message: 'Invalid scheduled time format. Use ISO 8601 format.', ResultCode: 'INVALID_SCHEDULE_TIME' }; } if (scheduledDate < minScheduleTime) { return { Success: false, Message: 'Scheduled time must be at least 10 minutes in the future', ResultCode: 'INVALID_SCHEDULE_TIME' }; } if (scheduledDate > maxScheduleTime) { return { Success: false, Message: 'Scheduled time cannot be more than 6 months in the future', ResultCode: 'INVALID_SCHEDULE_TIME' }; } // Get parameters const content = this.getParamValue(Params, 'Content'); const link = this.getParamValue(Params, 'Link'); const mediaFiles = this.getParamValue(Params, 'MediaFiles'); const tags = this.getParamValue(Params, 'Tags'); const placeId = this.getParamValue(Params, 'PlaceID'); const targetingRestrictions = this.getParamValue(Params, 'TargetingRestrictions'); const allowReschedule = this.getParamValue(Params, 'AllowReschedule'); // Validate that we have some content if (!content && !link && (!mediaFiles || mediaFiles.length === 0)) { return { Success: false, Message: 'At least one of Content, Link, or MediaFiles is required', ResultCode: 'MISSING_CONTENT' }; } // Check for scheduling conflicts if requested if (!allowReschedule) { const hasConflict = await this.checkSchedulingConflict(pageId, scheduledDate); if (hasConflict) { return { Success: false, Message: 'Another post is already scheduled within 5 minutes of this time', ResultCode: 'SCHEDULE_CONFLICT' }; } } // Build post data const postData = { scheduled_publish_time: Math.floor(scheduledDate.getTime() / 1000), published: false // Must be false for scheduled posts }; if (content) { postData.message = content; } if (link) { postData.link = link; } if (placeId) { postData.place = placeId; } if (tags && tags.length > 0) { postData.tags = tags; } if (targetingRestrictions) { postData.targeting = targetingRestrictions; } // Handle media uploads if (mediaFiles && mediaFiles.length > 0) { LogStatus(`Uploading ${mediaFiles.length} media files for scheduled post...`); const mediaIds = []; for (const file of mediaFiles) { try { const mediaId = await this.uploadMediaToPage(pageId, file); mediaIds.push(mediaId); LogStatus(`Uploaded media: ${file.filename}`); } catch (error) { LogError(`Failed to upload media ${file.filename}: ${error}`); return { Success: false, Message: `Failed to upload media: ${error instanceof Error ? error.message : 'Unknown error'}`, ResultCode: 'INVALID_MEDIA' }; } } // Attach media to post postData.attached_media = mediaIds.map(id => ({ media_fbid: id })); } // Create the scheduled post LogStatus(`Scheduling Facebook post for ${scheduledDate.toISOString()}...`); const post = await this.createPost(pageId, postData); // Get the scheduled post details const scheduledPost = await this.getScheduledPost(pageId, post.id); LogStatus(`Facebook post scheduled successfully: ${post.id}`); return { Success: true, Message: `Post scheduled for ${scheduledDate.toISOString()}`, ResultCode: 'SUCCESS', Params }; } catch (error) { LogError(`Failed to schedule Facebook post: ${error instanceof Error ? error.message : 'Unknown error'}`); if (this.isAuthError(error)) { return this.handleOAuthError(error); } return { Success: false, Message: error instanceof Error ? error.message : 'Unknown error occurred', ResultCode: 'ERROR' }; } } /** * Check if there's a scheduling conflict within 5 minutes */ async checkSchedulingConflict(pageId, scheduledTime) { try { const pageToken = await this.getPageAccessToken(pageId); const fiveMinutesBefore = new Date(scheduledTime.getTime() - 5 * 60 * 1000); const fiveMinutesAfter = new Date(scheduledTime.getTime() + 5 * 60 * 1000); // Get scheduled posts in the time window const response = await axios.get(`${this.apiBaseUrl}/${pageId}/scheduled_posts`, { params: { access_token: pageToken, since: Math.floor(fiveMinutesBefore.getTime() / 1000), until: Math.floor(fiveMinutesAfter.getTime() / 1000), limit: 10 } }); const scheduledPosts = response.data.data || []; return scheduledPosts.length > 0; } catch (error) { LogError(`Failed to check scheduling conflicts: ${error}`); return false; // Don't block on error } } /** * Get details of a scheduled post */ async getScheduledPost(pageId, postId) { try { const pageToken = await this.getPageAccessToken(pageId); const response = await axios.get(`${this.apiBaseUrl}/${postId}`, { params: { access_token: pageToken, fields: 'id,message,scheduled_publish_time,is_published' } }); return response.data; } catch (error) { LogError(`Failed to get scheduled post details: ${error}`); return null; } } }; FacebookSchedulePostAction = __decorate([ RegisterClass(BaseAction, 'FacebookSchedulePostAction') ], FacebookSchedulePostAction); export { FacebookSchedulePostAction }; //# sourceMappingURL=schedule-post.action.js.map