Advanced Examples
Advanced usage patterns and complex integration examples with the Meeting BaaS SDK.
Comprehensive Bot Management Workflow
Here's a complete workflow for managing bots throughout their lifecycle:
import { createBaasClient } from "@meeting-baas/sdk";
const client = createBaasClient({
api_key: "your-api-key",
timeout: 60000
});
async function comprehensiveBotWorkflow() {
try {
// 1. Join a meeting with advanced configuration
const joinResult = await client.joinMeeting({
meeting_url: "https://meet.google.com/abc-defg-hij",
bot_name: "Advanced Workflow Bot",
reserved: false,
bot_image: "https://example.com/bot-avatar.jpg",
enter_message: "Hello! I'm here to record and transcribe this meeting.",
extra: {
workflow_id: "comprehensive-example",
user_id: "user123",
session_type: "team-meeting"
},
recording_mode: "speaker_view",
speech_to_text: {
provider: "Gladia",
api_key: "your-gladia-key"
},
webhook_url: "https://your-app.com/webhooks/meeting-baas",
noone_joined_timeout: 300, // 5 minutes
waiting_room_timeout: 600 // 10 minutes
});
if (!joinResult.success) {
console.error("Failed to join meeting:", joinResult.error);
return;
}
const botId = joinResult.data.bot_id;
console.log("Bot joined successfully:", botId);
// 2. Monitor bot status and get meeting data
let meetingData = null;
let attempts = 0;
const maxAttempts = 10;
while (attempts < maxAttempts) {
const dataResult = await client.getMeetingData({
bot_id: botId,
include_transcripts: true
});
if (dataResult.success) {
meetingData = dataResult.data;
// Check if meeting has ended
if (meetingData.duration > 0) {
console.log("Meeting completed. Duration:", meetingData.duration);
break;
}
}
// Wait before next attempt
await new Promise(resolve => setTimeout(resolve, 30000)); // 30 seconds
attempts++;
}
// 3. Process meeting data
if (meetingData) {
console.log("Meeting duration:", meetingData.duration);
console.log("MP4 URL:", meetingData.mp4);
console.log("Transcript count:", meetingData.bot_data.transcripts.length);
// Process transcripts
meetingData.bot_data.transcripts.forEach(transcript => {
console.log(`Speaker: ${transcript.speaker}, Duration: ${transcript.end_time - transcript.start_time}s`);
});
}
// 4. Leave the meeting
const leaveResult = await client.leaveMeeting({ uuid: botId });
if (leaveResult.success) {
console.log("Bot left meeting successfully");
}
// 5. Clean up bot data
const deleteResult = await client.deleteBotData({ uuid: botId });
if (deleteResult.success) {
console.log("Bot data deleted successfully");
}
} catch (error) {
console.error("Unexpected error in workflow:", error);
}
}Calendar Integration with Event Scheduling
Advanced calendar integration with automatic event scheduling:
import { createBaasClient } from "@meeting-baas/sdk";
const client = createBaasClient({
api_key: "your-api-key"
});
async function advancedCalendarWorkflow() {
try {
// 1. Create calendar integration
const calendarResult = await client.createCalendar({
oauth_client_id: "your-oauth-client-id",
oauth_client_secret: "your-oauth-client-secret",
oauth_refresh_token: "your-oauth-refresh-token",
platform: "Google"
});
if (!calendarResult.success) {
console.error("Failed to create calendar:", calendarResult.error);
return;
}
const calendarId = calendarResult.data.calendar.uuid;
console.log("Calendar created:", calendarId);
// 2. List upcoming events
const eventsResult = await client.listCalendarEvents({
calendar_id: calendarId,
start_date_gte: new Date().toISOString(),
start_date_lte: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
status: "upcoming"
});
if (!eventsResult.success) {
console.error("Failed to list events:", eventsResult.error);
return;
}
console.log(`Found ${eventsResult.data.events.length} upcoming events`);
// 3. Schedule recordings for events with meeting URLs
for (const event of eventsResult.data.events) {
if (event.meeting_url && event.is_organizer) {
console.log(`Scheduling recording for: ${event.name}`);
const scheduleResult = await client.scheduleCalendarRecordEvent({
uuid: event.uuid,
body: {
bot_name: `Recording Bot - ${event.name}`,
extra: {
event_name: event.name,
scheduled_by: "advanced-workflow",
calendar_id: calendarId
},
recording_mode: "speaker_view",
speech_to_text: { provider: "Gladia" },
webhook_url: "https://your-app.com/webhooks/calendar-events",
enter_message: `Hello! I'm here to record the meeting: ${event.name}`
},
query: { all_occurrences: event.is_recurring }
});
if (scheduleResult.success) {
console.log(`Successfully scheduled recording for: ${event.name}`);
} else {
console.error(`Failed to schedule recording for: ${event.name}`, scheduleResult.error);
}
}
}
// 4. Monitor scheduled events
const scheduledEventsResult = await client.listCalendarEvents({
calendar_id: calendarId,
status: "upcoming"
});
if (scheduledEventsResult.success) {
scheduledEventsResult.data.events.forEach(event => {
if (event.bot_param) {
console.log(`Event "${event.name}" has bot scheduled:`, {
bot_name: event.bot_param.bot_name,
scheduled_time: event.start_time,
meeting_url: event.meeting_url
});
}
});
}
} catch (error) {
console.error("Unexpected error in calendar workflow:", error);
}
}Batch Operations and Error Handling
Advanced pattern for handling multiple operations with proper error handling:
import { createBaasClient } from "@meeting-baas/sdk";
const client = createBaasClient({
api_key: "your-api-key"
});
interface BatchOperation {
id: string;
meeting_url: string;
bot_name: string;
expected_duration: number;
}
async function batchBotOperations(operations: BatchOperation[]) {
const results = {
successful: [] as string[],
failed: [] as { id: string; error: string }[],
in_progress: [] as string[]
};
// 1. Join all meetings
const joinPromises = operations.map(async (op) => {
try {
const result = await client.joinMeeting({
meeting_url: op.meeting_url,
bot_name: op.bot_name,
reserved: false,
extra: { batch_id: op.id, expected_duration: op.expected_duration },
webhook_url: "https://your-app.com/webhooks/batch-operations"
});
if (result.success) {
results.in_progress.push(op.id);
return { id: op.id, bot_id: result.data.bot_id, success: true };
} else {
results.failed.push({ id: op.id, error: result.error.message });
return { id: op.id, success: false, error: result.error.message };
}
} catch (error) {
results.failed.push({ id: op.id, error: error.message });
return { id: op.id, success: false, error: error.message };
}
});
const joinResults = await Promise.allSettled(joinPromises);
// Process join results
joinResults.forEach((result, index) => {
if (result.status === 'fulfilled' && result.value.success) {
console.log(`Bot joined for operation ${result.value.id}: ${result.value.bot_id}`);
}
});
// 2. Monitor all active bots
const activeBots = joinResults
.filter((result, index) => result.status === 'fulfilled' && result.value.success)
.map(result => (result as PromiseFulfilledResult<any>).value);
if (activeBots.length > 0) {
console.log(`Monitoring ${activeBots.length} active bots...`);
// Wait for all meetings to complete
const monitoringPromises = activeBots.map(async (bot) => {
let attempts = 0;
const maxAttempts = 60; // 30 minutes with 30-second intervals
while (attempts < maxAttempts) {
const dataResult = await client.getMeetingData({
bot_id: bot.bot_id,
include_transcripts: true
});
if (dataResult.success && dataResult.data.duration > 0) {
// Meeting completed
results.successful.push(bot.id);
// Clean up
await client.deleteBotData({ uuid: bot.bot_id });
return { id: bot.id, duration: dataResult.data.duration };
}
await new Promise(resolve => setTimeout(resolve, 30000));
attempts++;
}
// Timeout - force leave
await client.leaveMeeting({ uuid: bot.bot_id });
results.failed.push({ id: bot.id, error: "Meeting monitoring timeout" });
return { id: bot.id, error: "Timeout" };
});
const monitoringResults = await Promise.allSettled(monitoringPromises);
// Process monitoring results
monitoringResults.forEach((result) => {
if (result.status === 'fulfilled' && !result.value.error) {
console.log(`Operation ${result.value.id} completed in ${result.value.duration}s`);
}
});
}
// 3. Generate summary
console.log("Batch operation summary:");
console.log(`- Successful: ${results.successful.length}`);
console.log(`- Failed: ${results.failed.length}`);
console.log(`- In Progress: ${results.in_progress.length}`);
if (results.failed.length > 0) {
console.log("Failed operations:");
results.failed.forEach(failure => {
console.log(` - ${failure.id}: ${failure.error}`);
});
}
return results;
}
// Usage example
const operations: BatchOperation[] = [
{
id: "meeting-1",
meeting_url: "https://meet.google.com/abc-def-ghi",
bot_name: "Batch Bot 1",
expected_duration: 3600
},
{
id: "meeting-2",
meeting_url: "https://meet.google.com/jkl-mno-pqr",
bot_name: "Batch Bot 2",
expected_duration: 1800
}
];
batchBotOperations(operations).then(summary => {
console.log("Batch operations completed:", summary);
});Webhook Integration with Event Processing
Advanced webhook handling and event processing:
import { createBaasClient } from "@meeting-baas/sdk";
import express from 'express';
const app = express();
app.use(express.json());
const client = createBaasClient({
api_key: "your-api-key"
});
// Webhook event handler
app.post('/webhooks/meeting-baas', async (req, res) => {
const { event_type, bot_id, data } = req.body;
try {
switch (event_type) {
case 'bot_joined':
console.log(`Bot ${bot_id} joined meeting`);
// Update UI, send notifications, etc.
break;
case 'bot_left':
console.log(`Bot ${bot_id} left meeting`);
// Get final meeting data
const meetingDataResult = await client.getMeetingData({
bot_id: bot_id,
include_transcripts: true
});
if (meetingDataResult.success) {
const meetingData = meetingDataResult.data;
// Process meeting data
await processMeetingData(meetingData);
// Clean up bot data
await client.deleteBotData({ uuid: bot_id });
}
break;
case 'transcription_completed':
console.log(`Transcription completed for bot ${bot_id}`);
// Process transcripts, update database, etc.
break;
case 'error':
console.error(`Error for bot ${bot_id}:`, data.error);
// Handle errors, retry logic, etc.
break;
default:
console.log(`Unknown event type: ${event_type}`);
}
res.status(200).json({ success: true });
} catch (error) {
console.error('Webhook processing error:', error);
res.status(500).json({ success: false, error: error.message });
}
});
async function processMeetingData(meetingData: any) {
// Process meeting data based on your application needs
console.log(`Processing meeting data: ${meetingData.duration}s duration`);
if (meetingData.mp4) {
console.log(`Recording available at: ${meetingData.mp4}`);
}
if (meetingData.bot_data.transcripts.length > 0) {
console.log(`Found ${meetingData.bot_data.transcripts.length} transcripts`);
// Process transcripts
meetingData.bot_data.transcripts.forEach((transcript: any) => {
console.log(`Speaker: ${transcript.speaker}, Words: ${transcript.words.length}`);
});
}
}
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});Error Recovery and Retry Logic
Advanced error handling with retry logic:
import { createBaasClient } from "@meeting-baas/sdk";
const client = createBaasClient({
api_key: "your-api-key",
timeout: 60000
});
interface RetryConfig {
maxAttempts: number;
baseDelay: number;
maxDelay: number;
backoffMultiplier: number;
}
async function retryOperation<T>(
operation: () => Promise<T>,
config: RetryConfig = {
maxAttempts: 3,
baseDelay: 1000,
maxDelay: 10000,
backoffMultiplier: 2
}
): Promise<T> {
for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {
try {
return await operation();
} catch (error) {
if (attempt === config.maxAttempts) {
// throw error if last attempt
throw error;
}
// Calculate delay with exponential backoff
const delay = Math.min(
config.baseDelay * Math.pow(config.backoffMultiplier, attempt - 1),
config.maxDelay
);
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
async function robustBotOperation() {
try {
// Join meeting with retry logic
const joinResult = await retryOperation(async () => {
const result = await client.joinMeeting({
meeting_url: "https://meet.google.com/abc-def-ghi",
bot_name: "Robust Bot",
reserved: false
});
if (!result.success) {
throw new Error(result.error.message);
}
return result;
});
console.log("Bot joined successfully:", joinResult.data.bot_id);
// Monitor with retry logic
const meetingData = await retryOperation(async () => {
const result = await client.getMeetingData({
bot_id: joinResult.data.bot_id,
include_transcripts: true
});
if (!result.success) {
throw new Error(result.error.message);
}
if (result.data.duration === 0) {
throw new Error("Meeting not yet completed");
}
return result;
}, {
maxAttempts: 20, // More attempts for monitoring
baseDelay: 5000, // 5 second base delay
maxDelay: 30000, // Max 30 second delay
backoffMultiplier: 1.5
});
console.log("Meeting completed:", meetingData.data.duration);
} catch (error) {
console.error("Operation failed after all retries:", error);
}
}