n8n-nodes-whatsapp-multi-session
Version:
n8n node for WhatsApp Multi-Session API integration
1,061 lines • 79.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WhatsAppMultiSession = void 0;
class WhatsAppMultiSession {
constructor() {
this.description = {
displayName: 'WhatsApp Multi-Session',
name: 'whatsAppMultiSession',
icon: 'file:whatsapp.svg',
group: ['communication'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Interact with WhatsApp Multi-Session API',
defaults: {
name: 'WhatsApp Multi-Session',
},
inputs: [{ displayName: '', type: "main" /* NodeConnectionType.Main */ }],
outputs: [{ displayName: '', type: "main" /* NodeConnectionType.Main */ }],
credentials: [
{
name: 'whatsAppMultiSessionApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Session',
value: 'session',
},
{
name: 'Message',
value: 'message',
},
{
name: 'Contact',
value: 'contact',
},
{
name: 'Typing',
value: 'typing',
},
{
name: 'Webhook',
value: 'webhook',
},
],
default: 'message',
},
// Session Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['session'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a new WhatsApp session',
action: 'Create a session',
},
{
name: 'Get',
value: 'get',
description: 'Get session information',
action: 'Get a session',
},
{
name: 'List',
value: 'list',
description: 'List all sessions',
action: 'List sessions',
},
{
name: 'Login',
value: 'login',
description: 'Initiate login process. Use "Get QR Code" operation afterwards to retrieve the QR code for scanning with WhatsApp',
action: 'Login to session',
},
{
name: 'Get QR Code',
value: 'getQrCode',
description: 'Get QR code for session authentication. Returns QR code as base64 image data URL. Scan with WhatsApp on your phone to authenticate',
action: 'Get QR code',
},
{
name: 'Connect',
value: 'connect',
description: 'Connect a session (alias for Login). Use "Get QR Code" operation afterwards to retrieve the QR code',
action: 'Connect a session',
},
{
name: 'Disconnect',
value: 'disconnect',
description: 'Disconnect a session',
action: 'Disconnect a session',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a session',
action: 'Delete a session',
},
{
name: 'Check Status',
value: 'checkStatus',
description: 'Check if session is active and ready',
action: 'Check session status',
},
],
default: 'list',
},
// Message Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['message'],
},
},
options: [
{
name: 'Send Text',
value: 'sendText',
description: 'Send a text message',
action: 'Send a text message',
},
{
name: 'Send Image',
value: 'sendImage',
description: 'Send an image message',
action: 'Send an image message',
},
{
name: 'Send Document',
value: 'sendDocument',
description: 'Send a document',
action: 'Send a document',
},
{
name: 'Send Location',
value: 'sendLocation',
description: 'Send a location',
action: 'Send a location',
},
{
name: 'Forward Message',
value: 'forwardMessage',
description: 'Forward an existing message',
action: 'Forward a message',
},
{
name: 'Reply to Message',
value: 'replyMessage',
description: 'Reply to a specific message',
action: 'Reply to a message',
},
{
name: 'Mark as Read',
value: 'markAsRead',
description: 'Mark a message as read (send blue tick)',
action: 'Mark message as read',
},
{
name: 'Download Image',
value: 'downloadImage',
description: 'Download an image from a received message',
action: 'Download an image',
},
],
default: 'sendText',
},
// Contact Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['contact'],
},
},
options: [
{
name: 'List',
value: 'list',
description: 'List contacts',
action: 'List contacts',
},
{
name: 'Check',
value: 'check',
description: 'Check if number is on WhatsApp',
action: 'Check contact',
},
],
default: 'list',
},
// Typing Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['typing'],
},
},
options: [
{
name: 'Start Typing',
value: 'startTyping',
description: 'Show typing indicator',
action: 'Start typing indicator',
},
{
name: 'Stop Typing',
value: 'stopTyping',
description: 'Hide typing indicator',
action: 'Stop typing indicator',
},
],
default: 'startTyping',
},
// Webhook Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['webhook'],
},
},
options: [
{
name: 'Set URL',
value: 'setUrl',
description: 'Set webhook URL for receiving messages',
action: 'Set webhook URL',
},
{
name: 'Get URL',
value: 'getUrl',
description: 'Get current webhook URL',
action: 'Get webhook URL',
},
{
name: 'Remove',
value: 'remove',
description: 'Remove webhook URL',
action: 'Remove webhook',
},
],
default: 'setUrl',
},
// Session ID field (used by most operations)
{
displayName: 'Session ID',
name: 'sessionId',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message', 'contact', 'typing', 'webhook'],
},
},
default: '',
placeholder: 'session_123',
description: 'The WhatsApp session ID',
},
// Session ID field for session operations (get, login, getQrCode, connect, disconnect, delete, checkStatus)
{
displayName: 'Session ID',
name: 'sessionId',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['session'],
operation: ['get', 'login', 'getQrCode', 'connect', 'disconnect', 'delete', 'checkStatus'],
},
},
default: '',
placeholder: 'session_123',
description: 'The WhatsApp session ID',
hint: 'Use "Create" operation first to get a session ID, or use "List" to see existing sessions',
},
// Session creation fields
{
displayName: 'Session Name',
name: 'sessionName',
type: 'string',
displayOptions: {
show: {
resource: ['session'],
operation: ['create'],
},
},
default: '',
placeholder: 'My WhatsApp Session',
description: 'Display name for the session',
},
// Message fields
{
displayName: 'Phone Number',
name: 'phoneNumber',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
},
},
default: '',
placeholder: '6281234567890',
description: 'Recipient phone number (with country code, no +)',
},
{
displayName: 'Message Text',
name: 'messageText',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['sendText'],
},
},
default: '',
placeholder: 'Hello from n8n!',
description: 'The text message to send',
},
{
displayName: 'Image URL',
name: 'imageUrl',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['sendImage'],
},
},
default: '',
placeholder: 'https://example.com/image.jpg',
description: 'URL of the image to send',
},
{
displayName: 'Caption',
name: 'caption',
type: 'string',
displayOptions: {
show: {
resource: ['message'],
operation: ['sendImage'],
},
},
default: '',
placeholder: 'Image caption',
description: 'Optional caption for the image',
},
{
displayName: 'Document URL',
name: 'documentUrl',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['sendDocument'],
},
},
default: '',
placeholder: 'https://example.com/document.pdf',
description: 'URL of the document to send',
},
{
displayName: 'Filename',
name: 'filename',
type: 'string',
displayOptions: {
show: {
resource: ['message'],
operation: ['sendDocument'],
},
},
default: '',
placeholder: 'document.pdf',
description: 'Optional filename for the document',
},
{
displayName: 'Latitude',
name: 'latitude',
type: 'number',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['sendLocation'],
},
},
default: 0,
placeholder: '-6.2088',
description: 'Latitude coordinate',
},
{
displayName: 'Longitude',
name: 'longitude',
type: 'number',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['sendLocation'],
},
},
default: 0,
placeholder: '106.8456',
description: 'Longitude coordinate',
},
{
displayName: 'Location Name',
name: 'locationName',
type: 'string',
displayOptions: {
show: {
resource: ['message'],
operation: ['sendLocation'],
},
},
default: '',
placeholder: 'Jakarta, Indonesia',
description: 'Optional name for the location',
},
// Forward message fields
{
displayName: 'Message ID to Forward',
name: 'forwardMessageId',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['forwardMessage'],
},
},
default: '',
placeholder: '3EB0D136B13F32830F7B88',
description: 'ID of the message to forward (from webhook trigger data: {{$json.id}}). Must be from the same session.',
},
{
displayName: 'Message Text',
name: 'forwardMessageText',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['forwardMessage'],
},
},
default: '',
placeholder: 'Hello, this is the message content to forward',
description: 'The text content of the message to forward (from webhook trigger data: {{$json.message.text || $json.message.conversation}})',
},
// Reply message fields
{
displayName: 'Reply Text',
name: 'replyText',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['replyMessage'],
},
},
default: '',
placeholder: 'Thank you for your message!',
description: 'The reply message text',
},
{
displayName: 'Quoted Message ID',
name: 'quotedMessageId',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['replyMessage'],
},
},
default: '',
placeholder: '3EB0D136B13F32830F7B88',
description: 'ID of the message to reply to (from webhook trigger data: {{$json.id}}). Must be from the same session.',
},
{
displayName: 'Message ID',
name: 'messageId',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['markAsRead'],
},
},
default: '',
placeholder: '3EB0D136B13F32830F7B88',
description: 'ID of the message to mark as read (from webhook trigger data: {{$json.id}}). Must be from the same session.',
},
// Download Image fields
{
displayName: 'Media URL',
name: 'mediaUrl',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['message'],
operation: ['downloadImage'],
},
},
default: '',
placeholder: '/api/media/temp/filename.jpg?expires=1234567890',
description: 'Media URL from webhook trigger data ({{$json.media_url}}). This should be the temporary media URL.',
},
{
displayName: 'Output Format',
name: 'outputFormat',
type: 'options',
displayOptions: {
show: {
resource: ['message'],
operation: ['downloadImage'],
},
},
options: [
{
name: 'Base64',
value: 'base64',
description: 'Return image as base64 encoded string',
},
{
name: 'Binary',
value: 'binary',
description: 'Return image as binary data buffer',
},
{
name: 'File',
value: 'file',
description: 'Return image as downloadable file attachment',
},
],
default: 'base64',
description: 'Format for the downloaded image data',
},
{
displayName: 'Put Output File in Field',
name: 'outputFileField',
type: 'string',
displayOptions: {
show: {
resource: ['message'],
operation: ['downloadImage'],
outputFormat: ['file'],
},
},
default: 'data',
placeholder: 'data',
description: 'Name of the binary property to write the file to',
},
// Contact check field
{
displayName: 'Phone Number',
name: 'phoneNumber',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['contact'],
operation: ['check'],
},
},
default: '',
placeholder: '6281234567890',
description: 'Phone number to check (with country code, no +)',
},
// Typing fields
{
displayName: 'Phone Number',
name: 'phoneNumber',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['typing'],
},
},
default: '',
placeholder: '6281234567890',
description: 'Phone number to send typing indicator to (with country code, no +)',
},
// Webhook fields
{
displayName: 'Webhook URL',
name: 'webhookUrl',
type: 'string',
required: true,
displayOptions: {
show: {
resource: ['webhook'],
operation: ['setUrl'],
},
},
default: '',
placeholder: 'https://your-server.com/webhook',
description: 'URL to receive webhook notifications',
},
],
};
}
async execute() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
const items = this.getInputData();
const returnData = [];
const credentials = await this.getCredentials('whatsAppMultiSessionApi');
const baseUrl = credentials.serverUrl;
// Use API key for authentication
const authHeaders = {
'Authorization': `Bearer ${credentials.apiKey}`,
'Content-Type': 'application/json',
};
// Helper function for handling message sending with proper error handling
const handleMessageSending = async (url, body, sessionId, operationType) => {
var _a, _b;
try {
const response = await this.helpers.request({
method: 'POST',
url: url,
headers: authHeaders,
body: body,
json: true,
resolveWithFullResponse: true,
simple: false,
});
// Handle successful response
if (response.statusCode === 200 || response.statusCode === 201) {
return {
success: true,
message: `${operationType} sent successfully`,
sessionId: sessionId,
operation: operationType,
...response.body,
};
}
// Handle error responses
let errorMessage = `HTTP ${response.statusCode}`;
let errorDetails = '';
let errorType = 'UNKNOWN_ERROR';
try {
const errorBody = ((_a = response.body) === null || _a === void 0 ? void 0 : _a.toString()) || '';
// Try to parse as JSON first
try {
const errorJson = JSON.parse(errorBody);
errorMessage = errorJson.message || errorJson.error || errorMessage;
errorDetails = errorJson.details || '';
errorType = errorJson.code || errorType;
}
catch (jsonError) {
// If not JSON, use plain text
errorMessage = errorBody.trim() || errorMessage;
}
}
catch (parseError) {
// If can't parse body, use status message
errorMessage = response.statusMessage || errorMessage;
}
// Handle specific error cases for message sending
if (response.statusCode === 403) {
errorType = 'SESSION_DISABLED';
errorMessage = 'Session is disabled or cannot perform operations';
errorDetails = errorDetails || 'The WhatsApp session may be disconnected, disabled, or not properly initialized. Please check the session status and try reconnecting.';
}
else if (response.statusCode === 400) {
errorType = 'BAD_REQUEST';
errorMessage = 'Bad request for message sending';
errorDetails = errorDetails || 'Check the message parameters and recipient phone number format.';
}
else if (response.statusCode === 401) {
errorType = 'AUTHENTICATION_FAILED';
errorMessage = 'Authentication failed';
errorDetails = errorDetails || 'Invalid API key or insufficient permissions.';
}
else if (response.statusCode === 404) {
errorType = 'SESSION_NOT_FOUND';
errorMessage = 'Session not found';
errorDetails = errorDetails || `The session ID '${sessionId}' was not found. Please check the session ID and ensure the session exists.`;
}
else if (response.statusCode === 429) {
errorType = 'RATE_LIMITED';
errorMessage = 'Rate limit exceeded';
errorDetails = errorDetails || 'Too many messages sent too quickly. Please wait before sending more messages.';
}
else if (response.statusCode === 500) {
errorType = 'SERVER_ERROR';
errorMessage = 'Internal server error';
errorDetails = errorDetails || 'The WhatsApp API encountered an error. Please try again later.';
}
else if (response.statusCode === 503) {
errorType = 'SERVICE_UNAVAILABLE';
errorMessage = 'Service unavailable';
errorDetails = errorDetails || 'The WhatsApp service is temporarily unavailable. Please try again later.';
}
// Return structured error response
return {
success: false,
error: true,
errorCode: response.statusCode,
errorType: errorType,
errorMessage: errorMessage,
errorDetails: errorDetails,
sessionId: sessionId,
operation: operationType,
requestBody: body,
};
}
catch (networkError) {
// Handle network errors and other exceptions
const error = networkError;
let errorMessage = 'Network error or request failed';
let errorDetails = error.message || '';
let errorType = 'NETWORK_ERROR';
// Try to extract more specific error information
if (error.code) {
errorType = 'NETWORK_ERROR';
errorMessage = `Network error: ${error.code}`;
errorDetails = errorDetails || error.code;
}
else if ((_b = error.response) === null || _b === void 0 ? void 0 : _b.statusCode) {
errorMessage = `HTTP ${error.response.statusCode}`;
errorType = 'HTTP_ERROR';
if (error.response.body) {
try {
const errorBody = error.response.body.toString();
const errorJson = JSON.parse(errorBody);
errorDetails = errorJson.message || errorJson.error || errorBody;
}
catch {
errorDetails = error.response.body.toString();
}
}
}
return {
success: false,
error: true,
errorType: errorType,
errorMessage: errorMessage,
errorDetails: errorDetails,
sessionId: sessionId,
operation: operationType,
requestBody: body,
};
}
};
// Track processed requests to avoid duplicates
const processedRequests = new Set();
for (let i = 0; i < items.length; i++) {
const resource = this.getNodeParameter('resource', i);
const operation = this.getNodeParameter('operation', i);
// Create a unique key for this request to prevent duplicates
let requestKey = '';
if (resource === 'message') {
const sessionId = this.getNodeParameter('sessionId', i);
const phoneNumber = this.getNodeParameter('phoneNumber', i);
if (operation === 'sendText') {
const messageText = this.getNodeParameter('messageText', i);
requestKey = `${resource}-${operation}-${sessionId}-${phoneNumber}-${messageText}`;
}
else if (operation === 'sendImage') {
const imageUrl = this.getNodeParameter('imageUrl', i);
const caption = this.getNodeParameter('caption', i, '');
requestKey = `${resource}-${operation}-${sessionId}-${phoneNumber}-${imageUrl}-${caption}`;
}
else {
requestKey = `${resource}-${operation}-${sessionId}-${phoneNumber}`;
}
}
else if (resource === 'session') {
// For session operations, only include sessionId if the operation requires it
if (['get', 'login', 'getQrCode', 'connect', 'disconnect', 'delete', 'checkStatus'].includes(operation)) {
const sessionId = this.getNodeParameter('sessionId', i);
requestKey = `${resource}-${operation}-${sessionId}`;
}
else {
// For operations like 'list' and 'create' that don't need sessionId
requestKey = `${resource}-${operation}`;
}
}
else {
const sessionId = this.getNodeParameter('sessionId', i);
requestKey = `${resource}-${operation}-${sessionId}`;
}
// Skip if this exact request has already been processed
if (processedRequests.has(requestKey)) {
continue;
}
processedRequests.add(requestKey);
try {
if (resource === 'session') {
if (operation === 'list') {
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/api/sessions`,
headers: authHeaders,
json: true,
});
// Handle both old format (response.sessions) and new format (response.data)
const sessions = response.sessions || response.data || [];
sessions.forEach((session) => {
returnData.push({ json: session });
});
}
else if (operation === 'create') {
const sessionName = this.getNodeParameter('sessionName', i);
const response = await this.helpers.request({
method: 'POST',
url: `${baseUrl}/api/sessions`,
headers: authHeaders,
body: {
name: sessionName,
},
json: true,
});
// Handle both old format (direct response) and new format (response.data)
const sessionData = response.data || response;
returnData.push({ json: sessionData });
}
else if (operation === 'get') {
const sessionId = this.getNodeParameter('sessionId', i);
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/api/sessions/${sessionId}`,
headers: authHeaders,
json: true,
});
// Handle both old format (direct response) and new format (response.data)
const sessionData = response.data || response;
returnData.push({ json: sessionData });
}
else if (operation === 'connect') {
const sessionId = this.getNodeParameter('sessionId', i);
const response = await this.helpers.request({
method: 'POST',
url: `${baseUrl}/api/sessions/${sessionId}/connect`,
headers: authHeaders,
json: true,
});
returnData.push({ json: response });
}
else if (operation === 'disconnect') {
const sessionId = this.getNodeParameter('sessionId', i);
const response = await this.helpers.request({
method: 'POST',
url: `${baseUrl}/api/sessions/${sessionId}/disconnect`,
headers: authHeaders,
json: true,
});
returnData.push({ json: response });
}
else if (operation === 'delete') {
const sessionId = this.getNodeParameter('sessionId', i);
const response = await this.helpers.request({
method: 'DELETE',
url: `${baseUrl}/api/sessions/${sessionId}`,
headers: authHeaders,
json: true,
});
returnData.push({ json: response });
}
else if (operation === 'checkStatus') {
const sessionId = this.getNodeParameter('sessionId', i);
try {
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/api/sessions/${sessionId}`,
headers: authHeaders,
json: true,
resolveWithFullResponse: true,
simple: false,
});
if (response.statusCode === 200) {
// Handle both old format (direct response) and new format (response.data)
const sessionData = response.data || response;
// Check if session is active based on common session status fields
const isActive = (sessionData.status === 'connected' ||
sessionData.status === 'active' ||
sessionData.state === 'CONNECTED' ||
sessionData.state === 'READY' ||
sessionData.connected === true ||
sessionData.ready === true);
const statusInfo = {
sessionId: sessionId,
isActive: isActive,
status: sessionData.status || sessionData.state || 'unknown',
connected: sessionData.connected || sessionData.ready || false,
phoneConnected: sessionData.phone_connected || false,
lastActivity: sessionData.last_activity || sessionData.lastActivity || null,
profilePicture: sessionData.profile_picture_url || sessionData.profilePicture || null,
pushname: sessionData.pushname || null,
wid: sessionData.wid || null,
me: sessionData.me || null,
rawSessionData: sessionData,
};
returnData.push({
json: {
success: true,
message: isActive ? 'Session is active and ready' : 'Session is not active',
...statusInfo,
}
});
}
else {
// Handle error responses for non-200 status codes
let errorMessage = `HTTP ${response.statusCode}`;
let errorDetails = '';
let errorType = 'SESSION_CHECK_ERROR';
try {
const errorBody = ((_a = response.body) === null || _a === void 0 ? void 0 : _a.toString()) || '';
// Try to parse as JSON first
try {
const errorJson = JSON.parse(errorBody);
errorMessage = errorJson.message || errorJson.error || errorMessage;
errorDetails = errorJson.details || '';
errorType = errorJson.code || errorType;
}
catch (jsonError) {
// If not JSON, use plain text
errorMessage = errorBody.trim() || errorMessage;
}
}
catch (parseError) {
// If can't parse body, use status message
errorMessage = response.statusMessage || errorMessage;
}
// Handle specific error cases
if (response.statusCode === 404) {
errorType = 'SESSION_NOT_FOUND';
errorMessage = 'Session not found';
errorDetails = `The session ID '${sessionId}' was not found. Please check the session ID and ensure the session exists.`;
}
else if (response.statusCode === 401) {
errorType = 'AUTHENTICATION_FAILED';
errorMessage = 'Authentication failed';
errorDetails = 'Invalid API key or insufficient permissions.';
}
else if (response.statusCode === 403) {
errorType = 'ACCESS_FORBIDDEN';
errorMessage = 'Access forbidden';
errorDetails = 'You do not have permission to access this session.';
}
returnData.push({
json: {
success: false,
error: true,
errorCode: response.statusCode,
errorType: errorType,
errorMessage: errorMessage,
errorDetails: errorDetails,
sessionId: sessionId,
isActive: false,
status: 'error',
}
});
}
}
catch (networkError) {
// Handle network errors and other exceptions
const error = networkError;
let errorMessage = 'Network error or request failed';
let errorDetails = error.message || '';
let errorType = 'NETWORK_ERROR';
// Try to extract more specific error information
if (error.code) {
errorType = 'NETWORK_ERROR';
errorMessage = `Network error: ${error.code}`;
errorDetails = errorDetails || error.code;
}
else if ((_b = error.response) === null || _b === void 0 ? void 0 : _b.statusCode) {
errorMessage = `HTTP ${error.response.statusCode}`;
errorType = 'HTTP_ERROR';
if (error.response.body) {
try {
const errorBody = error.response.body.toString();
const errorJson = JSON.parse(errorBody);
errorDetails = errorJson.message || errorJson.error || errorBody;
}
catch {
errorDetails = error.response.body.toString();
}
}
}
returnData.push({
json: {
success: false,
error: true,
errorType: errorType,
errorMessage: errorMessage,
errorDetails: errorDetails,
sessionId: sessionId,
isActive: false,
status: 'error',
}
});
}
}
else if (operation === 'login') {
// Initiate login for a session (triggers QR code generation)
const sessionId = this.getNodeParameter('sessionId', i);
try {
const response = await this.helpers.request({
method: 'POST',
url: `${baseUrl}/api/sessions/${sessionId}/login`,
headers: authHeaders,
json: true,
resolveWithFullResponse: true,
simple: false,
});
if (response.statusCode !== 200) {
let errorMessage = `HTTP ${response.statusCode}`;
let errorDetails = '';
try {
const errorBody = ((_c = response.body) === null || _c === void 0 ? void 0 : _c.toString()) || '';
const errorJson = JSON.parse(errorBody);
errorMessage = errorJson.message || errorJson.error || errorMessage;
errorDetails = errorJson.details || '';
}
catch {
errorMessage = response.statusMessage || errorMessage;
}
// Provide helpful error messages
if (errorMessage.includes('already logged in')) {
errorDetails = 'This session is already authe