n8n-nodes-zalo-nnt
Version:
Unofficial Zalo integration for n8n - Send messages, manage groups, user operations with QR login. No API key required, works via browser simulation.
171 lines • 7.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZaloChatHistory = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const zca_js_1 = require("zca-js");
const helper_1 = require("../utils/helper");
const ZaloChatHistory_properties_1 = require("./ZaloChatHistory.properties");
const utils_1 = require("./utils");
let api;
class ZaloChatHistory {
constructor() {
this.description = {
displayName: 'Lịch Sử Chat Zalo by diginno.net',
name: 'zaloChatHistory',
icon: 'file:../shared/image.svg',
group: ['transform'],
version: 1,
description: 'Lấy lịch sử tin nhắn từ Zalo (cá nhân & nhóm) by diginno.net',
defaults: {
name: 'Lịch Sử Chat Zalo by diginno.net',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'zaloApi',
required: true,
},
],
properties: ZaloChatHistory_properties_1.zaloChatHistoryProperties,
};
}
async execute() {
const returnData = [];
const items = this.getInputData();
const zaloCred = await this.getCredentials('zaloApi');
let cookieFromCred = zaloCred.cookie;
try {
cookieFromCred = JSON.parse(zaloCred.cookie);
}
catch {
}
const imeiFromCred = zaloCred.imei;
const userAgentFromCred = zaloCred.userAgent;
try {
const zalo = new zca_js_1.Zalo({
imageMetadataGetter: helper_1.imageMetadataGetter,
});
api = await zalo.login({
cookie: cookieFromCred,
imei: imeiFromCred,
userAgent: userAgentFromCred,
});
if (!api) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to initialize Zalo API. Check your credentials.');
}
if (!api.listener) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Zalo WebSocket listener not available.');
}
try {
this.logger.info('Starting WebSocket listener...');
api.listener.start({ retryOnClose: false });
await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('WebSocket connection timeout'));
}, 10000);
api.listener.once('connected', () => {
clearTimeout(timeout);
this.logger.info('WebSocket listener connected');
resolve(true);
});
api.listener.once('error', (error) => {
clearTimeout(timeout);
reject(error);
});
});
}
catch (error) {
if (error.message !== 'Already started') {
throw error;
}
this.logger.info('WebSocket listener already started');
}
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Zalo login error: ${error.message}`);
}
for (let i = 0; i < items.length; i++) {
try {
const operation = this.getNodeParameter('operation', i);
const filterByThreadId = this.getNodeParameter('filterByThreadId', i, true);
const threadId = this.getNodeParameter('threadId', i, '');
const fetchAll = this.getNodeParameter('fetchAll', i, false);
const limit = this.getNodeParameter('limit', i, 20);
const lastMsgId = this.getNodeParameter('lastMsgId', i, '');
const includeReactions = this.getNodeParameter('includeReactions', i, false);
const sortOrder = this.getNodeParameter('sortOrder', i, 'desc');
const fromDate = this.getNodeParameter('fromDate', i, '');
const toDate = this.getNodeParameter('toDate', i, '');
const delayBetweenRequests = this.getNodeParameter('delayBetweenRequests', i, 1000);
const maxPages = this.getNodeParameter('maxPages', i, 50);
const params = (0, utils_1.parseHistoryParams)({
operation,
threadId,
filterByThreadId,
limit,
lastMsgId,
includeReactions,
sortOrder,
fromDate: fromDate ? new Date(fromDate).getTime() : null,
toDate: toDate ? new Date(toDate).getTime() : null,
fetchAll,
delayBetweenRequests,
maxPages,
});
const target = filterByThreadId ? `thread ${threadId}` : 'ALL threads (no filter)';
if (fetchAll) {
this.logger.info(`Fetching ALL ${operation} for ${target} (maxPages: ${maxPages}, delay: ${delayBetweenRequests}ms)`);
}
else {
this.logger.info(`Fetching ${operation} for ${target} (limit: ${limit}, lastMsgId: ${lastMsgId || 'null'})`);
}
if (!api || !api.listener) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Zalo API or listener not initialized');
}
const result = await (0, utils_1.getChatHistory)(api, params, api.listener, 30000);
this.logger.info(`Retrieved ${result.totalCount}/${result.fetchedCount} messages in ${result.pagesRequested} page(s) ` +
`(hasMore: ${result.hasMore}, lastMsgId: ${result.lastMsgId})`);
if (fetchAll && result.hasMore) {
this.logger.warn(`Chạm trần ${maxPages} trang — backlog chưa vét hết. Chạy lại với "ID Tin Nhắn Cuối" = "${result.lastMsgId}" để kéo tiếp.`);
}
if (result.filterByThreadId && result.fetchedCount > 0 && result.totalCount === 0) {
this.logger.warn(`Zalo trả về ${result.fetchedCount} tin nhưng không tin nào thuộc hội thoại ${threadId}. Truyền lastMsgId="${result.lastMsgId}" để kéo tiếp phần backlog cũ hơn.`);
}
const responseData = {
success: true,
operation,
threadId: result.threadId,
threadType: result.threadType === 0 ? 'user' : 'group',
filterByThreadId: result.filterByThreadId,
messages: result.messages,
hasMore: result.hasMore,
lastMsgId: result.lastMsgId,
totalCount: result.totalCount,
fetchedCount: result.fetchedCount,
pagesRequested: result.pagesRequested,
};
returnData.push({
json: responseData,
});
}
catch (error) {
this.logger.error('Error fetching chat history:', error);
if (this.continueOnFail()) {
returnData.push({
json: {
success: false,
error: error.message,
},
});
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
}
}
}
return [returnData];
}
}
exports.ZaloChatHistory = ZaloChatHistory;
//# sourceMappingURL=ZaloChatHistory.node.js.map