/** * Zoom Integration for WORKWAY * * Unified client for Zoom Meetings, Clips, and Transcripts. * Supports both OAuth API transcripts and browser scraper fallback * for full speaker attribution. * * ## Transcript Retrieval (3-tier approach) * * 1. **OAuth API** - Fast, but may lack speaker names * 2. **Recordings API** - Falls back to download URL * 3. **Browser Scraper** - Full speaker attribution (requires setup) * * ## Browser Scraper Setup * * For speaker-attributed transcripts, deploy the WORKWAY Zoom Scraper: * * ```bash * cd packages/workers/zoom-scraper * wrangler kv:namespace create ZOOM_COOKIES * wrangler secret put UPLOAD_SECRET * wrangler deploy * ``` * * Then visit `/sync` to authenticate via bookmarklet. * * @example Basic usage (OAuth API only) * ```typescript * import { Zoom } from '@workwayco/integrations/zoom'; * * const zoom = new Zoom({ accessToken: tokens.zoom.access_token }); * * // Get recent meetings * const meetings = await zoom.getMeetings({ days: 1 }); * * // Get transcript (OAuth API) * const transcript = await zoom.getTranscript({ meetingId: '123456' }); * ``` * * @example With browser scraper fallback (speaker attribution) * ```typescript * const zoom = new Zoom({ * accessToken: tokens.zoom.access_token, * browserScraperUrl: 'https://zoom-scraper.your-domain.workers.dev' * }); * * // Get transcript with speaker names * const transcript = await zoom.getTranscript({ * meetingId: '123456', * fallbackToBrowser: true, * shareUrl: recording.share_url * }); * // Returns: { speakers: ['Alice', 'Bob'], has_speaker_attribution: true } * ``` */ import { ActionResult } from '@workwayco/sdk'; import { BaseAPIClient } from '../core/index.js'; /** * Zoom integration configuration */ export interface ZoomConfig { /** OAuth access token */ accessToken: string; /** Optional: Override API endpoint (for testing) */ apiUrl?: string; /** Request timeout in milliseconds (default: 30000) */ timeout?: number; /** Browser scraper URL for transcript fallback */ browserScraperUrl?: string; } /** * Zoom meeting object */ export interface ZoomMeeting { id: number; uuid?: string; topic: string; agenda?: string; start_time: string; duration: number; timezone?: string; created_at: string; host_id: string; join_url?: string; /** Meeting type: 1=instant, 2=scheduled, 3=recurring no fixed time, 8=recurring fixed time */ type?: 1 | 2 | 3 | 8; } /** * Zoom recording object */ export interface ZoomRecording { id: string; meeting_id: string; recording_start: string; recording_end: string; duration: number; total_size: number; recording_count: number; share_url?: string; topic?: string; recording_files: ZoomRecordingFile[]; } /** * Zoom recording file */ export interface ZoomRecordingFile { id: string; meeting_id: string; recording_start: string; recording_end: string; /** File type: 'MP4', 'TRANSCRIPT', 'CHAT', 'AUDIO', etc. */ file_type: 'MP4' | 'TRANSCRIPT' | 'CHAT' | 'AUDIO' | 'CC' | string; file_size: number; download_url: string; status: string; recording_type?: string; } /** * Zoom clip object */ export interface ZoomClip { id: string; title: string; description?: string; duration: number; created_at: string; status: string; download_url?: string; share_url?: string; thumbnail_url?: string; file_size?: number; host_id?: string; } /** * Transcript result with source information */ export interface TranscriptResult { /** Plain text transcript */ transcript_text: string; /** Raw WebVTT content (if available) */ webvtt_raw?: string; /** Source of the transcript */ source: 'oauth_api' | 'browser_scraper'; /** Whether speaker names are included */ has_speaker_attribution: boolean; /** Detected speaker names */ speakers?: string[]; /** Associated recording (if from recordings API) */ recording?: ZoomRecording; } /** * Paginated response for meetings */ export interface MeetingsResponse { meetings: ZoomMeeting[]; next_page_token?: string; page_count: number; page_size: number; total_records: number; } /** * Paginated response for clips */ export interface ClipsResponse { clips: ZoomClip[]; next_page_token?: string; page_size: number; total_records?: number; } /** * Options for getting meetings */ export interface GetMeetingsOptions { /** User ID or 'me' for current user */ userId?: string; /** Meeting type filter */ type?: 'scheduled' | 'live' | 'upcoming' | 'upcoming_meetings' | 'previous_meetings'; /** Number of days to look back */ days?: number; /** From date (YYYY-MM-DD or Date object) */ from?: string | Date; /** To date (YYYY-MM-DD or Date object) */ to?: string | Date; /** Page size (max 300) */ pageSize?: number; /** Pagination token */ nextPageToken?: string; } /** * Options for getting a single meeting */ export interface GetMeetingOptions { /** Meeting ID */ meetingId: string | number; } /** * Options for getting recordings */ export interface GetRecordingsOptions { /** Meeting ID */ meetingId: string | number; } /** * Options for getting transcript */ export interface GetTranscriptOptions { /** Meeting ID */ meetingId: string | number; /** Fall back to browser scraper if OAuth transcript lacks speaker attribution */ fallbackToBrowser?: boolean; /** Share URL for browser scraper (required if fallbackToBrowser is true) */ shareUrl?: string; } /** * Options for getting clips */ export interface GetClipsOptions { /** User ID or 'me' for current user */ userId?: string; /** Number of days to look back */ days?: number; /** From date */ from?: string | Date; /** To date */ to?: string | Date; /** Page size (max 300) */ pageSize?: number; /** Pagination token */ nextPageToken?: string; } /** * Options for getting clip transcript */ export interface GetClipTranscriptOptions { /** Clip share URL */ shareUrl: string; } /** * Zoom Integration * * Weniger, aber besser: Unified client for meetings, clips, and transcripts. * Extends BaseAPIClient for shared HTTP logic. */ export declare class Zoom extends BaseAPIClient { private browserScraperUrl?; constructor(config: ZoomConfig); /** * Get meetings for a user * * @returns ActionResult with meetings list */ getMeetings(options?: GetMeetingsOptions): Promise>; /** * Get a specific meeting * * @returns ActionResult with meeting details */ getMeeting(options: GetMeetingOptions): Promise>; /** * Get recordings for a meeting * * @returns ActionResult with recording data (null if no recordings) */ getRecordings(options: GetRecordingsOptions): Promise>; /** * Get transcript for a meeting * * Uses a hybrid approach: * 1. First tries the OAuth API /meetings/{id}/transcript endpoint * 2. Falls back to recordings API for download URL * 3. Optionally falls back to browser scraper for speaker attribution * * @returns ActionResult with transcript data */ getTranscript(options: GetTranscriptOptions): Promise>; /** * Get transcript metadata from the dedicated transcript endpoint */ private getTranscriptMetadata; /** * Download a file (transcript, recording, etc.) */ private downloadFile; /** * Parse WebVTT format to plain text with speaker extraction */ private parseWebVTT; /** * Fetch transcript from browser scraper (for speaker attribution) */ private fetchFromBrowserScraper; /** * Get clips for a user * * @returns ActionResult with clips list */ getClips(options?: GetClipsOptions): Promise>; /** * Get transcript for a clip using browser scraper * * Note: Clips don't have OAuth transcript API, so this always uses the scraper * * @returns ActionResult with transcript data */ getClipTranscript(options: GetClipTranscriptOptions): Promise>; /** * Get meetings with transcripts for a date range * * This is the main method for the Meeting Intelligence workflow. * Fetches meetings and their transcripts in a single operation. * * @returns ActionResult with meetings and their transcripts */ getMeetingsWithTranscripts(options?: GetMeetingsOptions & { fallbackToBrowser?: boolean; }): Promise>>; /** * Format date to YYYY-MM-DD */ private formatDate; /** * Format date to ISO string */ private formatDateISO; /** * Get capabilities for Zoom actions */ private getCapabilities; } //# sourceMappingURL=index.d.ts.map