@memberjunction/actions-bizapps-social
Version:
Social Media Actions for MemberJunction - Twitter, LinkedIn, Facebook, Instagram, TikTok, YouTube, HootSuite, Buffer
226 lines • 10.1 kB
JavaScript
;
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.YouTubeScheduleVideoAction = void 0;
const global_1 = require("@memberjunction/global");
const youtube_base_action_1 = require("../youtube-base.action");
const actions_1 = require("@memberjunction/actions");
/**
* Action to schedule a YouTube video for publishing
*/
let YouTubeScheduleVideoAction = class YouTubeScheduleVideoAction extends youtube_base_action_1.YouTubeBaseAction {
/**
* Schedule a video for publishing on YouTube
*/
async InternalRunAction(params) {
const { Params, ContextUser } = params;
try {
// Initialize OAuth
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
if (!companyIntegrationId) {
throw new Error('CompanyIntegrationID is required');
}
const initialized = await this.initializeOAuth(companyIntegrationId);
if (!initialized) {
throw new Error('Failed to initialize YouTube OAuth connection');
}
// Extract parameters
const videoId = this.getParamValue(Params, 'VideoID');
const publishAt = this.getParamValue(Params, 'PublishAt');
const notifySubscribers = this.getParamValue(Params, 'NotifySubscribers') ?? true;
const premiereTiming = this.getParamValue(Params, 'PremiereTiming');
const enableChat = this.getParamValue(Params, 'EnableChat') ?? false;
// Validate required parameters
if (!videoId) {
throw new Error('VideoID is required');
}
if (!publishAt) {
throw new Error('PublishAt date/time is required');
}
// Validate publish date is in the future
const publishDate = new Date(publishAt);
if (publishDate <= new Date()) {
throw new Error('PublishAt must be a future date/time');
}
// Get current video details
const currentVideo = await this.makeYouTubeRequest('/videos', 'GET', undefined, {
part: 'snippet,status',
id: videoId
}, ContextUser);
if (!currentVideo.items || currentVideo.items.length === 0) {
throw new Error(`Video not found: ${videoId}`);
}
const video = currentVideo.items[0];
// Verify video is currently private
if (video.status.privacyStatus !== 'private') {
throw new Error(`Video must be private to schedule. Current status: ${video.status.privacyStatus}`);
}
// Prepare update data
const updateData = {
id: videoId,
status: {
privacyStatus: 'private', // Keep private until publish time
publishAt: this.formatDate(publishDate),
selfDeclaredMadeForKids: video.status.selfDeclaredMadeForKids,
notifySubscribers: notifySubscribers
}
};
// Handle premiere settings
if (premiereTiming === 'premiere') {
// Set up as a premiere
updateData.status.privacyStatus = 'unlisted'; // Premieres start as unlisted
updateData.liveStreamingDetails = {
scheduledStartTime: this.formatDate(publishDate),
enableLowLatency: false,
enableAutoStart: true,
enableDvr: true
};
if (enableChat) {
updateData.liveStreamingDetails.enableClosedCaptions = false;
updateData.liveStreamingDetails.enableContentEncryption = false;
updateData.liveStreamingDetails.enableEmbed = true;
}
}
// Update the video
const updateResponse = await this.makeYouTubeRequest('/videos', 'PUT', updateData, {
part: 'status' + (premiereTiming === 'premiere' ? ',liveStreamingDetails' : '')
}, ContextUser);
// Get updated video details
const updatedVideo = await this.makeYouTubeRequest('/videos', 'GET', undefined, {
part: 'snippet,status,contentDetails' + (premiereTiming === 'premiere' ? ',liveStreamingDetails' : ''),
id: videoId
}, ContextUser);
const finalVideo = updatedVideo.items[0];
// Calculate time until publish
const timeUntilPublish = publishDate.getTime() - Date.now();
const hoursUntilPublish = Math.floor(timeUntilPublish / (1000 * 60 * 60));
const minutesUntilPublish = Math.floor((timeUntilPublish % (1000 * 60 * 60)) / (1000 * 60));
// Prepare result
const result = {
videoId: finalVideo.id,
videoUrl: `https://www.youtube.com/watch?v=${finalVideo.id}`,
title: finalVideo.snippet.title,
scheduledFor: finalVideo.status.publishAt,
scheduledForLocal: new Date(finalVideo.status.publishAt).toLocaleString(),
timeUntilPublish: {
hours: hoursUntilPublish,
minutes: minutesUntilPublish,
formatted: `${hoursUntilPublish}h ${minutesUntilPublish}m`
},
privacyStatus: finalVideo.status.privacyStatus,
notifySubscribers: notifySubscribers,
isPremiere: premiereTiming === 'premiere',
premiereDetails: premiereTiming === 'premiere' ? {
scheduledStartTime: finalVideo.liveStreamingDetails?.scheduledStartTime,
chatEnabled: enableChat
} : null,
thumbnails: finalVideo.snippet.thumbnails,
duration: finalVideo.contentDetails.duration,
quotaCost: this.getQuotaCost('videos.update')
};
// Update output parameters
const outputParams = [...Params];
const scheduleDetailsParam = outputParams.find(p => p.Name === 'ScheduleDetails');
if (scheduleDetailsParam)
scheduleDetailsParam.Value = result;
const scheduledTimeParam = outputParams.find(p => p.Name === 'ScheduledTime');
if (scheduledTimeParam)
scheduledTimeParam.Value = result.scheduledFor;
return {
Success: true,
ResultCode: 'SUCCESS',
Message: `Video scheduled successfully for ${result.scheduledForLocal} (${result.timeUntilPublish.formatted} from now)`,
Params: outputParams
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
return {
Success: false,
ResultCode: this.getErrorCode(errorMessage),
Message: `Failed to schedule video: ${errorMessage}`,
Params
};
}
}
/**
* Get error code from error message
*/
getErrorCode(message) {
if (message.includes('quota'))
return 'QUOTA_EXCEEDED';
if (message.includes('401') || message.includes('unauthorized'))
return 'INVALID_TOKEN';
if (message.includes('403') || message.includes('forbidden'))
return 'INSUFFICIENT_PERMISSIONS';
if (message.includes('404'))
return 'NOT_FOUND';
if (message.includes('rate limit'))
return 'RATE_LIMIT';
if (message.includes('future'))
return 'INVALID_DATE';
if (message.includes('private'))
return 'INVALID_STATUS';
return 'ERROR';
}
/**
* Define the parameters this action expects
*/
get Params() {
const baseParams = this.commonSocialParams;
const specificParams = [
{
Name: 'VideoID',
Type: 'Input',
Value: null
},
{
Name: 'PublishAt',
Type: 'Input',
Value: null
},
{
Name: 'NotifySubscribers',
Type: 'Input',
Value: true
},
{
Name: 'PremiereTiming',
Type: 'Input',
Value: 'standard'
},
{
Name: 'EnableChat',
Type: 'Input',
Value: false
},
{
Name: 'ScheduleDetails',
Type: 'Output',
Value: null
},
{
Name: 'ScheduledTime',
Type: 'Output',
Value: null
}
];
return [...baseParams, ...specificParams];
}
/**
* Metadata about this action
*/
get Description() {
return 'Schedules a private YouTube video to be published at a specific date/time with optional premiere settings';
}
};
exports.YouTubeScheduleVideoAction = YouTubeScheduleVideoAction;
exports.YouTubeScheduleVideoAction = YouTubeScheduleVideoAction = __decorate([
(0, global_1.RegisterClass)(actions_1.BaseAction, 'YouTubeScheduleVideoAction')
], YouTubeScheduleVideoAction);
//# sourceMappingURL=schedule-video.action.js.map