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.

819 lines 41.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ZaloUser = void 0; const n8n_workflow_1 = require("n8n-workflow"); const ZaloUserDescription_1 = require("./ZaloUserDescription"); const zca_js_1 = require("zca-js"); let api; class ZaloUser { constructor() { this.description = { displayName: 'Zalo Người dùng by diginno.net', name: 'zaloUser', icon: 'file:../shared/image.svg', group: ['Zalo'], version: 1, subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}', description: 'Quản lý người dùng Zalo by diginno.net', defaults: { name: 'Zalo Người dùng by diginno.net', }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'zaloApi', required: true, displayName: 'Zalo Credential to connect with', }, ], properties: ZaloUserDescription_1.zaloUserProperties, }; } async execute() { var _a, _b, _c, _d, _e, _f, _g, _h, _j; const items = this.getInputData(); const returnData = []; const resource = this.getNodeParameter('resource', 0); const operation = this.getNodeParameter('operation', 0); 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; const cookie = cookieFromCred !== null && cookieFromCred !== void 0 ? cookieFromCred : (_a = items.find((x) => x.json.cookie)) === null || _a === void 0 ? void 0 : _a.json.cookie; const imei = imeiFromCred !== null && imeiFromCred !== void 0 ? imeiFromCred : (_b = items.find((x) => x.json.imei)) === null || _b === void 0 ? void 0 : _b.json.imei; const userAgent = userAgentFromCred !== null && userAgentFromCred !== void 0 ? userAgentFromCred : (_c = items.find((x) => x.json.userAgent)) === null || _c === void 0 ? void 0 : _c.json.userAgent; const isConnectionCheck = resource === 'system' && operation === 'checkConnection'; const checkedAt = new Date().toISOString(); const zalo = new zca_js_1.Zalo(); let loginError = null; try { const _api = await zalo.login({ cookie: cookie, imei, userAgent }); api = _api; } catch (error) { if (!isConnectionCheck) { throw error; } loginError = error; } if (isConnectionCheck) { for (let i = 0; i < items.length; i++) { if (loginError || !api) { returnData.push({ json: { alive: false, status: 'Mất kết nối', checkedAt, error: (loginError === null || loginError === void 0 ? void 0 : loginError.message) || 'No API instance returned from login', }, pairedItem: { item: i }, }); continue; } try { const accountInfo = await api.fetchAccountInfo(); returnData.push({ json: { alive: true, status: 'Đang kết nối', checkedAt, accountInfo }, pairedItem: { item: i }, }); } catch (checkError) { returnData.push({ json: { alive: false, status: 'Mất kết nối', checkedAt, error: checkError.message, }, pairedItem: { item: i }, }); } } return [returnData]; } if (!api) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No API instance found. Please make sure to provide valid credentials.'); } for (let i = 0; i < items.length; i++) { try { if (resource === 'friend') { if (operation === 'rejectFriendRequest') { const userId = this.getNodeParameter('userId', i); const response = await api.rejectFriendRequest(userId); returnData.push({ json: { status: 'Thành công', message: 'Đã từ chối lời mời kết bạn', userId: userId, response: response, }, pairedItem: { item: i }, }); } else if (operation === 'undoFriendRequest') { const userId = this.getNodeParameter('userId', i); const response = await api.undoFriendRequest(userId); returnData.push({ json: { status: 'Thành công', message: 'Đã hủy lời mời kết bạn', userId: userId, response: response, }, pairedItem: { item: i }, }); } else if (operation === 'getSentFriendRequest') { try { const response = await api.getSentFriendRequest(); const sentRequests = Object.values(response || {}); returnData.push({ json: { status: 'Thành công', totalRequests: sentRequests.length, requests: sentRequests, }, pairedItem: { item: i }, }); } catch (error) { if (error.message && error.message.includes('112')) { returnData.push({ json: { status: 'Thành công', totalRequests: 0, requests: [], message: 'Không có lời mời kết bạn nào đang chờ xử lý', }, pairedItem: { item: i }, }); } else { throw error; } } } else if (operation === 'removeFriend') { const userId = this.getNodeParameter('userId', i); const response = await api.removeFriend(userId); returnData.push({ json: { status: 'Thành công', message: 'Đã xóa người dùng khỏi danh sách bạn bè', userId: userId, response: response, }, pairedItem: { item: i }, }); } else if (operation === 'getFriendRequestStatus') { const userId = this.getNodeParameter('userId', i); const response = await api.getFriendRequestStatus(userId); returnData.push({ json: { status: 'Thành công', userId: userId, friendStatus: response, }, pairedItem: { item: i }, }); } else if (operation === 'getFriendOnlines') { const response = await api.getFriendOnlines(); returnData.push({ json: { status: 'Thành công', ownerStatus: response.ownerStatus, onlines: response.onlines, totalOnline: ((_d = response.onlines) === null || _d === void 0 ? void 0 : _d.length) || 0, }, pairedItem: { item: i }, }); } else if (operation === 'getRelatedFriendGroup') { const userId = this.getNodeParameter('userId', i); const response = await api.getRelatedFriendGroup(userId); returnData.push({ json: { status: 'Thành công', userId: userId, groupRelateds: response.groupRelateds, }, pairedItem: { item: i }, }); } else if (operation === 'acceptFriendRequest') { const userId = this.getNodeParameter('userId', i); const response = await api.acceptFriendRequest(userId); returnData.push({ json: { status: 'Thành công', response: response, }, pairedItem: { item: i, }, }); } else if (operation === 'sendFriendRequest') { const userId = this.getNodeParameter('userId', i); const message = this.getNodeParameter('message', i); const response = await api.sendFriendRequest(message, userId); returnData.push({ json: { status: 'Thành công', response: response, }, pairedItem: { item: i, }, }); } else if (operation === 'getAllFriends') { const limit = this.getNodeParameter('limit', i); const response = await api.getAllFriends(); const friends = response.slice(0, limit) || []; returnData.push({ json: { friends: friends, }, pairedItem: { item: i, }, }); } else if (operation === 'findUser') { const phoneNumber = this.getNodeParameter('phoneNumber', i); const response = await api.findUser(phoneNumber); returnData.push({ json: response, pairedItem: { item: i, }, }); } else if (operation === 'getCloseFriends') { const limit = this.getNodeParameter('limit', i, 50); const offset = this.getNodeParameter('offset', i, 0); const allCloseFriends = await api.getCloseFriends(); const friends = allCloseFriends.slice(offset, offset + limit); returnData.push({ json: { status: 'Thành công', friends: friends, totalReturned: friends.length, }, pairedItem: { item: i, }, }); } else if (operation === 'findUserByUsername') { const username = this.getNodeParameter('username', i); const response = await api.findUserByUsername(username); returnData.push({ json: response, pairedItem: { item: i, }, }); } else if (operation === 'getMultiUsersByPhones') { const phonesStr = this.getNodeParameter('phones', i); const phones = phonesStr .split(',') .map((p) => p.trim()) .filter((p) => p); if (phones.length > 50) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Tối đa 50 số điện thoại được phép tìm kiếm cùng lúc', { itemIndex: i }); } const response = await api.getMultiUsersByPhones(phones); const users = Object.values(response || {}); returnData.push({ json: { status: 'Thành công', users: users, totalRequested: phones.length, totalFound: users.length, }, pairedItem: { item: i, }, }); } else if (operation === 'getFriendRecommendations') { const response = await api.getFriendRecommendations(); returnData.push({ json: { status: 'Thành công', totalItems: ((_e = response.recommItems) === null || _e === void 0 ? void 0 : _e.length) || 0, recommendations: response.recommItems || [], expiredDuration: response.expiredDuration, }, pairedItem: { item: i, }, }); } } else if (resource === 'account') { if (operation === 'getUserInfo') { const userId = this.getNodeParameter('userId', i); const response = await api.getUserInfo(userId); returnData.push({ json: response, pairedItem: { item: i, }, }); } else if (operation === 'fetchAccountInfo') { const response = await api.fetchAccountInfo(); returnData.push({ json: { status: 'Thành công', accountInfo: response, }, pairedItem: { item: i }, }); } else if (operation === 'changeAccountSetting') { const name = this.getNodeParameter('name', i); const dob = this.getNodeParameter('dob', i); const gender = this.getNodeParameter('gender', i); const response = await api.updateProfile({ profile: { name, dob: dob, gender: gender, }, }); returnData.push({ json: { status: 'Thành công', response: response, }, pairedItem: { item: i, }, }); } else if (operation === 'updateLang') { const language = this.getNodeParameter('language', i); const response = await api.updateLang(language); returnData.push({ json: { status: 'Thành công', message: `Đã đổi ngôn ngữ sang ${language}`, language: language, response: response, }, pairedItem: { item: i }, }); } else if (operation === 'updateProfileBio') { const bio = this.getNodeParameter('bio', i); const response = await api.updateProfileBio(bio); returnData.push({ json: { status: 'Thành công', bio, response, }, pairedItem: { item: i }, }); } else if (operation === 'changeAccountAvatar') { const avatarUrl = this.getNodeParameter('avatarUrl', i); const response = await api.changeAccountAvatar(avatarUrl); returnData.push({ json: { status: 'Thành công', avatarUrl, response, }, pairedItem: { item: i }, }); } else if (operation === 'getSettings') { const response = await api.getSettings(); returnData.push({ json: { status: 'Thành công', settings: response, }, pairedItem: { item: i }, }); } else if (operation === 'updateSettings') { const settingType = this.getNodeParameter('settingType', i); const settingValue = this.getNodeParameter('settingValue', i); const response = await api.updateSettings(settingType, settingValue); returnData.push({ json: { status: 'Thành công', settingType, settingValue, response, }, pairedItem: { item: i }, }); } else if (operation === 'updateActiveStatus') { const active = this.getNodeParameter('active', i); const response = await api.updateActiveStatus(active); returnData.push({ json: { status: 'Thành công', active, response, }, pairedItem: { item: i }, }); } } else if (resource === 'privacy') { if (operation === 'blockUser') { const userId = this.getNodeParameter('userId', i); const response = await api.blockUser(userId); returnData.push({ json: { status: 'Thành công', response: response, }, pairedItem: { item: i, }, }); } else if (operation === 'unblockUser') { const userId = this.getNodeParameter('userId', i); const response = await api.unblockUser(userId); returnData.push({ json: { status: 'Thành công', response: response, }, pairedItem: { item: i, }, }); } else if (operation === 'blockViewFeed') { const userId = this.getNodeParameter('userId', i); const isBlockFeed = this.getNodeParameter('isBlockFeed', i); const response = await api.blockViewFeed(isBlockFeed, userId); returnData.push({ json: { status: 'Thành công', message: isBlockFeed ? 'Đã chặn người dùng xem bảng tin' : 'Đã bỏ chặn người dùng xem bảng tin', userId: userId, isBlocked: isBlockFeed, response: response, }, pairedItem: { item: i }, }); } else if (operation === 'sendReport') { const threadId = this.getNodeParameter('reportThreadId', i); const threadTypeNumber = this.getNodeParameter('reportThreadType', i, 0); const type = threadTypeNumber === 1 ? zca_js_1.ThreadType.Group : zca_js_1.ThreadType.User; const reason = this.getNodeParameter('reportReason', i); const options = reason === zca_js_1.ReportReason.Other ? { reason: zca_js_1.ReportReason.Other, content: this.getNodeParameter('reportContent', i, '') } : { reason }; const response = await api.sendReport(options, threadId, type); returnData.push({ json: { status: 'Thành công', threadId, reason, response, }, pairedItem: { item: i }, }); } } else if (resource === 'alias') { if (operation === 'changeAliasName') { const userId = this.getNodeParameter('userId', i); const aliasName = this.getNodeParameter('aliasName', i); const response = await api.changeFriendAlias(aliasName, userId); returnData.push({ json: { status: 'Thành công', response: response, }, pairedItem: { item: i, }, }); } else if (operation === 'removeFriendAlias') { const userId = this.getNodeParameter('userId', i); const response = await api.removeFriendAlias(userId); returnData.push({ json: { status: 'Thành công', message: 'Đã xóa tên gợi nhớ', userId: userId, response: response, }, pairedItem: { item: i }, }); } else if (operation === 'getAliasList') { const count = this.getNodeParameter('count', i); const page = this.getNodeParameter('page', i); const response = await api.getAliasList(count, page); returnData.push({ json: { status: 'Thành công', totalItems: ((_f = response.items) === null || _f === void 0 ? void 0 : _f.length) || 0, updateTime: response.updateTime, items: response.items || [], }, pairedItem: { item: i }, }); } } else if (resource === 'avatar') { if (operation === 'getAvatarList') { const count = this.getNodeParameter('count', i); const page = this.getNodeParameter('page', i); const response = await api.getAvatarList(count, page); returnData.push({ json: { status: 'Thành công', albumId: response.albumId, hasMore: response.hasMore === 1, totalPhotos: ((_g = response.photos) === null || _g === void 0 ? void 0 : _g.length) || 0, photos: response.photos || [], }, pairedItem: { item: i }, }); } else if (operation === 'getAvatarUrlProfile') { const userId = this.getNodeParameter('userId', i); const useLargeAvatar = this.getNodeParameter('avatarSize', i, false); const response = await api.getAvatarUrlProfile(userId, useLargeAvatar ? zca_js_1.AvatarSize.Large : zca_js_1.AvatarSize.Small); returnData.push({ json: { status: 'Thành công', userId: userId, avatarUrl: (_h = response[userId]) === null || _h === void 0 ? void 0 : _h.avatar, }, pairedItem: { item: i }, }); } else if (operation === 'getFullAvatar') { const userId = this.getNodeParameter('userId', i); const response = await api.getFullAvatar(userId); returnData.push({ json: { status: 'Thành công', userId: userId, avatarData: response, }, pairedItem: { item: i }, }); } else if (operation === 'reuseAvatar') { const photoId = this.getNodeParameter('photoId', i); const response = await api.reuseAvatar(photoId); returnData.push({ json: { status: 'Thành công', message: 'Đã đổi lại ảnh đại diện cũ', photoId: photoId, response: response, }, pairedItem: { item: i }, }); } else if (operation === 'deleteAvatar') { const photoIds = this.getNodeParameter('photoIds', i); const photoIdArray = photoIds .split(',') .map((id) => id.trim()) .filter((id) => id); const response = await api.deleteAvatar(photoIdArray); const successCount = ((_j = response.delPhotoIds) === null || _j === void 0 ? void 0 : _j.length) || 0; const failedIds = Object.keys(response.errMap || {}); returnData.push({ json: { status: successCount > 0 ? 'Thành công' : 'Thất bại', totalRequested: photoIdArray.length, successCount: successCount, failedCount: failedIds.length, deletedPhotoIds: response.delPhotoIds || [], errors: response.errMap || {}, }, pairedItem: { item: i }, }); } } else if (resource === 'message') { if (operation === 'undoMessage') { const threadId = this.getNodeParameter('threadId', i); const type = this.getNodeParameter('threadType', i); const msgId = this.getNodeParameter('msgId', i); const cliMsgId = this.getNodeParameter('cliMsgId', i); const UndoOptions = { msgId: msgId, cliMsgId: cliMsgId, }; const response = await api.undo(UndoOptions, threadId, type); returnData.push({ json: { status: 'Thành công', response: response, }, pairedItem: { item: i, }, }); } else if (operation === 'addReaction') { const threadId = this.getNodeParameter('reactionThreadId', i); const threadTypeNumber = this.getNodeParameter('reactionThreadType', i, 0); const type = threadTypeNumber === 1 ? zca_js_1.ThreadType.Group : zca_js_1.ThreadType.User; const msgId = this.getNodeParameter('reactionMsgId', i); const cliMsgId = this.getNodeParameter('reactionCliMsgId', i); const icon = this.getNodeParameter('reactionIcon', i); const response = await api.addReaction(zca_js_1.Reactions[icon], { data: { msgId, cliMsgId }, threadId, type, }); returnData.push({ json: { status: 'Thành công', threadId, icon, response, }, pairedItem: { item: i }, }); } else if (operation === 'forwardMessage') { const message = this.getNodeParameter('forwardMessageContent', i); const threadIdsRaw = this.getNodeParameter('forwardThreadIds', i); const threadTypeNumber = this.getNodeParameter('forwardThreadType', i, 0); const type = threadTypeNumber === 1 ? zca_js_1.ThreadType.Group : zca_js_1.ThreadType.User; const threadIds = threadIdsRaw .split(',') .map((id) => id.trim()) .filter((id) => id); if (!message || message.trim() === '') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Nội dung tin nhắn không được để trống', { itemIndex: i, }); } if (threadIds.length === 0) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Danh sách ID đích không được để trống', { itemIndex: i }); } const response = await api.forwardMessage({ message }, threadIds, type); returnData.push({ json: { status: 'Thành công', threadIds, success: response.success, fail: response.fail, }, pairedItem: { item: i }, }); } else if (operation === 'deleteMessage') { const threadId = this.getNodeParameter('deleteThreadId', i); const threadTypeNumber = this.getNodeParameter('deleteThreadType', i, 0); const type = threadTypeNumber === 1 ? zca_js_1.ThreadType.Group : zca_js_1.ThreadType.User; const msgId = this.getNodeParameter('deleteMsgId', i); const cliMsgId = this.getNodeParameter('deleteCliMsgId', i); const uidFrom = this.getNodeParameter('deleteUidFrom', i); const onlyMe = this.getNodeParameter('deleteOnlyMe', i, true); const response = await api.deleteMessage({ data: { cliMsgId, msgId, uidFrom }, threadId, type, }, onlyMe); returnData.push({ json: { status: 'Thành công', threadId, msgId, onlyMe, response, }, pairedItem: { item: i }, }); } else if (operation === 'sendSeenEvent') { const threadTypeNumber = this.getNodeParameter('seenThreadType', i, 0); const type = threadTypeNumber === 1 ? zca_js_1.ThreadType.Group : zca_js_1.ThreadType.User; const messages = this.getNodeParameter('seenMessages', i); const response = await api.sendSeenEvent(messages, type); returnData.push({ json: { status: 'Thành công', response, }, pairedItem: { item: i }, }); } else if (operation === 'sendDeliveredEvent') { const threadTypeNumber = this.getNodeParameter('deliveredThreadType', i, 0); const type = threadTypeNumber === 1 ? zca_js_1.ThreadType.Group : zca_js_1.ThreadType.User; const isSeen = this.getNodeParameter('deliveredIsSeen', i, false); const messages = this.getNodeParameter('deliveredMessages', i); const response = await api.sendDeliveredEvent(isSeen, messages, type); returnData.push({ json: { status: 'Thành công', isSeen, response, }, pairedItem: { item: i }, }); } } else if (resource === 'system') { if (operation === 'keepAlive') { const response = await api.keepAlive(); returnData.push({ json: { status: 'Thành công', message: 'Session đã được làm mới', response: response, }, pairedItem: { item: i }, }); } else if (operation === 'lastOnline') { const userId = this.getNodeParameter('userId', i); const response = await api.lastOnline(userId); returnData.push({ json: { status: 'Thành công', userId: userId, lastOnline: response, }, pairedItem: { item: i }, }); } else if (operation === 'parseLink') { const link = this.getNodeParameter('linkToParse', i); const response = await api.parseLink(link); returnData.push({ json: { status: 'Thành công', link, data: response.data, errorMaps: response.error_maps, }, pairedItem: { item: i }, }); } else if (operation === 'getCookie') { const cookieJar = api.getCookie().toJSON(); returnData.push({ json: { status: 'Thành công', warning: 'Cookie này cấp quyền truy cập đầy đủ vào tài khoản Zalo. Không chia sẻ, không lưu vào workflow công khai, và lưu ý nó sẽ tồn tại dạng plaintext trong execution log của n8n.', cookie: cookieJar, }, pairedItem: { item: i }, }); } } } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message, }, pairedItem: { item: i, }, }); continue; } throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i, }); } } return [returnData]; } } exports.ZaloUser = ZaloUser; //# sourceMappingURL=ZaloUser.node.js.map