UNPKG

@akson/chatsuite-sdk

Version:

Production-ready TypeScript SDK for ChatSuite - WhatsApp automation with built-in session management, message queuing, webhook server, and database sync

366 lines (301 loc) โ€ข 11.3 kB
/** * Webhook Server Example * * Demonstrates the built-in webhook server features: * - Event handling and routing * - Signature verification * - Rate limiting and security * - Integration with Express apps * * Run: npx ts-node examples/webhook-server.ts */ import { WebhookServer } from '../src/index'; async function webhookServerExample() { console.log('๐Ÿ”— Webhook Server Example'); // Create webhook server with comprehensive configuration const webhookServer = new WebhookServer({ port: 3001, path: '/webhook', secret: 'your-webhook-secret-key', // For signature verification enableLogging: true, // CORS configuration cors: { origin: ['http://localhost:3000', 'https://yourdomain.com'], methods: ['GET', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'X-Signature'] }, // Rate limiting rateLimit: { windowMs: 60000, // 1 minute max: 100 // 100 requests per minute per IP }, // Event handlers handlers: { // WhatsApp message events 'messages.upsert': async (data) => { console.log('๐Ÿ“จ New messages received:', data.messages?.length || 0); for (const message of data.messages || []) { await handleIncomingMessage(message); } }, 'messages.update': async (data) => { console.log('๐Ÿ“ Messages updated:', data.messages?.length || 0); for (const message of data.messages || []) { await handleMessageUpdate(message); } }, 'message-receipt.update': async (data) => { console.log('โœ… Message receipts updated:', data.length || 0); for (const receipt of data || []) { await handleMessageReceipt(receipt); } }, // Connection events 'connection.update': async (data) => { console.log('๐Ÿ”— Connection update:', data); await handleConnectionUpdate(data); }, // Presence events 'presence.update': async (data) => { console.log('๐Ÿ‘๏ธ Presence update:', data); await handlePresenceUpdate(data); }, // Chat events 'chats.upsert': async (data) => { console.log('๐Ÿ’ฌ Chats updated:', data.length || 0); for (const chat of data || []) { await handleChatUpdate(chat); } }, 'chats.update': async (data) => { console.log('๐Ÿ’ฌ Chats modified:', data.length || 0); }, 'chats.delete': async (data) => { console.log('๐Ÿ—‘๏ธ Chats deleted:', data.length || 0); }, // Contact events 'contacts.upsert': async (data) => { console.log('๐Ÿ‘ฅ Contacts updated:', data.length || 0); for (const contact of data || []) { await handleContactUpdate(contact); } }, // Group events 'groups.upsert': async (data) => { console.log('๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Groups updated:', data.length || 0); }, 'groups.update': async (data) => { console.log('๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Groups modified:', data.length || 0); }, // Credentials update 'creds.update': async (data) => { console.log('๐Ÿ”‘ Credentials updated'); await handleCredsUpdate(data); } } }); // Event monitoring webhookServer.on('server:start', (port) => { console.log(`๐Ÿš€ Webhook server started on port ${port}`); }); webhookServer.on('server:stop', () => { console.log('๐Ÿ›‘ Webhook server stopped'); }); webhookServer.on('server:error', (error) => { console.error('โŒ Server error:', error); }); webhookServer.on('webhook:received', (event, data) => { console.log(`๐ŸŽฃ Webhook received: ${event}`); }); webhookServer.on('webhook:processed', (event, data, result) => { console.log(`โœ… Webhook processed: ${event}`); }); webhookServer.on('webhook:error', (event, data, error) => { console.error(`โŒ Webhook error in ${event}:`, error.message); }); // Start the webhook server console.log('Starting webhook server...'); await webhookServer.start(); // Add dynamic handlers console.log('\n๐Ÿ”ง Adding dynamic handlers...'); webhookServer.addHandler('custom.event', async (data) => { console.log('๐Ÿ”ง Custom event received:', data); }); webhookServer.addHandler('business.order', async (data) => { console.log('๐Ÿ›’ Business order received:', data); await handleBusinessOrder(data); }); webhookServer.addHandler('payment.status', async (data) => { console.log('๐Ÿ’ณ Payment status update:', data); await handlePaymentUpdate(data); }); // Monitor webhook statistics const statsInterval = setInterval(() => { const stats = webhookServer.getStats(); console.log('\n๐Ÿ“Š Webhook Statistics:'); console.log(` Total Requests: ${stats.totalRequests}`); console.log(` Successful: ${stats.successfulRequests}`); console.log(` Failed: ${stats.failedRequests}`); console.log(` Success Rate: ${stats.totalRequests > 0 ? (stats.successfulRequests / stats.totalRequests * 100).toFixed(1) : 0}%`); console.log(` Avg Response Time: ${stats.averageResponseTime.toFixed(2)}ms`); console.log(` Uptime: ${(stats.uptime / 60).toFixed(1)} minutes`); }, 30000); // Every 30 seconds // Simulate webhook events for testing console.log('\n๐Ÿงช Simulating webhook events for testing...'); const eventSimulator = setInterval(() => { const events = [ { event: 'messages.upsert', data: { messages: [{ key: { remoteJid: '+1234567890@c.us', id: 'test_' + Date.now() }, message: { conversation: 'Hello from webhook simulator!' }, messageTimestamp: Date.now() }] } }, { event: 'connection.update', data: { connection: Math.random() > 0.5 ? 'open' : 'connecting', lastDisconnect: null } }, { event: 'custom.event', data: { customData: 'This is a custom event', timestamp: new Date().toISOString() } } ]; const randomEvent = events[Math.floor(Math.random() * events.length)]; // Simulate webhook call (normally this would come from WhatsApp) console.log(`๐Ÿ“ก Simulating: ${randomEvent.event}`); // You could use curl or fetch to test the webhook endpoint: // fetch('http://localhost:3001/webhook', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify(randomEvent) // }); }, 15000); // Every 15 seconds console.log('\n๐ŸŽฎ Webhook server demo running!'); console.log('Features demonstrated:'); console.log(' โœ… Event handling and routing'); console.log(' โœ… Signature verification'); console.log(' โœ… CORS and rate limiting'); console.log(' โœ… Real-time statistics'); console.log(' โœ… Dynamic handler management'); console.log(' โœ… Health monitoring'); console.log('\nEndpoints available:'); console.log(' ๐Ÿ“ก POST http://localhost:3001/webhook - Main webhook endpoint'); console.log(' ๐Ÿฅ GET http://localhost:3001/webhook/health - Health check'); console.log('\nTest with curl:'); console.log(' curl -X POST http://localhost:3001/webhook \\'); console.log(' -H "Content-Type: application/json" \\'); console.log(' -d \'{"event":"test","data":{"message":"hello"}}\''); console.log('\nPress Ctrl+C to stop...'); // Graceful shutdown process.on('SIGINT', async () => { console.log('\n๐Ÿ›‘ Shutting down webhook server...'); clearInterval(statsInterval); clearInterval(eventSimulator); await webhookServer.stop(); console.log('โœ… Webhook server stopped'); process.exit(0); }); } // Event handler functions async function handleIncomingMessage(message: any) { const text = message.message?.conversation; const from = message.key?.remoteJid; if (text && from) { console.log(`๐Ÿ’ฌ Message from ${from}: ${text}`); // Process different message types if (text.toLowerCase().includes('hello')) { console.log('๐Ÿ‘‹ Detected greeting message'); } else if (text.toLowerCase().includes('help')) { console.log('โ“ Detected help request'); } else if (text.toLowerCase().includes('order')) { console.log('๐Ÿ›’ Detected order inquiry'); } } // Handle media messages if (message.message?.imageMessage) { console.log('๐Ÿ–ผ๏ธ Received image message'); } else if (message.message?.videoMessage) { console.log('๐ŸŽฅ Received video message'); } else if (message.message?.documentMessage) { console.log('๐Ÿ“„ Received document message'); } } async function handleMessageUpdate(message: any) { const messageId = message.key?.id; const status = message.update?.status; if (messageId && status) { console.log(`๐Ÿ“ Message ${messageId} status: ${status}`); } } async function handleMessageReceipt(receipt: any) { const messageId = receipt.key?.id; const receiptType = receipt.receipt?.receiptTimestamp ? 'read' : 'delivered'; console.log(`โœ… Message ${messageId} ${receiptType}`); } async function handleConnectionUpdate(data: any) { const connection = data.connection; const lastDisconnect = data.lastDisconnect; switch (connection) { case 'open': console.log('๐ŸŸข WhatsApp connected successfully'); break; case 'close': console.log('๐Ÿ”ด WhatsApp connection closed'); if (lastDisconnect?.error) { console.log('โŒ Disconnect reason:', lastDisconnect.error); } break; case 'connecting': console.log('๐ŸŸก WhatsApp connecting...'); break; } } async function handlePresenceUpdate(data: any) { const jid = data.id; const presences = data.presences; for (const [participantJid, presence] of Object.entries(presences || {})) { const status = (presence as any).lastKnownPresence; console.log(`๐Ÿ‘๏ธ ${participantJid} is ${status}`); } } async function handleChatUpdate(chat: any) { const chatId = chat.id; const name = chat.name; const unreadCount = chat.unreadCount; console.log(`๐Ÿ’ฌ Chat ${name || chatId}: ${unreadCount || 0} unread`); } async function handleContactUpdate(contact: any) { const jid = contact.id; const name = contact.name || contact.pushName; console.log(`๐Ÿ‘ฅ Contact updated: ${name || jid}`); } async function handleCredsUpdate(creds: any) { console.log('๐Ÿ”‘ Saving updated credentials...'); // In a real app, you would save these credentials } async function handleBusinessOrder(data: any) { console.log('๐Ÿ›’ Processing business order:', data); // Process business order logic here } async function handlePaymentUpdate(data: any) { console.log('๐Ÿ’ณ Processing payment update:', data); // Process payment update logic here } // Handle errors process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); }); // Run the example if (require.main === module) { webhookServerExample().catch(console.error); } export { webhookServerExample };