UNPKG

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.

313 lines 17.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ZaloLoginByQr = void 0; const n8n_workflow_1 = require("n8n-workflow"); const zca_js_1 = require("zca-js"); const axios_1 = __importDefault(require("axios")); class ZaloLoginByQr { constructor() { this.description = { displayName: 'Zalo Login Via QR Code', name: 'zaloLoginByQr', group: ['Zalo'], version: 1, description: 'LĐăng nhập Zalo bằng QR code và lưu thông tin vào Credentia', defaults: { name: 'Zalo Login Via QR Code', }, inputs: ['main'], outputs: ['main'], icon: 'file:../shared/zalo.svg', credentials: [ { name: 'n8nApiZaloApi', required: true, displayName: 'n8n API Account (Required - only API Key & URL)', }, ], properties: [ { displayName: 'Proxy', name: 'proxy', type: 'string', default: '', placeholder: 'https://user:pass@host:port', description: 'HTTP proxy to use for Zalo API requests', }, ], }; } async execute() { const returnData = []; const proxy = this.getNodeParameter('proxy', 0, ''); const timeout = 30; const fileName = 'zalo-qr-code.png'; let n8nCredential; try { n8nCredential = await this.getCredentials('n8nApiZaloApi'); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'n8n API credentials are required for QR login'); } console.error('Using n8n account credential for QR login'); try { const zaloOptions = { selfListen: true, logging: true, }; if (proxy) { zaloOptions.proxy = proxy; } const zalo = new zca_js_1.Zalo(zaloOptions); console.error('Starting Zalo QR login process...'); const processContext = (context) => { if (!context) { console.error('Context is null or undefined'); return; } const cookie = context.cookie || ''; const imei = context.imei || ''; const userAgent = context.userAgent || ''; console.error('=== ZALO CREDENTIALS ==='); console.error('Cookie:', cookie ? `Received (length: ${typeof cookie === 'string' ? cookie.length : (Array.isArray(cookie) ? cookie.length : 'unknown')})` : 'None'); console.error('IMEI:', imei ? imei : 'None'); console.error('User Agent:', userAgent ? userAgent : 'None'); console.error('=== END CREDENTIALS ==='); }; const setupEventListeners = (api) => { console.error('Setting up event listeners to get credentials'); try { if (typeof api.getContext === 'function') { const contextResult = api.getContext(); if (contextResult && typeof contextResult.then === 'function') { contextResult.then((context) => { processContext(context); }).catch((error) => { console.error('Error getting context:', error); }); } else { processContext(contextResult); } } else { console.error('getContext is not a function'); if (api.context) { console.error('Found context in api object'); processContext(api.context); } else { console.error('No context found in api object'); } } } catch (error) { console.error('Error in setupEventListeners:', error); } }; const qrCodePromise = new Promise(async (resolve, reject) => { let isResolved = false; const timeoutId = setTimeout(() => { if (!isResolved) { isResolved = true; reject(new n8n_workflow_1.NodeOperationError(this.getNode(), 'Timeout generating QR code. Please try again or check your Zalo connection.')); } }, timeout * 1000); try { let api = await zalo.loginQR(null, (qrEvent) => { var _a, _b; console.error('Received QR event type:', qrEvent ? qrEvent.type : 'no event'); switch (qrEvent.type) { case 0: if ((_a = qrEvent === null || qrEvent === void 0 ? void 0 : qrEvent.data) === null || _a === void 0 ? void 0 : _a.image) { const qrCodeBase64 = qrEvent.data.image; console.error('QR code generated, length:', qrCodeBase64.length); if (isResolved) return; clearTimeout(timeoutId); if (qrCodeBase64) { isResolved = true; resolve(qrCodeBase64); } } else { console.error('Could not get QR code from Zalo SDK'); reject(new Error("Could not get QR code")); } break; case 1: console.error('QR code expired. Please try again.'); break; case 2: console.error('=== QR CODE SCANNED ==='); if (qrEvent === null || qrEvent === void 0 ? void 0 : qrEvent.data) { console.error('User:', qrEvent.data.display_name); console.error('Avatar:', qrEvent.data.avatar ? 'Yes' : 'No'); } break; case 3: console.error('=== QR CODE DECLINED ==='); if ((_b = qrEvent === null || qrEvent === void 0 ? void 0 : qrEvent.data) === null || _b === void 0 ? void 0 : _b.code) { console.error('Decline code:', qrEvent.data.code); } break; case 4: console.error('=== GOT LOGIN INFO ==='); if (qrEvent === null || qrEvent === void 0 ? void 0 : qrEvent.data) { const cookie = qrEvent.data.cookie || []; const imei = qrEvent.data.imei || ''; const userAgent = qrEvent.data.userAgent || ''; console.error('Cookie received:', cookie.length > 0 ? 'Yes' : 'No'); console.error('IMEI received:', imei ? 'Yes' : 'No'); console.error('User Agent received:', userAgent ? 'Yes' : 'No'); try { if (cookie.length > 0 || imei || userAgent) { const credentialName = 'Zalo API Credentials'; const credentialData = { cookie: JSON.stringify(cookie), imei: imei, userAgent: userAgent, proxy: proxy || '', supportCode: '', licenseKey: '' }; try { console.error('Attempting to create Zalo credential via n8n API'); const credentialApiData = { name: credentialName, type: 'zaloApi', nodesAccess: [], data: credentialData }; const ports = [5678]; const createCredentialOnPort = async (port) => { const n8nApi = await this.getCredentials('n8nApiZaloApi'); const n8nApiUrl = n8nApi.url; const fullApiUrl = `${n8nApiUrl}/api/v1/credentials`; const n8nApiKey = n8nApi.apiKey; console.error(`Trying to create credential via n8n API at ${fullApiUrl}`); try { await axios_1.default.post(fullApiUrl, credentialApiData, { headers: { 'Content-Type': 'application/json', 'X-N8N-API-KEY': n8nApiKey }, }); console.error('Credential created successfully via n8n API'); console.error('Credential ID:'); return true; } catch (apiError) { console.error(`Error creating credential on port ${port}:`, apiError.message); return false; } }; let credentialCreated = false; (async () => { for (const port of ports) { try { const result = await createCredentialOnPort.call(this, port); if (result) { credentialCreated = true; break; } } catch (error) { console.error(`Error trying port ${port}:`, error.message); } } })().catch(error => { console.error('Error in credential creation:', error.message); }); if (!credentialCreated) { console.error('Could not create credential via n8n API on any port.'); console.error('Credential info saved to file. You can create it manually using:'); console.error('node auto-create-zalo-credential.js'); } } catch (error) { console.error(`Error creating credential: ${error.message}`); console.error('Credential info saved to file. You can create it manually using:'); console.error('node auto-create-zalo-credential.js'); } } else { console.error('=== NO CREDENTIALS TO SAVE ==='); console.error('No login information available to save'); } } catch (fileError) { console.error('Error saving credentials:', fileError.message); } } break; default: console.error('Unknown QR event type:', qrEvent.type); } }); console.error('Starting Zalo listener'); api.listener.start(); api.listener.onConnected(() => { console.error("=== ZALO SDK CONNECTED ==="); setupEventListeners(api); }); api.listener.onError((error) => { console.error("=== ZALO ERROR ===", error); }); api.listener.onMessage((message) => { console.error("=== ZALO MESSAGE RECEIVED ==="); console.error("Message type:", message.type); console.error("Message content:", JSON.stringify(message).substring(0, 200) + '...'); if (message.type === 'login_success' || message.type === 'qr_scanned') { console.error("=== QR CODE SCANNED OR LOGIN SUCCESSFUL ==="); setupEventListeners(api); } }); console.error('All event listeners set up'); } catch (error) { clearTimeout(timeoutId); if (!isResolved) { isResolved = true; reject(error); } } }); const qrCodeBase64 = await qrCodePromise; const binaryData = Buffer.from(qrCodeBase64, 'base64'); const newItem = { json: { success: true, message: 'QR code generated successfully. Scan with Zalo app to login. Credentials will be auto-created after successful login.', fileName, credentialType: 'n8nApiZaloApi', }, binary: { data: await this.helpers.prepareBinaryData(binaryData, fileName, 'image/png'), }, }; returnData.push(newItem); if (returnData[0] && returnData[0].json) { returnData[0].json.credentialInstructions = 'Using n8n API credential. New Zalo credentials will be created automatically after successful QR login.'; returnData[0].json.credentialName = n8nCredential.name || 'Unknown'; returnData[0].json.credentialId = n8nCredential.id || 'Unknown'; returnData[0].json.autoCreateApi = 'Credentials will be created automatically via n8n API after successful login.'; } return [returnData]; } catch (error) { if (this.continueOnFail()) { const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: 0 } }); return [executionData]; } else { throw error; } } } } exports.ZaloLoginByQr = ZaloLoginByQr; //# sourceMappingURL=ZaloLoginByQr.node.js.map