/** * YouTube Integration for WORKWAY * * Provides actions for interacting with YouTube: * - List playlist items * - Get video metadata * - Fetch video transcripts (captions) * * ## Transcript Retrieval * * YouTube has no official transcript API for videos you don't own. * This integration uses the youtube-transcript library which scrapes * the publicly-available captions from the YouTube player. * * ## OAuth Scopes * * - `youtube.readonly` - Read access to playlists and videos * * @example Basic usage * ```typescript * import { YouTube } from '@workwayco/integrations/youtube'; * * const youtube = new YouTube({ accessToken: tokens.youtube.access_token }); * * // List videos in a playlist * const videos = await youtube.getPlaylistItems({ playlistId: 'PLxxx' }); * * // Get video details * const video = await youtube.getVideo({ videoId: 'dQw4w9WgXcQ' }); * * // Get transcript * const transcript = await youtube.getTranscript({ videoId: 'dQw4w9WgXcQ' }); * ``` */ import { ActionResult } from '@workwayco/sdk'; import { BaseAPIClient } from '../core/index.js'; /** * YouTube integration configuration */ export interface YouTubeConfig { /** OAuth access token */ accessToken: string; /** Optional: Override API endpoint (for testing) */ apiUrl?: string; /** Request timeout in milliseconds (default: 30000) */ timeout?: number; /** API Key (alternative to OAuth for public data) */ apiKey?: string; /** OAuth refresh token for automatic token refresh */ refreshToken?: string; /** OAuth client ID (required for token refresh) */ clientId?: string; /** OAuth client secret (required for token refresh) */ clientSecret?: string; /** Token expiration timestamp in Unix ms (for proactive refresh) */ tokenExpiresAt?: number; /** Callback when token is refreshed */ onTokenRefreshed?: (newAccessToken: string, newRefreshToken?: string, expiresIn?: number) => void | Promise; } /** * YouTube video object */ export interface YouTubeVideo { id: string; title: string; description: string; publishedAt: string; channelId: string; channelTitle: string; thumbnails: { default?: YouTubeThumbnail; medium?: YouTubeThumbnail; high?: YouTubeThumbnail; standard?: YouTubeThumbnail; maxres?: YouTubeThumbnail; }; tags?: string[]; duration?: string; viewCount?: number; likeCount?: number; commentCount?: number; } /** * YouTube thumbnail object */ export interface YouTubeThumbnail { url: string; width: number; height: number; } /** * YouTube playlist item object */ export interface YouTubePlaylistItem { id: string; videoId: string; title: string; description: string; publishedAt: string; channelId: string; channelTitle: string; position: number; thumbnails: YouTubeVideo['thumbnails']; videoOwnerChannelId?: string; videoOwnerChannelTitle?: string; } /** * YouTube playlist object */ export interface YouTubePlaylist { id: string; title: string; description: string; publishedAt: string; channelId: string; channelTitle: string; thumbnails: YouTubeVideo['thumbnails']; itemCount: number; } /** * YouTube transcript segment */ export interface YouTubeTranscriptSegment { text: string; offset: number; duration: number; } /** * YouTube transcript result */ export interface YouTubeTranscript { videoId: string; segments: YouTubeTranscriptSegment[]; text: string; language?: string; } /** * Paginated list response */ export interface YouTubePagedResponse { items: T[]; nextPageToken?: string; prevPageToken?: string; totalResults?: number; resultsPerPage: number; } export interface GetPlaylistItemsOptions { /** Playlist ID */ playlistId: string; /** Maximum results (default: 50, max: 50) */ maxResults?: number; /** Page token for pagination */ pageToken?: string; } export interface GetVideoOptions { /** Video ID */ videoId: string; } export interface GetVideosOptions { /** Video IDs (max 50) */ videoIds: string[]; } export interface GetPlaylistOptions { /** Playlist ID */ playlistId: string; } export interface GetTranscriptOptions { /** Video ID */ videoId: string; /** Preferred language code (e.g., 'en', 'es') */ language?: string; } export interface SearchVideosOptions { /** Search query */ query: string; /** Maximum results (default: 25, max: 50) */ maxResults?: number; /** Page token for pagination */ pageToken?: string; /** Channel ID to search within */ channelId?: string; /** Order: 'date', 'rating', 'relevance', 'title', 'viewCount' */ order?: 'date' | 'rating' | 'relevance' | 'title' | 'viewCount'; } /** * YouTube Integration * * Extends BaseAPIClient for DRY HTTP handling with automatic token refresh. */ export declare class YouTube extends BaseAPIClient { private apiKey?; constructor(config: YouTubeConfig); /** * Get authorization params - either OAuth token or API key */ private getAuthParams; /** * Get headers - include OAuth token if available */ private getAuthHeaders; /** * Get items in a playlist * * @returns ActionResult with playlist items */ getPlaylistItems(options: GetPlaylistItemsOptions): Promise>>; /** * Get playlist metadata * * @returns ActionResult with playlist details */ getPlaylist(options: GetPlaylistOptions): Promise>; /** * Get video details * * @returns ActionResult with video details */ getVideo(options: GetVideoOptions): Promise>; /** * Get multiple videos at once (batch) * * @returns ActionResult with video details */ getVideos(options: GetVideosOptions): Promise>; /** * Get video transcript * * Note: YouTube does not have an official transcript API for videos you don't own. * This method fetches the auto-generated or user-uploaded captions that are * publicly visible on the video. * * For Cloudflare Workers environment, we fetch the caption track directly from * YouTube's timedtext API. * * @returns ActionResult with transcript */ getTranscript(options: GetTranscriptOptions): Promise>; /** * Get capabilities - be honest about what this integration can do */ private getCapabilities; /** * Convert YouTube video to StandardDocument format */ private toStandardDocument; } /** * Parse ISO 8601 duration to seconds * * @example * parseDuration('PT1H2M10S') // 3730 * parseDuration('PT5M30S') // 330 */ export declare function parseDuration(duration: string): number; /** * Format seconds to human-readable duration * * @example * formatDuration(3730) // '1:02:10' * formatDuration(330) // '5:30' */ export declare function formatDuration(seconds: number): string; /** * Extract video ID from various YouTube URL formats * * @example * extractVideoId('https://www.youtube.com/watch?v=dQw4w9WgXcQ') // 'dQw4w9WgXcQ' * extractVideoId('https://youtu.be/dQw4w9WgXcQ') // 'dQw4w9WgXcQ' * extractVideoId('dQw4w9WgXcQ') // 'dQw4w9WgXcQ' */ export declare function extractVideoId(urlOrId: string): string | null; /** * Extract playlist ID from various YouTube URL formats * * @example * extractPlaylistId('https://www.youtube.com/playlist?list=PLxxx') // 'PLxxx' * extractPlaylistId('PLxxx') // 'PLxxx' */ export declare function extractPlaylistId(urlOrId: string): string | null; //# sourceMappingURL=index.d.ts.map