@warriorteam/zalo-webhook-types
Version:
TypeScript types for Zalo Personal webhook events from automation-web
305 lines • 9.8 kB
JavaScript
;
/**
* 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