n8n-nodes-zuckzapgo
Version:
n8n community nodes for ZuckZapGo - WhatsApp Multi-Device REST API
767 lines • 39.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZuckZapGoAdmin = void 0;
class ZuckZapGoAdmin {
constructor() {
this.description = {
displayName: 'ZuckZapGo Admin',
name: 'zuckzapgoAdmin',
icon: 'file:zuckzapgo.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"]}}',
description: 'Administrative operations for ZuckZapGo WhatsApp API',
defaults: {
name: 'ZuckZapGo Admin',
},
inputs: ["main" /* NodeConnectionType.Main */],
outputs: ["main" /* NodeConnectionType.Main */],
credentials: [
{
name: 'zuckzapgoAdminApi',
required: true,
},
],
properties: [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Create User',
value: 'createUser',
description: 'Create a new user',
action: 'Create user',
},
{
name: 'Delete User',
value: 'deleteUser',
description: 'Delete a user from database',
action: 'Delete user',
},
{
name: 'Delete User Full',
value: 'deleteUserFull',
description: 'Delete user completely (DB, S3, logout)',
action: 'Delete user completely',
},
{
name: 'Get Global Configuration',
value: 'getGlobalConfiguration',
description: 'Get current global configuration and env vars',
action: 'Get global configuration',
},
{
name: 'Get Global Stats',
value: 'getGlobalStats',
description: 'Get global system statistics',
action: 'Get global statistics',
},
{
name: 'List Users',
value: 'listUsers',
description: 'List all users',
action: 'List users',
},
{
name: 'Reload Global Config',
value: 'reloadGlobalConfig',
description: 'Reload global configurations from environment',
action: 'Reload global config',
},
{
name: 'Send Global Test Event',
value: 'sendGlobalTestEvent',
description: 'Send test event through global systems',
action: 'Send global test event',
},
{
name: 'Test Global Systems',
value: 'testGlobalSystems',
description: 'Test global webhook and RabbitMQ systems',
action: 'Test global systems',
},
],
default: 'listUsers',
},
// Create User
{
displayName: 'User Name',
name: 'userName',
type: 'string',
default: '',
placeholder: 'John Doe',
description: 'Name of the user',
required: true,
displayOptions: {
show: {
operation: ['createUser'],
},
},
},
{
displayName: 'User Token',
name: 'userToken',
type: 'string',
typeOptions: { password: true },
default: '',
placeholder: 'e.g. Z1234ABCCXD',
description: 'Authentication token for the user',
required: true,
displayOptions: {
show: {
operation: ['createUser'],
},
},
},
{
displayName: 'Additional Options',
name: 'additionalOptions',
type: 'collection',
placeholder: 'Add Option',
default: {},
displayOptions: {
show: {
operation: ['createUser'],
},
},
options: [
{
displayName: 'Webhook URL',
name: 'webhook',
type: 'string',
default: '',
placeholder: 'https://webhook.site/1234567890',
description: 'Webhook URL to receive events',
},
{
displayName: 'Events',
name: 'events',
type: 'string',
default: 'All',
placeholder: 'e.g. All, Message, Presence',
description: 'Events to subscribe to',
},
{
displayName: 'Expiration',
name: 'expiration',
type: 'number',
default: 0,
description: 'User expiration timestamp (0 for no expiration)',
},
// Skip Options
{
displayName: 'Skip Media Download',
name: 'skipMedia',
type: 'boolean',
default: false,
description: 'Whether to skip downloading media files',
},
{
displayName: 'Skip Groups',
name: 'skipGroups',
type: 'boolean',
default: false,
description: 'Whether to skip group messages',
},
{
displayName: 'Skip Newsletters',
name: 'skipNewsletters',
type: 'boolean',
default: false,
description: 'Whether to skip newsletter messages',
},
{
displayName: 'Skip Broadcasts',
name: 'skipBroadcasts',
type: 'boolean',
default: false,
description: 'Whether to skip broadcast messages',
},
{
displayName: 'Skip Own Messages',
name: 'skipOwnMessages',
type: 'boolean',
default: false,
description: 'Whether to skip own sent messages',
},
{
displayName: 'Skip Calls',
name: 'skipCalls',
type: 'boolean',
default: false,
description: 'Whether to auto-reject incoming calls',
},
{
displayName: 'Call Reject Message',
name: 'callRejectMessage',
type: 'string',
default: 'Sorry, I cannot take calls at the moment.',
description: 'Message to send when rejecting calls',
displayOptions: {
show: {
'/skipCalls': [true],
},
},
},
{
displayName: 'Call Reject Type',
name: 'callRejectType',
type: 'options',
default: 'busy',
options: [
{
name: 'Busy',
value: 'busy',
},
{
name: 'Declined',
value: 'declined',
},
{
name: 'Unavailable',
value: 'unavailable',
},
],
description: 'Type of call rejection',
displayOptions: {
show: {
'/skipCalls': [true],
},
},
},
// Proxy Configuration
{
displayName: 'Proxy Configuration',
name: 'proxyConfig',
type: 'fixedCollection',
default: {},
description: 'Proxy settings for the user',
options: [
{
name: 'proxy',
displayName: 'Proxy',
values: [
{
displayName: 'Enabled',
name: 'enabled',
type: 'boolean',
default: false,
description: 'Whether to enable proxy',
},
{
displayName: 'Proxy URL',
name: 'proxyURL',
type: 'string',
default: '',
placeholder: 'socks5://user:pass@host:port',
description: 'Proxy URL (socks5:// or http://)',
},
],
},
],
},
// S3 Configuration
{
displayName: 'S3 Configuration',
name: 's3Config',
type: 'fixedCollection',
default: {},
description: 'S3 storage settings for the user',
options: [
{
name: 's3',
displayName: 'S3',
values: [
{
displayName: 'Access Key',
name: 'accessKey',
type: 'string',
default: '',
description: 'S3 access key ID',
},
{
displayName: 'Bucket',
name: 'bucket',
type: 'string',
default: '',
description: 'S3 bucket name',
},
{
displayName: 'Enabled',
name: 'enabled',
type: 'boolean',
default: false,
description: 'Whether to enable S3',
},
{
displayName: 'Endpoint',
name: 'endpoint',
type: 'string',
default: 'https://s3.amazonaws.com',
description: 'S3 endpoint URL',
},
{
displayName: 'Media Delivery',
name: 'mediaDelivery',
type: 'options',
default: 'both',
options: [
{
name: 'Base64',
value: 'base64',
},
{
name: 'S3',
value: 's3',
},
{
name: 'Both',
value: 'both',
},
],
description: 'Media delivery method',
},
{
displayName: 'Path Style',
name: 'pathStyle',
type: 'boolean',
default: false,
description: 'Whether to use path style URLs',
},
{
displayName: 'Public URL',
name: 'publicURL',
type: 'string',
default: '',
description: 'Public URL for accessing files',
},
{
displayName: 'Region',
name: 'region',
type: 'string',
default: 'us-east-1',
description: 'S3 region',
},
{
displayName: 'Retention Days',
name: 'retentionDays',
type: 'number',
default: 30,
description: 'Days to retain files',
},
{
displayName: 'Secret Key',
name: 'secretKey',
type: 'string',
typeOptions: { password: true },
default: '',
description: 'S3 secret access key',
},
],
},
],
},
// RabbitMQ Configuration
{
displayName: 'RabbitMQ Configuration',
name: 'rabbitmqConfig',
type: 'fixedCollection',
default: {},
description: 'RabbitMQ configuration for the user. Use {user_id} and {event_type} placeholders in queue/routing_key patterns. System automatically creates event-specific queues as events arrive.',
options: [
{
name: 'rabbitmq',
displayName: 'RabbitMQ',
values: [
{
displayName: 'Auto Delete',
name: 'autoDelete',
type: 'boolean',
default: false,
description: 'Whether to auto-delete when unused',
},
{
displayName: 'Delivery Mode',
name: 'deliveryMode',
type: 'options',
default: 2,
options: [
{
name: 'Non-Persistent (1)',
value: 1
},
{
name: 'Persistent (2)',
value: 2
},
],
description: 'Message delivery mode',
},
{
displayName: 'Durable',
name: 'durable',
type: 'boolean',
default: true,
description: 'Whether exchange and queue should be durable',
},
{
displayName: 'Enabled',
name: 'enabled',
type: 'boolean',
default: false,
description: 'Whether to enable RabbitMQ',
},
{
displayName: 'Events',
name: 'events',
type: 'string',
default: 'All',
placeholder: 'e.g. All, Message, Presence',
description: 'Events to subscribe to',
},
{
displayName: 'Exchange',
name: 'exchange',
type: 'string',
default: 'whatsapp.events',
placeholder: 'e.g. whatsapp.events',
description: 'RabbitMQ exchange name',
},
{
displayName: 'Exchange Type',
name: 'exchangeType',
type: 'options',
default: 'topic',
options: [
{
name: 'Topic',
value: 'topic',
},
{
name: 'Direct',
value: 'direct',
},
{
name: 'Fanout',
value: 'fanout',
},
{
name: 'Headers',
value: 'headers',
},
],
},
{
displayName: 'Exclusive',
name: 'exclusive',
type: 'boolean',
default: false,
description: 'Whether queue should be exclusive',
},
{
displayName: 'No Wait',
name: 'noWait',
type: 'boolean',
default: false,
description: 'Whether to wait for server confirmation',
},
{
displayName: 'Queue',
name: 'queue',
type: 'string',
default: 'user_{user_id}_event_{event_type}',
placeholder: 'e.g. user_{user_id}_event_{event_type}',
description: 'Queue name pattern. Use placeholders {user_id} and {event_type}. System automatically creates event-specific queues as events arrive. Examples: user_abc123_event_Message, user_abc123_event_Receipt',
},
{
displayName: 'Queue Type',
name: 'queueType',
type: 'options',
default: 'classic',
options: [
{
name: 'Classic',
value: 'classic',
},
{
name: 'Quorum',
value: 'quorum',
},
{
name: 'Stream',
value: 'stream',
},
],
},
{
displayName: 'Routing Key',
name: 'routingKey',
type: 'string',
default: 'whatsapp.{user_id}.{event_type}',
placeholder: 'e.g. whatsapp.{user_id}.{event_type}',
description: 'Routing key pattern. Use placeholders {user_id} and {event_type}. Examples: whatsapp.abc123.Message, whatsapp.abc123.Receipt, whatsapp.abc123.Presence',
},
{
displayName: 'URL',
name: 'url',
type: 'string',
default: '',
placeholder: 'amqp://user:password@localhost:5672/',
description: 'RabbitMQ connection URL',
},
],
},
],
},
],
},
// Delete User
{
displayName: 'User ID',
name: 'userId',
type: 'string',
default: '',
placeholder: 'e.g. 4e4942c7dee1deef99ab8fd9f7350de5',
description: 'ID of the user to delete',
required: true,
displayOptions: {
show: {
operation: ['deleteUser', 'deleteUserFull'],
},
},
},
// Send Global Test Event
{
displayName: 'Event Type',
name: 'eventType',
type: 'string',
default: 'TestEvent',
placeholder: 'e.g. TestEvent, Message, Connected',
description: 'Type of event to send',
required: true,
displayOptions: {
show: {
operation: ['sendGlobalTestEvent'],
},
},
},
{
displayName: 'User ID',
name: 'testUserId',
type: 'string',
default: 'admin-test',
placeholder: 'e.g. admin-test',
description: 'User ID for the test event',
required: true,
displayOptions: {
show: {
operation: ['sendGlobalTestEvent'],
},
},
},
{
displayName: 'Test Data',
name: 'testData',
type: 'json',
default: '{"message": "test event", "timestamp": "2024-01-01T00:00:00Z"}',
description: 'Custom data for the test event (JSON format)',
displayOptions: {
show: {
operation: ['sendGlobalTestEvent'],
},
},
},
],
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
const credentials = await this.getCredentials('zuckzapgoAdminApi');
for (let i = 0; i < items.length; i++) {
try {
const operation = this.getNodeParameter('operation', i);
let responseData;
// Admin API request helper
const adminApiRequest = async (method, endpoint, body, qs) => {
const options = {
method: method,
url: `${credentials.url}${endpoint}`,
headers: {
'Authorization': credentials.adminToken,
'Content-Type': 'application/json',
},
json: true,
body,
qs,
};
return await this.helpers.httpRequest(options);
};
if (operation === 'listUsers') {
responseData = await adminApiRequest('GET', '/admin/users');
}
else if (operation === 'createUser') {
const name = this.getNodeParameter('userName', i);
const token = this.getNodeParameter('userToken', i);
const additionalOptions = this.getNodeParameter('additionalOptions', i);
const body = {
name,
token,
};
// Basic options
if (additionalOptions.webhook) {
body.webhook = additionalOptions.webhook;
}
if (additionalOptions.events) {
body.events = additionalOptions.events;
}
if (additionalOptions.expiration) {
body.expiration = additionalOptions.expiration;
}
// Skip options
if (additionalOptions.skipMedia !== undefined) {
body.skipMedia = additionalOptions.skipMedia;
}
if (additionalOptions.skipGroups !== undefined) {
body.skipGroups = additionalOptions.skipGroups;
}
if (additionalOptions.skipNewsletters !== undefined) {
body.skipNewsletters = additionalOptions.skipNewsletters;
}
if (additionalOptions.skipBroadcasts !== undefined) {
body.skipBroadcasts = additionalOptions.skipBroadcasts;
}
if (additionalOptions.skipOwnMessages !== undefined) {
body.skipOwnMessages = additionalOptions.skipOwnMessages;
}
if (additionalOptions.skipCalls !== undefined) {
body.skipCalls = additionalOptions.skipCalls;
}
if (additionalOptions.callRejectMessage) {
body.callRejectMessage = additionalOptions.callRejectMessage;
}
if (additionalOptions.callRejectType) {
body.callRejectType = additionalOptions.callRejectType;
}
// Proxy config
if (additionalOptions.proxyConfig) {
const proxyConfigWrapper = additionalOptions.proxyConfig;
const proxyConfig = proxyConfigWrapper.proxy || proxyConfigWrapper;
if (proxyConfig) {
const config = Array.isArray(proxyConfig) ? proxyConfig[0] : proxyConfig;
if (config) {
body.proxyConfig = {
Enabled: config.enabled || false,
ProxyURL: config.proxyURL || '',
};
}
}
}
// S3 config
if (additionalOptions.s3Config) {
const s3ConfigWrapper = additionalOptions.s3Config;
const s3Config = s3ConfigWrapper.s3 || s3ConfigWrapper;
if (s3Config) {
const config = Array.isArray(s3Config) ? s3Config[0] : s3Config;
if (config) {
body.s3Config = {
Enabled: config.enabled || false,
Endpoint: config.endpoint || '',
Region: config.region || 'us-east-1',
Bucket: config.bucket || '',
AccessKey: config.accessKey || '',
SecretKey: config.secretKey || '',
PathStyle: config.pathStyle || false,
PublicURL: config.publicURL || '',
MediaDelivery: config.mediaDelivery || 'both',
RetentionDays: config.retentionDays || 30,
};
}
}
}
// RabbitMQ config
if (additionalOptions.rabbitmqConfig) {
const rabbitmqConfigWrapper = additionalOptions.rabbitmqConfig;
const rabbitmqConfig = rabbitmqConfigWrapper.rabbitmq || rabbitmqConfigWrapper;
if (rabbitmqConfig) {
const config = Array.isArray(rabbitmqConfig) ? rabbitmqConfig[0] : rabbitmqConfig;
if (config) {
body.rabbitmqConfig = {
Enabled: config.enabled || false,
URL: config.url || '',
Exchange: config.exchange || '',
ExchangeType: config.exchangeType || 'topic',
Queue: config.queue || '',
QueueType: config.queueType || 'classic',
RoutingKey: config.routingKey || '',
Events: config.events || 'All',
Durable: config.durable !== false,
AutoDelete: config.autoDelete === true,
Exclusive: config.exclusive === true,
NoWait: config.noWait === true,
DeliveryMode: config.deliveryMode || 2,
};
}
}
}
responseData = await adminApiRequest('POST', '/admin/users', body);
}
else if (operation === 'deleteUser') {
const userId = this.getNodeParameter('userId', i);
responseData = await adminApiRequest('DELETE', `/admin/users/${userId}`);
}
else if (operation === 'deleteUserFull') {
const userId = this.getNodeParameter('userId', i);
responseData = await adminApiRequest('DELETE', `/admin/users/${userId}/full`);
}
// Global System Management operations
else if (operation === 'getGlobalStats') {
responseData = await adminApiRequest('GET', '/admin/global/stats');
}
else if (operation === 'testGlobalSystems') {
responseData = await adminApiRequest('POST', '/admin/global/test');
}
else if (operation === 'reloadGlobalConfig') {
responseData = await adminApiRequest('POST', '/admin/global/config/reload');
}
else if (operation === 'sendGlobalTestEvent') {
const eventType = this.getNodeParameter('eventType', i);
const testUserId = this.getNodeParameter('testUserId', i);
const testDataStr = this.getNodeParameter('testData', i);
let testData;
try {
testData = JSON.parse(testDataStr);
}
catch (error) {
throw new Error('Test Data must be valid JSON');
}
const body = {
event_type: eventType,
user_id: testUserId,
data: testData,
};
responseData = await adminApiRequest('POST', '/admin/global/event/test', body);
}
else if (operation === 'getGlobalConfiguration') {
responseData = await adminApiRequest('GET', '/admin/global/config');
}
const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
returnData.push(...executionData);
}
catch (error) {
if (this.continueOnFail()) {
const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
returnData.push(...executionErrorData);
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.ZuckZapGoAdmin = ZuckZapGoAdmin;
//# sourceMappingURL=ZuckZapGoAdmin.node.js.map