UNPKG

@warriorteam/zalo-webhook-types

Version:

TypeScript types for Zalo Personal webhook events from automation-web

305 lines 9.8 kB
"use strict"; /** * Utility Functions for Zalo Webhook Events * * Helper functions for working with webhook events and message content. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.detectMessageType = detectMessageType; exports.getMessageCategory = getMessageCategory; exports.createDetailedMessageEventType = createDetailedMessageEventType; exports.hasAttachment = hasAttachment; exports.extractThreadId = extractThreadId; exports.formatTimestamp = formatTimestamp; exports.getThreadDisplayName = getThreadDisplayName; exports.isFromSelf = isFromSelf; exports.getTextContent = getTextContent; exports.formatFileSize = formatFileSize; exports.formatDuration = formatDuration; exports.getEventCategory = getEventCategory; exports.isSentEvent = isSentEvent; exports.isReceivedEvent = isReceivedEvent; exports.isUserEvent = isUserEvent; exports.isGroupEvent = isGroupEvent; exports.createMessageEventData = createMessageEventData; exports.validateWebhookEvent = validateWebhookEvent; exports.sanitizeContentForLogging = sanitizeContentForLogging; const enums_1 = require("../enums"); /** * Detect message type from SDK msgType */ function detectMessageType(msgType) { switch (msgType) { case 'webchat': return enums_1.ZaloMessageType.WEBCHAT; case 'chat.link': return enums_1.ZaloMessageType.LINK; case 'chat.photo': return enums_1.ZaloMessageType.PHOTO; case 'chat.video.msg': return enums_1.ZaloMessageType.VIDEO; case 'chat.voice': return enums_1.ZaloMessageType.VOICE; case 'chat.gif': return enums_1.ZaloMessageType.GIF; case 'chat.doodle': return enums_1.ZaloMessageType.DOODLE; case 'share.file': return enums_1.ZaloMessageType.FILE; case 'chat.sticker': return enums_1.ZaloMessageType.STICKER; case 'chat.location.new': return enums_1.ZaloMessageType.LOCATION; default: return enums_1.ZaloMessageType.WEBCHAT; // Default fallback } } /** * Get message category from message type */ function getMessageCategory(msgType) { switch (msgType) { case enums_1.ZaloMessageType.WEBCHAT: case enums_1.ZaloMessageType.LINK: return enums_1.ZaloMessageCategory.TEXT; case enums_1.ZaloMessageType.PHOTO: case enums_1.ZaloMessageType.VIDEO: case enums_1.ZaloMessageType.VOICE: case enums_1.ZaloMessageType.GIF: case enums_1.ZaloMessageType.DOODLE: return enums_1.ZaloMessageCategory.MEDIA; case enums_1.ZaloMessageType.FILE: return enums_1.ZaloMessageCategory.FILE; case enums_1.ZaloMessageType.STICKER: case enums_1.ZaloMessageType.LOCATION: return enums_1.ZaloMessageCategory.SOCIAL; default: return enums_1.ZaloMessageCategory.TEXT; } } /** * Create detailed message event type from basic info */ function createDetailedMessageEventType(msgType, threadType, isSelf) { const direction = isSelf ? 'SENT' : 'RECEIVED'; const target = threadType === enums_1.ZaloThreadType.USER ? 'USER' : 'GROUP'; switch (msgType) { case enums_1.ZaloMessageType.WEBCHAT: return `TEXT_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.LINK: return `LINK_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.PHOTO: return `IMAGE_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.VIDEO: return `VIDEO_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.VOICE: return `VOICE_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.GIF: return `GIF_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.DOODLE: return `DOODLE_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.FILE: return `FILE_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.STICKER: return `STICKER_MESSAGE_${direction}_TO_${target}`; case enums_1.ZaloMessageType.LOCATION: return `LOCATION_MESSAGE_${direction}_TO_${target}`; default: return `MESSAGE_${direction}_TO_${target}`; } } /** * Check if message has attachment based on message type */ function hasAttachment(msgType) { return [ enums_1.ZaloMessageType.PHOTO, enums_1.ZaloMessageType.VIDEO, enums_1.ZaloMessageType.VOICE, enums_1.ZaloMessageType.GIF, enums_1.ZaloMessageType.DOODLE, enums_1.ZaloMessageType.FILE ].includes(msgType); } /** * Extract thread ID from message data */ function extractThreadId(data) { // For group messages, use idTo (group ID) // For user messages, use uidFrom if not self, otherwise idTo if (data.threadType === enums_1.ZaloThreadType.GROUP) { return data.idTo; } else { return data.isSelf ? data.idTo : data.uidFrom; } } /** * Format timestamp from SDK ts string to number */ function formatTimestamp(ts) { return parseInt(ts, 10); } /** * Get display name for thread */ function getThreadDisplayName(data, threadType) { if (threadType === enums_1.ZaloThreadType.GROUP) { return `Group ${data.idTo}`; } else { return data.isSelf ? `User ${data.idTo}` : data.dName; } } /** * Check if message is from self */ function isFromSelf(data, currentUserId) { return data.uidFrom === currentUserId; } /** * Get message content as string (for text messages) */ function getTextContent(content) { if (typeof content === 'string') { return content; } return ''; } /** * Get file size in human readable format */ function formatFileSize(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } /** * Format duration from milliseconds to human readable format */ function formatDuration(milliseconds) { const seconds = Math.floor(milliseconds / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); if (hours > 0) { return `${hours}:${(minutes % 60).toString().padStart(2, '0')}:${(seconds % 60).toString().padStart(2, '0')}`; } else { return `${minutes}:${(seconds % 60).toString().padStart(2, '0')}`; } } /** * Get event category from event type */ function getEventCategory(eventType) { if (eventType.includes('MESSAGE') || eventType.includes('message')) { return 'message'; } if ([ enums_1.ZaloWebhookEventType.TYPING, enums_1.ZaloWebhookEventType.SEEN_MESSAGES, enums_1.ZaloWebhookEventType.DELIVERED_MESSAGES, enums_1.ZaloWebhookEventType.REACTION, enums_1.ZaloWebhookEventType.UNDO ].includes(eventType)) { return 'interaction'; } if ([ enums_1.ZaloWebhookEventType.FRIEND_EVENT, enums_1.ZaloWebhookEventType.GROUP_EVENT ].includes(eventType)) { return 'social'; } return 'system'; } /** * Check if event is sent event (from self) */ function isSentEvent(eventType) { return eventType.includes('SENT'); } /** * Check if event is received event (from others) */ function isReceivedEvent(eventType) { return eventType.includes('RECEIVED'); } /** * Check if event is user event (1-on-1 chat) */ function isUserEvent(eventType) { return eventType.includes('USER'); } /** * Check if event is group event (group chat) */ function isGroupEvent(eventType) { return eventType.includes('GROUP'); } /** * Create a basic message event data structure */ function createMessageEventData(msgId, msgType, uidFrom, idTo, content, threadType, isSelf, dName = '', ts = Date.now().toString()) { const messageCategory = getMessageCategory(msgType); const hasAttachmentFlag = hasAttachment(msgType); return { actionId: `action_${msgId}`, msgId, cliMsgId: `cli_${msgId}`, msgType, uidFrom, idTo, dName, ts, status: 1, content, threadId: extractThreadId({ threadType, isSelf, uidFrom, idTo }), threadType, isSelf, messageType: msgType, messageCategory, hasAttachment: hasAttachmentFlag }; } /** * Validate webhook event structure */ function validateWebhookEvent(event) { return (typeof event === 'object' && event !== null && typeof event.eventType === 'string' && typeof event.sessionId === 'string' && typeof event.userUuid === 'string' && typeof event.timestamp === 'number' && typeof event.data === 'object' && event.data !== null); } /** * Sanitize message content for logging */ function sanitizeContentForLogging(content) { if (typeof content === 'string') { return content.length > 100 ? content.substring(0, 100) + '...' : content; } if (typeof content === 'object' && content !== null) { if ('href' in content) { return `[Attachment: ${content.fileName || 'unknown'}]`; } if ('latitude' in content && 'longitude' in content) { return `[Location: ${content.latitude}, ${content.longitude}]`; } if ('stickerId' in content) { return `[Sticker: ${content.stickerId || 'unknown'}]`; } } return '[Unknown content]'; } //# sourceMappingURL=index.js.map