π¨ MultiChannelAlert - Kien Nguyen Support
π― The Ultimate Multi-Channel Alert & Notification System
Send alerts to 15+ platforms simultaneously with zero dependencies!
π± Supported Platforms
A comprehensive MultiChannelAlert system and utilities package for logging, notifications, and webhook management with enhanced formatting and smart routing.
Installation
npm install kien-nguyen-support
π Why MultiChannelAlert?
π Before
Multiple libraries, complex setup
telegram-bot-api
+ @slack/web-api
+ discord.js
+ nodemailer
+ whatsapp-web.js
= 50+ dependencies
|
β¨ After
One simple import, zero dependencies
const { MultiChannelAlert }
= require('kien-nguyen-support')
// Send to 15+ platforms
multiAlert.error('Alert!')
= ZERO dependencies
|
π¨ MultiChannelAlert - Core Features
π― ONE API β 15+ PLATFORMS
"Write once, alert everywhere!"
π Key Highlights
- π¨ MultiChannelAlert: Send alerts to 15+ platforms simultaneously (Telegram, Slack, Mattermost, Discord, Email, WhatsApp, Zalo, LINE, Viber, Skype, WeChat, RocketChat, Firebase, N8n, Messenger)
- π― Logger-Style API: Clean constructor pattern with
.error(), .info(), .warn(), .success() methods
- π Smart ID Extraction: Automatically extract and display IDs in copyable code blocks
- π Enhanced Formatting: Rich formatting with emojis, proper JSON display, platform-specific markdown, and code blocks for curl commands
- βοΈ Conditional Channels: Initialize only channels with available configurations
- π Dynamic Management: Add/remove channels at runtime with graceful error handling
- ποΈ Individual StrictMode: Filter data per channel with
strictMode parameter for sensitive data protection
- π Configuration Inheritance: Channel-specific settings override global configurations
- π¨ Cross-Platform Formatting: Consistent rich formatting across Telegram (Markdown), Mattermost (Markdown), Slack (Blocks), Discord (Embeds)
β‘ Performance & Optimization
- Zero Dependencies: No external runtime dependencies - uses only Node.js built-ins
- 85% Smaller Package: Reduced from ~585KB to ~85KB by replacing axios & moment.js
- Native HTTP Client: Custom implementation with axios-compatible API
- Custom DateTime Utils: Native Date formatting without external libraries
- Fast Installation: No dependency resolution or security vulnerabilities
- Production Ready: Lightweight, secure, and maintainable
π± Live Demo Screenshots
Demo with Telegram and Mattermost
Real-time alerts with rich formatting, ID extraction, and smart routing:
Live examples showing enhanced formatting, automatic ID extraction, and multi-channel broadcasting
π― 4 Core Features
- π¨ MultiChannelAlert System: Send notifications to 15+ platforms simultaneously - Telegram, Slack, Mattermost, Discord, Email, WhatsApp, Zalo, LINE, Viber, Skype, WeChat, RocketChat, Firebase, N8n, Messenger
- π Third-Party Log: Save HTTP request/response logs and curl commands with provider-specific formatting
- π Telegram Webhook: Production webhook management with fallback and auto-recovery
- π― Smart Routing: Automatic thread/channel routing based on service and environment using nested object access
β‘ 30-Second Demo
const multiAlert = new MultiChannelAlert({
channels: [
{ type: 'telegram', config: { } },
{ type: 'slack', config: { } },
{ type: 'discord', config: { } },
{ type: 'email', config: { } },
]
})
multiAlert.error('Payment system down!', {
userId: 'U123456',
amount: 999.99
})
π₯ 15+ Platforms β’ Zero Dependencies β’ One Simple API π₯
ποΈ Advanced Data Filtering & Formatting
π StrictMode Data Filtering
Control exactly which data fields are sent to each platform:
const multiAlert = new MultiChannelAlert({
channels: [
{
type: 'telegram',
config: {
botToken: 'your-token',
chatId: 'your-chat-id',
strictMode: true
}
},
{
type: 'mattermost',
config: {
apiUrl: 'your-api-url',
token: 'your-token',
channelId: 'your-channel-id'
}
}
],
specific: [
{ key: 'user', title: 'π€ User', markdown: true },
{ key: 'method', title: 'π¨ Method', markdown: true },
{ key: 'status', title: 'π Status', markdown: true },
{ key: 'error_code', title: 'π΄ Error Code', markdown: true },
{ key: 'curl', title: 'π» cURL Command', markdown: true }
],
strictMode: false
})
const alertData = {
user: 'john_doe',
method: 'POST',
status: 500,
error_code: 'DB_CONNECTION_FAILED',
curl: 'curl -X POST https://api.example.com/users',
internal_debug: 'This sensitive data',
server_logs: 'Internal server information'
}
await multiAlert.error(alertData)
π¨ Enhanced Message Formatting
Rich formatting with platform-specific optimizations:
Telegram Output:
**π€ User:**
john_doe
**π¨ Method:**
POST
**π» cURL Command:**
curl -X POST https://api.example.com/users
Mattermost Output:
------------------------
[From Mattermost Bot Alert]
π¨ Environment: PRODUCTION
**π€ User:** `john_doe`
**π¨ Method:** `POST`
**π» cURL Command:**
```bash
curl -X POST https://api.example.com/users
### π§ Individual Component StrictMode
Use individual alert components with their own filtering:
```javascript
// Individual components with their own strictMode
const telegramAlert = new TelegramAlert({
botToken: 'your-token',
chatId: 'your-chat-id',
strictMode: true // This component will filter data
})
const slackAlert = new SlackAlert({
webhookUrl: 'your-webhook-url'
// No strictMode - sends all data
})
// Same data, different filtering per component
const data = { user: 'john', secret: 'hidden', method: 'POST' }
const specific = [{ key: 'user', title: 'π€ User' }, { key: 'method', title: 'π¨ Method' }]
await telegramAlert.error(data) // Only sends: user, method (if specific is provided)
await slackAlert.error(data) // Sends all: user, secret, method
Quick Start
const {
MultiChannelAlert,
TelegramAlert,
SlackAlert,
saveProviderLog,
createTelegramWebhookClient
} = require('kien-nguyen-support')
const multiAlert = new MultiChannelAlert({
channels: [
{
type: 'telegram',
config: {
botToken: process.env.TELEGRAM_BOT_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID,
service: 'hotel'
}
},
{
type: 'slack',
config: {
webhookUrl: process.env.SLACK_WEBHOOK_URL,
service: 'hotel'
}
}
],
environment: 'PRODUCTION'
})
await multiAlert.error({
user_id: '123',
booking_id: 'BK456',
error_code: 'PAYMENT_FAILED',
message: 'Payment processing failed'
})
const telegram = new TelegramAlert({
botToken: process.env.TELEGRAM_BOT_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID,
service: 'hotel'
})
await telegram.error({ error_message: 'Hello from Telegram!' })
await saveProviderLog({
action: 'search',
req: requestData,
res: responseData,
code: 'EXPEDIA',
name: 'search-hotels'
})
const webhook = createTelegramWebhookClient({ })
await webhook.setWebhook()
Feature 1: Multi-Channel Alerts π
Send alerts to multiple platforms simultaneously with a single command.
MultiChannelAlert Class (NEW)
const { MultiChannelAlert } = require('kien-nguyen-support')
const multiAlert = new MultiChannelAlert({
channels: [
{
type: 'telegram',
config: {
botToken: 'your-bot-token',
chatId: 'your-chat-id',
service: 'hotel'
}
},
{
type: 'mattermost',
config: {
url: 'https://mattermost.example.com',
token: 'access-token',
chatId: 'channel-id',
service: 'hotel'
}
},
{
type: 'slack',
config: {
webhookUrl: 'https://hooks.slack.com/...',
service: 'hotel'
}
},
{
type: 'email',
config: {
host: 'smtp.gmail.com',
port: 587,
auth: {
user: 'alerts@company.com',
pass: 'app-password'
},
from: 'alerts@company.com',
to: 'team@company.com',
service: 'hotel'
}
}
],
service: 'hotel',
environment: 'PRODUCTION',
failSilently: true
})
await multiAlert.error({
user_id: '123',
booking_id: 'BK456',
error_code: 'PAYMENT_FAILED',
message: 'Payment processing failed',
amount: 150,
currency: 'USD'
})
await multiAlert.info({
deployment: 'v2.0.0',
status: 'success',
message: 'Deployment completed successfully'
})
await multiAlert.warn({
cpu_usage: '85%',
memory_usage: '78%',
message: 'High resource usage detected'
})
await multiAlert.success({
payment_id: 'PAY123',
amount: 150,
message: 'Payment processed successfully'
})
π― Configuration Inheritance & Data Filtering (NEW)
MultiChannelAlert now supports advanced configuration inheritance and data filtering:
const multiAlert = new MultiChannelAlert({
service: 'flight',
environment: 'PRODUCTION',
beauty: true,
specific: [
{ field: 'error', markdown: false },
{ field: 'message', markdown: true }
],
strictMode: true,
channels: [
{
type: 'telegram',
config: {
botToken: 'bot-token',
chatId: 'chat-id',
specific: [
{ field: 'error', markdown: false },
{ field: 'message', markdown: true },
{ field: 'timestamp', markdown: false }
]
}
},
{
type: 'slack',
config: {
webhookUrl: 'webhook-url'
}
}
]
})
const alertData = {
error: 'Flight API timeout',
message: 'Booking system down',
timestamp: '2024-01-01T10:00:00Z',
userId: 'user123',
sessionId: 'session456',
metadata: { extra: 'info' }
}
await multiAlert.error(alertData)
Configuration Inheritance Rules:
- Channel config overrides Global config overrides Default values
strictMode: true β Only fields in specific[] are sent
strictMode: false β All fields are sent regardless of specific[]
- Channel-level
specific[] overrides global specific[]
Benefits:
- π― Selective Logging: Only log relevant fields per channel
- π Data Privacy: Filter sensitive fields from certain channels
- β‘ Performance: Reduce message size by filtering unnecessary data
- ποΈ Flexibility: Different field sets per channel type
Conditional Channel Initialization
Only initialize channels that have available configuration:
const channels = []
if (process.env.TELEGRAM_BOT_TOKEN && process.env.TELEGRAM_CHAT_ID) {
channels.push({
type: 'telegram',
config: {
botToken: process.env.TELEGRAM_BOT_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID,
service: 'hotel'
}
})
}
if (process.env.SLACK_WEBHOOK_URL) {
channels.push({
type: 'slack',
config: {
webhookUrl: process.env.SLACK_WEBHOOK_URL,
service: 'hotel'
}
})
}
if (process.env.MATTERMOST_URL && process.env.MATTERMOST_TOKEN) {
channels.push({
type: 'mattermost',
config: {
url: process.env.MATTERMOST_URL,
token: process.env.MATTERMOST_TOKEN,
chatId: process.env.MATTERMOST_CHAT_ID,
service: 'hotel'
}
})
}
const multiAlert = new MultiChannelAlert({
channels,
service: 'hotel',
environment: 'PRODUCTION'
})
const result = await multiAlert.error({ message: 'Test error' })
console.log(`Sent to ${result.summary.successful}/${result.summary.total} channels`)
π― Individual Component StrictMode (NEW)
Each alert component now supports individual strictMode for data filtering:
const { TelegramAlert, SlackAlert, MattermostAlert } = require('kien-nguyen-support')
const telegramAlert = new TelegramAlert({
botToken: 'your-bot-token',
chatId: 'your-chat-id',
specific: [
{ field: 'error', markdown: false },
{ field: 'message', markdown: true }
],
strictMode: true
})
const slackAlert = new SlackAlert({
webhookUrl: 'your-webhook-url',
specific: [
{ key: 'error', title: 'Error' },
{ key: 'user_id', title: 'User ID' }
],
strictMode: true
})
const mattermostAlert = new MattermostAlert({
apiUrl: 'your-mattermost-api-url',
token: 'your-token',
channelId: 'your-channel-id',
specific: [
{ field: 'error' },
{ field: 'message' },
{ field: 'user_id' }
],
strictMode: true
})
const alertData = {
error: 'System failure',
message: 'Database error',
user_id: 'user_123',
session_id: 'session_456',
ip_address: '192.168.1.1',
metadata: { extra: 'info' }
}
await telegramAlert.error(alertData)
await slackAlert.error(alertData)
await mattermostAlert.error(alertData)
Benefits of Individual StrictMode:
- π― Selective Data: Filter data without MultiChannelAlert
- π Privacy Control: Remove sensitive fields per component
- β‘ Performance: Reduce message payload size
- ποΈ Flexibility: Different filtering per alert type
Individual Alert Classes
You can also use individual alert classes directly:
1. TelegramAlert
Setup Requirements:
-
Create a Telegram Bot:
- Message @BotFather on Telegram
- Send
/newbot and follow instructions
- Get your
botToken
-
Get Chat ID:
- Add your bot to a group/channel
- Send a message to the group
- Visit
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates
- Find
chat.id in the response
const { TelegramAlert } = require('kien-nguyen-support')
const telegram = new TelegramAlert({
botToken: 'your-bot-token',
chatId: 'your-chat-id',
service: 'hotel',
environment: 'PRODUCTION',
messageThreadIds: {
'hotel.error.all': 30,
'hotel.info.all': 31,
general: 9
}
})
await telegram.error({ message: 'Error occurred' })
2. SlackAlert
Setup Requirements:
const { SlackAlert } = require('kien-nguyen-support')
const slack = new SlackAlert({
webhookUrl: 'https://hooks.slack.com/services/...',
service: 'hotel',
environment: 'PRODUCTION',
channels: {
'hotel.error.all': '#hotel-errors',
'hotel.info.all': '#hotel-info',
general: '#general'
}
})
await slack.error({ message: 'Error occurred' })
3. MattermostAlert
Setup Requirements:
const { MattermostAlert } = require('kien-nguyen-support')
const mattermost = new MattermostAlert({
url: 'https://your-mattermost.com',
token: 'your-access-token',
chatId: 'channel-id-or-name',
service: 'hotel',
environment: 'PRODUCTION'
})
await mattermost.error({ message: 'Error occurred' })
4. EmailAlert
Setup Requirements:
- SMTP Configuration (Gmail example):
- Enable 2FA on Gmail
- Generate App Password: Account β Security β App passwords
- Use app password (not your regular password)
const { EmailAlert } = require('kien-nguyen-support')
const email = new EmailAlert({
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: 'your-email@gmail.com',
pass: 'your-app-password'
},
from: 'alerts@company.com',
to: 'team@company.com',
service: 'hotel',
environment: 'PRODUCTION'
})
await email.error({ message: 'Error occurred' })
5. DiscordAlert
Setup Requirements:
- Create Discord Webhook:
- Go to Discord channel β Settings β Integrations
- Click "Create Webhook"
- Copy webhook URL
const { DiscordAlert } = require('kien-nguyen-support')
const discord = new DiscordAlert({
webhookUrl: 'https://discord.com/api/webhooks/...',
service: 'hotel',
environment: 'PRODUCTION'
})
await discord.error({ message: 'Error occurred' })
6. ZaloAlert
Setup Requirements:
const { ZaloAlert } = require('kien-nguyen-support')
const zalo = new ZaloAlert({
accessToken: 'your-oa-access-token',
userId: 'user-id',
service: 'hotel',
environment: 'PRODUCTION'
})
await zalo.error({ message: 'Error occurred' })
7. MessengerAlert
Setup Requirements:
-
Create Facebook App:
-
Get Page Access Token:
- Go to Messenger β Settings
- Generate page access token
- Get recipient PSID from webhook events
const { MessengerAlert } = require('kien-nguyen-support')
const messenger = new MessengerAlert({
pageAccessToken: 'your-page-access-token',
recipientId: 'user-psid',
service: 'hotel',
environment: 'PRODUCTION'
})
await messenger.error({ message: 'Error occurred' })
8. N8nAlert
Setup Requirements:
- Create N8n Webhook:
- In N8n workflow, add "Webhook" node
- Set HTTP Method to POST
- Copy the webhook URL
const { N8nAlert } = require('kien-nguyen-support')
const n8n = new N8nAlert({
webhookUrl: 'https://your-n8n.com/webhook/...',
service: 'hotel',
environment: 'PRODUCTION'
})
await n8n.error({ message: 'Error occurred' })
Feature 2: Third-Party Log (HTTP Request Logging)
Save API request/response logs and curl commands to organized files:
const { saveProviderLog, saveProviderCurl } = require('kien-nguyen-support')
await saveProviderLog({
action: 'search',
req: requestData,
res: responseData,
code: 'EXPEDIA',
name: 'search-hotels'
})
await saveProviderCurl({
name: 'search-hotels',
request: {
method: 'POST',
url: 'https://api.expedia.com/search',
headers: { 'Content-Type': 'application/json' },
body: { destination: 'Bangkok' }
},
code: 'EXPEDIA',
action: 'search'
})
Files are automatically saved to:
- Request/Response:
../logs/logs_YYYY-MM-DD/TIMESTAMP_CODE_NAME_ACTION_req.json
- Curl commands:
../curl_logs/logs_YYYY-MM-DD/TIMESTAMP_CODE_NAME_ACTION_curl.txt
Feature 3: Telegram Bot (Legacy - Backward Compatibility)
TelegramClient Class (Recommended)
Pre-configured client with smart thread routing:
const { TelegramClient } = require('kien-nguyen-support')
const telegram = new TelegramClient({
botToken: process.env.TELEGRAM_BOT_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID,
service: 'hotel',
environment: 'PROD',
messageThreadIds: {
general: 17,
hotel: {
system: {
all: 17,
search: 19,
offer_search: 19,
prebook: 21,
book: 23,
cancel: 25
},
third_party: {
all: 28,
search: 30,
prebook: 32,
book: 34,
cancel: 36
}
},
flight: {
system: {
search: 5038,
'confirm-tax': 5039,
'generate-pnr': 5042
},
third_party: {
search: 3561,
'confirm-tax': 5050
}
},
flight: {
system: {
search: 5038,
'confirm-tax': 5039,
'generate-pnr': 5042
},
third_party: {
search: 3561,
'confirm-tax': 5050
}
}
},
disableNotification: false,
timeout: 10000
})
await telegram.sendMessage({
error_message: 'Hello World!'
})
await telegram.sendErrorAlert({
error_message: 'Failed to book hotel',
error_code: 'BOOKING_FAILED',
type: 'third_party',
metric: 'book',
user_email: 'user@example.com',
supplier: {
code: 'EXPEDIA',
id: 123,
source_id: 'EXP001'
},
request_metadata: {
bookingId: 'ABC123',
search_id: 'd8e2048ba1974f568a807532752e452f',
trace_id: 'trace-12345',
log_id: '63b5c9faf56fc04fdf2509b3874cb6d4'
},
error_stack: error.stack,
metadata: { additional: 'data' }
})
Factory Function (Alternative)
const { createTelegramClient } = require('kien-nguyen-support')
const telegramClient = createTelegramClient({
botToken: process.env.TELEGRAM_BOT_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID,
messageThreadIds: { }
})
await telegramClient.sendMessage({ error_message: 'Hello!' })
})
π― Smart Thread Routing (v2.2.0)
The new nested object structure provides better organization and type safety:
messageThreadIds: {
'hotel_system_search': 19,
'hotel_system_book': 23,
'hotel_third_party_search': 30
}
messageThreadIds: {
general: 17,
hotel: {
system: {
all: 17,
search: 19,
book: 23
},
third_party: {
all: 28,
search: 30,
book: 34
}
},
flight: {
system: { search: 5038 },
third_party: { search: 3561 }
}
}
Routing Priority:
messageThreadIds.{service}.{type}.{metric} - Most specific
messageThreadIds.{service}.{type}.all - Service + type fallback
messageThreadIds.{service}.{type}.general - Service + type general
messageThreadIds.general - Global fallback
Example: service: 'hotel', type: 'system', metric: 'search'
β Looks for messageThreadIds.hotel.system.search = 19
Feature 4: Telegram Webhook (Production Setup)
Manage webhooks for production deployment:
const { createTelegramWebhookClient } = require('kien-nguyen-support')
const webhookClient = createTelegramWebhookClient({
botToken: process.env.TELEGRAM_BOT_TOKEN,
webhookUrl: process.env.WEBHOOK_URL,
secretToken: process.env.WEBHOOK_SECRET_TOKEN,
allowedUpdates: ['message', 'callback_query'],
maxConnections: 100,
timeout: 10000
})
await webhookClient.setWebhook()
const info = await webhookClient.getWebhookInfo()
console.log('Webhook status:', info.url)
await webhookClient.deleteWebhook()
app.post('/telegram-webhook', (req, res) => {
const secretToken = req.headers['x-telegram-bot-api-secret-token']
if (!webhookClient.verifyRequest(secretToken)) {
return res.status(401).send('Unauthorized')
}
const update = webhookClient.parseUpdate(req.body)
if (update.message) {
console.log('Received message:', update.message.text)
}
res.sendStatus(200)
})
Smart Thread Routing
Configure automatic message routing to specific Telegram threads:
const messageThreadIds = {
general: 9,
hotel_system_search: 19,
hotel_system_book: 23,
hotel_third_party_search: 30,
hotel_third_party_book: 34,
flight_system_search: 41,
flight_system_book: 43,
tour_system_search: 51,
transfer_system_book: 73
}
Routing Logic: {product}_{type}_{metric} β Falls back to general
Examples:
hotel + third_party + book β hotel_third_party_book (34)
flight + system + search β flight_system_search (41)
- Unknown combination β
general (9)
Usage Patterns
Pattern 1: Multi-Channel Alert System (Recommended)
Create a shared multi-channel client for your entire project:
const { MultiChannelAlert } = require('kien-nguyen-support')
const channels = []
if (process.env.TELEGRAM_BOT_TOKEN && process.env.TELEGRAM_CHAT_ID) {
channels.push({
type: 'telegram',
config: {
botToken: process.env.TELEGRAM_BOT_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID,
service: 'hotel'
}
})
}
if (process.env.SLACK_WEBHOOK_URL) {
channels.push({
type: 'slack',
config: {
webhookUrl: process.env.SLACK_WEBHOOK_URL,
service: 'hotel'
}
})
}
if (process.env.MATTERMOST_URL && process.env.MATTERMOST_TOKEN) {
channels.push({
type: 'mattermost',
config: {
url: process.env.MATTERMOST_URL,
token: process.env.MATTERMOST_TOKEN,
chatId: process.env.MATTERMOST_CHAT_ID,
service: 'hotel'
}
})
}
const alertClient = new MultiChannelAlert({
channels,
service: 'hotel',
environment: process.env.NODE_ENV || 'STAGING',
failSilently: true
})
module.exports = alertClient
const alertClient = require('../config/alert-client')
async function bookHotel(hotelData) {
try {
const booking = await processHotelBooking(hotelData)
await alertClient.success({
booking_id: booking.id,
user_email: hotelData.userEmail,
amount: booking.amount,
currency: booking.currency,
message: `Hotel booking successful: ${booking.id}`
})
return booking
} catch (error) {
await alertClient.error({
error_code: 'BOOKING_FAILED',
message: error.message,
user_email: hotelData.userEmail,
booking_data: hotelData,
error_stack: error.stack
})
throw error
}
}
Pattern 2: Service-Specific Alert Clients
const { TelegramAlert, SlackAlert } = require('kien-nguyen-support')
const flightTelegram = new TelegramAlert({
botToken: process.env.TELEGRAM_BOT_TOKEN,
chatId: process.env.FLIGHT_CHAT_ID,
service: 'flight',
environment: 'PRODUCTION',
messageThreadIds: {
'flight.error.all': 31,
'flight.info.all': 33,
general: 9
}
})
const flightSlack = new SlackAlert({
webhookUrl: process.env.FLIGHT_SLACK_WEBHOOK,
service: 'flight',
channels: {
'flight.error.all': '#flight-errors',
'flight.info.all': '#flight-info'
}
})
async function searchFlights(searchData) {
try {
await flightTelegram.info({
action: 'search_start',
message: 'Flight search initiated',
search_data: searchData
})
const results = await performFlightSearch(searchData)
await flightSlack.success({
action: 'search_complete',
message: `Found ${results.length} flights`,
search_id: searchData.search_id,
results_count: results.length
})
return results
} catch (error) {
await Promise.allSettled([
flightTelegram.error({
error_code: 'SEARCH_FAILED',
message: error.message,
search_data: searchData
}),
flightSlack.error({
error_code: 'SEARCH_FAILED',
message: error.message,
search_data: searchData
})
])
throw error
}
}
π Enhanced Multi-Channel Message Format
With version 2.0.0, all alert channels now include:
Automatically extracts and displays IDs in copyable code blocks:
π **Search ID:**
d8e2048ba1974f568a807532752e452f
π **Trace ID:**
trace-12345-abcdef
π **Log ID:**
63b5c9faf56fc04fdf2509b3874cb6d4
Rich Formatting with Emojis
- π§ Environment:
PRODUCTION
- π Type:
third_party
- β Error Code:
BOOKING_FAILED
- π Message: Error details in code blocks
- π€ User: User information
- π’ Supplier: Supplier details
- π Request Data: Formatted JSON with proper indentation
- π Stack Trace: Limited to first 2 lines for readability
Example Enhanced Message Output
π§ Environment: `PRODUCTION`
π Type: `third_party`
β Error Code: `BOOKING_FAILED`
π Message:
Failed to book hotel room
π Search ID:
d8e2048ba1974f568a807532752e452f
π Request Data:
```json
{
"adults": 2,
"children": 0,
"departure_date": "2025-09-29",
"search_id": "d8e2048ba1974f568a807532752e452f"
}
π Stack Trace:
BookingError: Room not available
at bookRoom (/app/services/booking.js:145:12)
## π§ Troubleshooting & Best Practices
### β Common Issues
#### "message text is empty" Error (Telegram)
**Cause:** StrictMode filtering resulted in empty data or missing required fields.
**Solution:**
```javascript
// β Wrong: No matching fields in specific configuration
const specific = [
{ key: 'user_name', title: 'User' } // But data has 'user', not 'user_name'
]
const data = { user: 'john', method: 'POST' }
// β
Correct: Match field keys exactly
const specific = [
{ key: 'user', title: 'π€ User' }, // Matches data.user
{ key: 'method', title: 'π¨ Method' } // Matches data.method
]
No Data Filtering with StrictMode
Cause: strictMode is enabled but no specific configuration provided.
Solution:
const alert = new TelegramAlert({
botToken: 'token',
chatId: 'chat',
strictMode: true
})
const alert = new TelegramAlert({
botToken: 'token',
chatId: 'chat',
strictMode: true,
specific: [
{ key: 'user', title: 'π€ User' },
{ key: 'error_code', title: 'π΄ Error' }
]
})
π― Best Practices
1. Field Naming Consistency
const standardFields = [
{ key: 'user', title: 'π€ User' },
{ key: 'method', title: 'π¨ Method' },
{ key: 'status', title: 'π Status' },
{ key: 'error_code', title: 'π΄ Error Code' },
{ key: 'curl', title: 'π» cURL Command' }
]
2. Sensitive Data Protection
const productionAlert = new MultiChannelAlert({
channels: [
{
type: 'telegram',
config: {
botToken: process.env.TELEGRAM_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID,
strictMode: true
}
}
],
specific: [
{ key: 'user', title: 'π€ User' },
{ key: 'error_code', title: 'π΄ Error' }
]
})
3. Platform-Specific Formatting
const data = {
user: 'john_doe',
metadata: { session_id: '123', ip: '192.168.1.1' },
curl: 'curl -X POST https://api.com',
error_stack: 'Error\n at function()\n at ...'
}
4. Configuration Inheritance
const multiAlert = new MultiChannelAlert({
channels: [
{
type: 'telegram',
config: {
botToken: 'token',
chatId: 'chat-id',
specific: [
{ key: 'user', title: 'π€ User' },
{ key: 'error_code', title: 'π΄ Error' }
]
}
},
{
type: 'slack',
config: {
webhookUrl: 'webhook-url'
}
}
],
specific: [
{ key: 'user', title: 'π€ User' },
{ key: 'method', title: 'π¨ Method' },
{ key: 'status', title: 'π Status' }
],
strictMode: true
})
API Reference
Multi-Channel Alerts
new MultiChannelAlert(config)
Create a multi-channel alert instance.
Config Parameters:
channels (Array, required): Array of channel configurations
service (string, optional): Default service name ('hotel', 'flight', 'tour', 'transfer')
environment (string, optional): Default environment ('DEV', 'STAGING', 'PRODUCTION')
failSilently (boolean, optional): Don't throw errors if some channels fail (default: true)
Channel Configuration:
{
type: 'telegram',
config: {
botToken: 'token',
chatId: 'chat-id',
service: 'hotel',
environment: 'PROD'
}
}
Logger Methods
await multiAlert.error(data)
await multiAlert.info(data)
await multiAlert.warn(data)
await multiAlert.success(data)
Management Methods
multiAlert.getChannels()
multiAlert.getChannelCount()
multiAlert.hasChannel('telegram')
multiAlert.addChannel(config)
multiAlert.removeChannel('slack')
Response Format
{
success: true,
results: [
{
type: 'telegram',
success: true,
result: { }
},
{
type: 'slack',
success: false,
error: 'Webhook URL invalid'
}
],
errors: [
{
type: 'slack',
success: false,
error: 'Webhook URL invalid'
}
],
summary: {
total: 2,
successful: 1,
failed: 1
}
}
Individual Alert Classes
new TelegramAlert(config)
Required Config:
botToken (string): Telegram bot token from @BotFather
chatId (string): Chat/channel ID where messages will be sent
Optional Config:
service (string): Service name for routing ('hotel', 'flight', etc.)
environment (string): Environment context ('DEV', 'STAGING', 'PRODUCTION')
messageThreadIds (Object): Thread routing configuration
beauty (boolean): Enable rich formatting (default: true)
timeout (number): Request timeout in ms (default: 10000)
new SlackAlert(config)
Required Config:
webhookUrl (string): Slack webhook URL from app configuration
Optional Config:
channel (string): Override channel from webhook
service (string): Service name for routing
environment (string): Environment context
channels (Object): Channel routing configuration
beauty (boolean): Enable rich formatting (default: true)
new MattermostAlert(config)
Required Config:
url (string): Mattermost server URL
token (string): Personal access token
chatId (string): Channel ID or name
Optional Config:
service (string): Service name for routing
environment (string): Environment context
new EmailAlert(config)
Required Config:
host (string): SMTP server host
port (number): SMTP server port
auth.user (string): SMTP username
auth.pass (string): SMTP password/app password
from (string): From email address
to (string|Array): Recipient email address(es)
Optional Config:
secure (boolean): Use SSL/TLS (default: false for port 587)
service (string): Service name for subject line
environment (string): Environment context
Third-Party Logging
saveProviderLog(options)
Save HTTP request/response logs to organized files.
Parameters:
action (string): Action name (e.g., 'search', 'book')
req (Object|string): Request data (JSON object or XML string)
res (Object|string): Response data (JSON object or XML string)
code (string): Provider/supplier code (e.g., 'EXPEDIA')
name (string): Operation name (e.g., 'search-hotels')
saveProviderCurl(options)
Save curl command to file for debugging.
Parameters:
name (string): Operation name
request (Object): Request object with method, url, headers, body
code (string): Provider/supplier code
action (string, optional): Action name
TelegramClient Class
new TelegramClient(config)
Create a Telegram client instance.
Config Parameters:
botToken (string, required): Telegram bot token
chatId (string, required): Chat ID to send messages to
product (string, optional): Default product type ('hotel', 'flight', 'tour', 'transfer')
environment (string, optional): Default environment ('DEV', 'STAGING', 'PROD')
messageThreadIds (Object, optional): Thread routing configuration
disableNotification (boolean, optional): Disable notifications (default: false)
timeout (number, optional): Request timeout in ms (default: 5000)
telegram.sendMessage(options)
Send message using error-handler.js style options parameter.
Options Parameters:
error_message (string, required): Message text to send
type (string, optional): Alert type ('system', 'third_party')
metric (string, optional): Metric for thread routing
- All other fields are optional and used for metadata
telegram.sendErrorAlert(options)
Send error alert with automatic thread routing.
Options Parameters:
error_message (string, required): Error message
error_code (string, optional): Error code
type (string, optional): 'system' or 'third_party' (default: 'system')
metric (string, optional): Metric for thread routing (default: 'general')
user_email (string, optional): User email
supplier (Object, optional): Supplier info with code, id, etc.
request_metadata (Object|string, optional): Request metadata
error_stack (string, optional): Error stack trace (auto-truncated)
metadata (Object|string, optional): Additional metadata
Webhook Client
createTelegramWebhookClient(config)
Create a webhook client for production.
Config Parameters:
botToken (string, required): Telegram bot token
webhookUrl (string, required): Webhook URL
secretToken (string, optional): Secret token for verification
allowedUpdates (Array, optional): Update types to receive
maxConnections (number, optional): Max connections
timeout (number, optional): Request timeout
Multi-Channel Support
Supported Alert Channels (v2.0.0)
- TelegramAlert: Send alerts to Telegram chats/channels with thread routing
- SlackAlert: Send alerts to Slack channels with rich formatting
- MattermostAlert: Send alerts to Mattermost channels
- EmailAlert: Send HTML/text email alerts via SMTP
- DiscordAlert: Send alerts to Discord channels via webhooks
- ZaloAlert: Send alerts via Zalo Official Account
- MessengerAlert: Send alerts via Facebook Messenger
- N8nAlert: Trigger N8n workflows with alert data
- WhatsAppAlert: Send alerts via WhatsApp Business API
- LineAlert: Send alerts via Line Notify API
- ViberAlert: Send alerts via Viber Bot API
- SkypeAlert: Send alerts via Skype Bot Framework
- WeChatAlert: Send alerts via WeChat Work webhook
- RocketChatAlert: Send alerts to Rocket.Chat channels
- FirebaseAlert: Send push notifications via Firebase Cloud Messaging
- MultiChannelAlert: Send to multiple channels simultaneously
Service Types
- hotel: Hotel bookings and searches
- flight: Flight bookings, PNR generation, e-tickets
- tour: Tour packages and bookings
- transfer: Airport transfers and transportation
Alert Types (Logger Methods)
- error(): Error alerts with red/urgent styling
- info(): Informational alerts with blue styling
- warn(): Warning alerts with yellow/caution styling
- success(): Success alerts with green/positive styling
Environment Types
- DEV: Development environment
- STAGING: Staging/testing environment
- PRODUCTION: Production environment
Version History
- v2.0.1 (2025-10-01):
- π Fixed: Data filtering bug in MultiChannelAlert (
item.field β item.key)
- π¨ Enhanced: Mattermost message formatting with emoji titles and code blocks
- ποΈ Added: Individual component
strictMode support (TelegramAlert, SlackAlert, MattermostAlert)
- π Improved: Cross-platform formatting consistency for JSON objects and curl commands
- π§ Added: Comprehensive data filtering utilities with backward compatibility
- v2.0.0 (2025-09-29): Multi-channel alert system, logger-style API, conditional channels
- v1.1.1 (2025): Enhanced Telegram formatting, smart ID extraction
- v1.0.0 (2025): Initial release with Telegram bot and logging
Best Practices
1. Use MultiChannelAlert for New Projects
const { MultiChannelAlert } = require('kien-nguyen-support')
const alert = new MultiChannelAlert({ channels: [...] })
await alert.error(data)
await telegramAlert.error(data)
await slackAlert.error(data)
await emailAlert.error(data)
2. Conditional Channel Setup
const channels = []
if (process.env.TELEGRAM_BOT_TOKEN) channels.push({...})
if (process.env.SLACK_WEBHOOK_URL) channels.push({...})
const channels = [telegram, slack, email]
3. Use Environment Variables
const alert = new MultiChannelAlert({
channels: [...],
environment: process.env.NODE_ENV || 'STAGING',
failSilently: process.env.NODE_ENV === 'production'
})
4. Handle Errors Gracefully
const result = await multiAlert.error(data)
if (result.summary.failed > 0) {
console.warn(`${result.summary.failed} channels failed to send alert`)
}
const alert = new MultiChannelAlert({
failSilently: true
})
Troubleshooting
Common Issues
1. "Unable to resolve path to module" error:
npm install kien-nguyen-support
const { MultiChannelAlert } = require('kien-nguyen-support')
2. Telegram "Unauthorized" error:
- Check bot token is correct
- Ensure bot is added to the chat/channel
- Verify chat ID format (numbers for groups, @channel for channels)
3. Slack "Invalid webhook URL" error:
- Regenerate webhook URL from Slack app settings
- Ensure webhook is activated for correct channel
4. Email SMTP errors:
- Use app passwords for Gmail (not regular password)
- Check firewall/network allows SMTP traffic
- Verify port (587 for TLS, 465 for SSL)
5. MultiChannelAlert some channels failing:
- Enable
failSilently: true to continue on errors
- Check individual channel configurations
- Review error details in response.errors array
Getting Help
License
ISC
Author
nguyenkien2022001@gmail.com
Repository
https://github.com/Trungkien2022001/kien-nguyen-support