@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
text/typescript
/**
* 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 };