UNPKG

@memberjunction/actions-bizapps-social

Version:

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

257 lines (232 loc) 9.1 kB
import { RegisterClass } from '@memberjunction/global'; import { YouTubeBaseAction } from '../youtube-base.action'; import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base'; import { BaseAction } from '@memberjunction/actions'; /** * Action to create a playlist on YouTube */ @RegisterClass(BaseAction, 'YouTubeCreatePlaylistAction') export class YouTubeCreatePlaylistAction extends YouTubeBaseAction { /** * Create a playlist on YouTube */ protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> { 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 title = this.getParamValue(Params, 'Title'); const description = this.getParamValue(Params, 'Description'); const privacyStatus = this.getParamValue(Params, 'PrivacyStatus') || 'private'; const tags = this.getParamValue(Params, 'Tags'); const defaultLanguage = this.getParamValue(Params, 'DefaultLanguage'); const videoIds = this.getParamValue(Params, 'VideoIDs'); // Validate required parameters if (!title) { throw new Error('Title is required for playlist creation'); } // Create playlist const playlistData = { snippet: { title: title, description: description || '', tags: tags || [], defaultLanguage: defaultLanguage || 'en' }, status: { privacyStatus: privacyStatus } }; const playlistResponse = await this.makeYouTubeRequest<any>( '/playlists', 'POST', playlistData, { part: 'snippet,status' }, ContextUser ); const playlistId = playlistResponse.id; // Add videos to playlist if provided let addedVideos: any[] = []; if (videoIds && videoIds.length > 0) { addedVideos = await this.addVideosToPlaylist(playlistId, videoIds, ContextUser); } // Get full playlist details const playlistDetails = await this.makeYouTubeRequest<any>( '/playlists', 'GET', undefined, { part: 'snippet,status,contentDetails', id: playlistId }, ContextUser ); const playlist = playlistDetails.items[0]; // Prepare result const result = { playlistId: playlist.id, playlistUrl: `https://www.youtube.com/playlist?list=${playlist.id}`, title: playlist.snippet.title, description: playlist.snippet.description, tags: playlist.snippet.tags, privacyStatus: playlist.status.privacyStatus, itemCount: playlist.contentDetails.itemCount, channelId: playlist.snippet.channelId, channelTitle: playlist.snippet.channelTitle, publishedAt: playlist.snippet.publishedAt, thumbnails: playlist.snippet.thumbnails, videosAdded: addedVideos.length, videoDetails: addedVideos, quotaCost: this.getQuotaCost('playlists.insert') + (addedVideos.length * this.getQuotaCost('playlistItems.insert')) }; // Update output parameters const outputParams = [...Params]; const playlistDetailsParam = outputParams.find(p => p.Name === 'PlaylistDetails'); if (playlistDetailsParam) playlistDetailsParam.Value = result; const playlistIdParam = outputParams.find(p => p.Name === 'PlaylistID'); if (playlistIdParam) playlistIdParam.Value = playlistId; const playlistUrlParam = outputParams.find(p => p.Name === 'PlaylistURL'); if (playlistUrlParam) playlistUrlParam.Value = result.playlistUrl; return { Success: true, ResultCode: 'SUCCESS', Message: `Playlist created successfully with ${addedVideos.length} videos: ${result.playlistUrl}`, Params: outputParams }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { Success: false, ResultCode: this.getErrorCode(errorMessage), Message: `Failed to create playlist: ${errorMessage}`, Params }; } } /** * Add videos to a playlist */ private async addVideosToPlaylist(playlistId: string, videoIds: string[], contextUser?: any): Promise<any[]> { const addedVideos: any[] = []; for (let i = 0; i < videoIds.length; i++) { const videoId = videoIds[i]; try { const playlistItem = { snippet: { playlistId: playlistId, position: i, resourceId: { kind: 'youtube#video', videoId: videoId } } }; const response = await this.makeYouTubeRequest<any>( '/playlistItems', 'POST', playlistItem, { part: 'snippet' }, contextUser ); addedVideos.push({ videoId: videoId, position: response.snippet.position, addedAt: response.snippet.publishedAt, playlistItemId: response.id }); } catch (error) { // Log error but continue adding other videos console.error(`Failed to add video ${videoId} to playlist:`, error); addedVideos.push({ videoId: videoId, position: i, error: error.message }); } } return addedVideos; } /** * Get error code from error message */ private getErrorCode(message: string): string { 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'; return 'ERROR'; } /** * Define the parameters this action expects */ public get Params(): ActionParam[] { const baseParams = this.commonSocialParams; const specificParams: ActionParam[] = [ { Name: 'Title', Type: 'Input', Value: null }, { Name: 'Description', Type: 'Input', Value: null }, { Name: 'PrivacyStatus', Type: 'Input', Value: 'private' }, { Name: 'Tags', Type: 'Input', Value: null }, { Name: 'DefaultLanguage', Type: 'Input', Value: 'en' }, { Name: 'VideoIDs', Type: 'Input', Value: null }, { Name: 'PlaylistDetails', Type: 'Output', Value: null }, { Name: 'PlaylistID', Type: 'Output', Value: null }, { Name: 'PlaylistURL', Type: 'Output', Value: null } ]; return [...baseParams, ...specificParams]; } /** * Metadata about this action */ public get Description(): string { return 'Creates a YouTube playlist and optionally adds videos to it'; } }