n8n-nodes-zola-fake
Version:
Các node hỗ trợ Zalo cho n8n Thong
181 lines (165 loc) • 7.91 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZaloGomTin = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const dbManager = require('../utils/dbManager');
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
class ZaloGomTin {
constructor() {
this.description = {
displayName: 'Zalo Gom Tin Nhắn',
name: 'zaloGomTin',
icon: 'file:../shared/zalo.svg',
group: ['Zalo'],
version: 1,
description: 'Gom tin nhắn Zalo và chờ trong một khoảng thời gian',
defaults: { name: 'Zalo Gom Tin Nhắn' },
inputs: ['main'],
outputs: ['main', 'main'],
outputNames: ['Kết quả', 'Bỏ qua'],
credentials: [
{
name: 'redis',
required: true,
displayOptions: {
show: {
'/dbType': ['redis'],
},
},
},
{
name: 'zaloPostgres',
required: true,
displayOptions: {
show: {
'/dbType': ['postgres'],
},
},
},
{
name: 'zaloMySql',
required: true,
displayOptions: {
show: {
'/dbType': ['mysql'],
},
},
},
],
properties: [
{
displayName: 'Loại Cơ Sở Dữ Liệu',
name: 'dbType',
type: 'options',
options: [
{ name: 'Redis', value: 'redis' },
{ name: 'PostgreSQL', value: 'postgres' },
{ name: 'MySQL', value: 'mysql' },
],
default: 'redis',
description: 'Chọn loại cơ sở dữ liệu để lưu trữ tin nhắn tạm thời.',
},
{
displayName: 'ID Nhóm Chat (Thread ID)',
name: 'thread_id',
type: 'string',
default: '={{ $json.message.threadId }}',
placeholder: 'ID định danh của cuộc trò chuyện',
description: 'ID định danh duy nhất của cuộc trò chuyện để gom tin nhắn.',
},
{
displayName: 'Nội Dung Tin Nhắn',
name: 'message_content',
type: 'string',
default: '={{ $json.message.data.content }}',
placeholder: 'Nội dung tin nhắn',
description: 'Nội dung tin nhắn cần gom.',
},
{
displayName: 'Thời Gian Chờ (giây)',
name: 'waitTime',
type: 'number',
default: 10,
description: 'Thời gian chờ (tính bằng giây) trước khi gom và gửi tin nhắn.',
}
],
};
}
async execute() {
const items = this.getInputData();
let dbOperations;
try {
const thread_id = this.getNodeParameter('thread_id', 0, '');
const message_content = this.getNodeParameter('message_content', 0, '');
console.log(`\n--- [ZaloGomTin] START Execution for thread_id: ${thread_id} ---`);
console.log(`[ZaloGomTin] Received message: "${message_content}"`);
dbOperations = await dbManager.getDbOperations(this);
const waitTime = this.getNodeParameter('waitTime', 0, 5);
const debounceKey = `zalo_message_collector_debounce:${thread_id}`;
const contentKey = `zalo_message_collector_content:${thread_id}`;
const currentTime = new Date().getTime().toString();
console.log(`[ZaloGomTin] Current execution time ID: ${currentTime}`);
// Luôn cập nhật thời gian để reset bộ đếm debounce
await dbOperations.set(debounceKey, currentTime);
console.log(`[ZaloGomTin] Set debounceKey (${debounceKey}) to: ${currentTime}`);
// Lấy nội dung cũ, thêm nội dung mới và lưu lại
let lastContent = await dbOperations.get(contentKey);
let contentArray = lastContent ? JSON.parse(lastContent) : [];
console.log(`[ZaloGomTin] Content BEFORE add: ${JSON.stringify(contentArray)}`);
contentArray.push(message_content);
await dbOperations.set(contentKey, JSON.stringify(contentArray));
console.log(`[ZaloGomTin] Content AFTER add: ${JSON.stringify(contentArray)}`);
// Chờ hết thời gian debounce
console.log(`[ZaloGomTin] Waiting for ${waitTime} seconds...`);
await sleep(waitTime * 1000);
// Sau khi chờ, kiểm tra xem có tin nhắn nào mới hơn không
const finalDebounceTime = await dbOperations.get(debounceKey);
console.log(`[ZaloGomTin] After wait, debounceKey in DB is: ${finalDebounceTime}`);
console.log(`[ZaloGomTin] Comparing DB time (${finalDebounceTime}) with execution time (${currentTime})`);
// Nếu thời gian trong DB không phải là của lần thực thi này, nghĩa là có tin nhắn mới hơn đã đến. Bỏ qua.
if (finalDebounceTime !== currentTime) {
console.log('[ZaloGomTin] SKIPPING: Newer message arrived. This is normal for intermediate messages.');
console.log('--- [ZaloGomTin] END Execution (Skipped) ---\n');
return [[], [items[0]]];
}
console.log('[ZaloGomTin] PROCEEDING: This is the last message in the sequence.');
await dbOperations.del(debounceKey);
const finalContent = await dbOperations.get(contentKey);
await dbOperations.del(contentKey);
console.log('[ZaloGomTin] Deleted debounceKey and contentKey from DB.');
let finalContentArray = finalContent ? JSON.parse(finalContent) : [];
console.log(`[ZaloGomTin] Final collected content: ${JSON.stringify(finalContentArray)}`);
if (finalContentArray.length <= 0) {
console.log('[ZaloGomTin] No content to return. Skipping.');
console.log('--- [ZaloGomTin] END Execution (No Content) ---\n');
return [[], [items[0]]]; // Bỏ qua
} else {
const returnItem = {
json: {
threadId: thread_id,
messages: finalContentArray,
content: finalContentArray.join(' '),
},
pairedItem: { item: 0 },
};
console.log('[ZaloGomTin] Returning collected messages.');
console.log('--- [ZaloGomTin] END Execution (Success) ---\n');
return [[returnItem], []];
}
} catch (error) {
console.error(`[ZaloGomTin] ERROR: ${error.stack}`);
if (this.continueOnFail()) {
const errorItem = { json: { error: error.message }, pairedItem: { item: 0 } };
return [[], [errorItem]];
}
throw error;
} finally {
if (dbOperations && dbOperations.quit) {
await dbOperations.quit();
}
}
}
}
exports.ZaloGomTin = ZaloGomTin;