@raevon/n8n-nodes-whatsapp 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,6 +48,7 @@ const baileys_1 = __importStar(require("@whiskeysockets/baileys"));
48
48
  const p_queue_1 = __importDefault(require("p-queue"));
49
49
  const node_path_1 = __importDefault(require("node:path"));
50
50
  const node_fs_1 = __importDefault(require("node:fs"));
51
+ const qrcode_1 = __importDefault(require("qrcode"));
51
52
  const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
52
53
  const randBetween = (min, max) => max > min ? min + Math.floor(Math.random() * (max - min + 1)) : min;
53
54
  // Silent logger — Baileys expects pino-compatible logger with these methods
@@ -122,8 +123,16 @@ async function scheduleReconnect(cfg) {
122
123
  }, delay);
123
124
  }
124
125
  async function initSocket(cfg, authPath) {
125
- if (socketInstance && socketStatus === 'connected')
126
- return socketInstance;
126
+ // Always create fresh socket if current one is dead
127
+ if (socketInstance && socketStatus === 'connected') {
128
+ try {
129
+ if (socketInstance.user)
130
+ return socketInstance;
131
+ }
132
+ catch {
133
+ // Socket dead, create new one
134
+ }
135
+ }
127
136
  const gen = ++generation; // #10: Snapshot generation for this connection attempt
128
137
  const resolvedPath = expandHome(authPath);
129
138
  if (!node_fs_1.default.existsSync(resolvedPath)) {
@@ -156,7 +165,7 @@ async function initSocket(cfg, authPath) {
156
165
  console.error('[WhatsApp] Failed to save credentials:', err.message);
157
166
  });
158
167
  });
159
- sock.ev.on('connection.update', (update) => {
168
+ sock.ev.on('connection.update', async (update) => {
160
169
  var _a, _b;
161
170
  if (gen !== generation)
162
171
  return; // #10: Ignore stale connection events
@@ -164,10 +173,10 @@ async function initSocket(cfg, authPath) {
164
173
  if (qr) {
165
174
  latestQr = qr;
166
175
  socketStatus = 'qr_ready';
167
- // Output quickchart URL works from anywhere, no localhost needed
176
+ // Generate QR locally using qrcode package no external service
168
177
  if (qrResolve) {
169
- const qrUrl = `https://quickchart.io/qr?text=${encodeURIComponent(qr)}&size=300`;
170
- qrResolve({ qr, qrUrl });
178
+ const qrDataUrl = await qrcode_1.default.toDataURL(qr, { width: 300, margin: 2 });
179
+ qrResolve({ qr, qrUrl: qrDataUrl });
171
180
  qrResolve = null;
172
181
  }
173
182
  }
@@ -209,8 +218,17 @@ async function getWhatsAppCredentials(credentials) {
209
218
  };
210
219
  }
211
220
  async function ensureConnected(cfg) {
212
- if (socketStatus === 'connected' && socketInstance)
213
- return socketInstance;
221
+ // Always try to use existing socket first, but verify it's actually alive
222
+ if (socketInstance && socketStatus === 'connected') {
223
+ try {
224
+ // Quick check — if socket user is set, it's alive
225
+ if (socketInstance.user)
226
+ return socketInstance;
227
+ }
228
+ catch {
229
+ // Socket is dead, reconnect below
230
+ }
231
+ }
214
232
  const antiBanCfg = {
215
233
  messageDelayMinMs: cfg.messageDelayMinMs,
216
234
  messageDelayMaxMs: cfg.messageDelayMaxMs,
@@ -227,42 +245,29 @@ async function ensureConnected(cfg) {
227
245
  if (!queue) {
228
246
  queue = new p_queue_1.default({ concurrency: 1 });
229
247
  }
230
- // Check if session already exists
248
+ // Check if session already exists on disk
231
249
  const resolvedPath = expandHome(cfg.sessionPath);
232
250
  const hasSession = node_fs_1.default.existsSync(resolvedPath) && node_fs_1.default.readdirSync(resolvedPath).length > 0;
233
- const sock = await initSocket(antiBanCfg, cfg.sessionPath);
234
- // If no session, wait for QR with a reasonable timeout
235
251
  if (!hasSession) {
236
- const qrData = await new Promise((resolve) => {
237
- qrResolve = resolve;
238
- // 90 second timeout — QR codes expire quickly, user needs to act fast
239
- setTimeout(() => {
240
- if (qrResolve) {
241
- qrResolve(null);
242
- qrResolve = null;
243
- }
244
- }, 90000);
252
+ throw new n8n_workflow_1.NodeApiError({}, {
253
+ message: 'No WhatsApp session found. Run the WhatsApp Connect node first to scan QR code.',
245
254
  });
246
- if (!qrData) {
247
- throw new n8n_workflow_1.NodeApiError({}, {
248
- message: 'QR code expired. Run the Connect node again to get a new QR code.',
249
- });
250
- }
251
- // Wait for connection to open after scan (30s timeout)
252
- await new Promise((resolve, reject) => {
253
- const timeout = setTimeout(() => reject(new Error('Connection timeout — QR was scanned but connection did not open in time')), 30000);
254
- const checkInterval = setInterval(() => {
255
- if (socketStatus === 'connected') {
256
- clearTimeout(timeout);
257
- clearInterval(checkInterval);
258
- resolve();
259
- }
260
- if (socketStatus === 'logged_out' || socketStatus === 'error') {
261
- clearTimeout(timeout);
262
- clearInterval(checkInterval);
263
- reject(new Error('Connection failed after QR scan'));
264
- }
265
- }, 1000);
255
+ }
256
+ // Session exists — connect using saved credentials (no QR needed)
257
+ const sock = await initSocket(antiBanCfg, cfg.sessionPath);
258
+ // Wait for connection to open (up to 15s)
259
+ await new Promise((resolve) => {
260
+ const check = setInterval(() => {
261
+ if (socketStatus === 'connected' || socketStatus === 'error' || socketStatus === 'logged_out') {
262
+ clearInterval(check);
263
+ resolve();
264
+ }
265
+ }, 500);
266
+ setTimeout(() => { clearInterval(check); resolve(); }, 15000);
267
+ });
268
+ if (socketStatus !== 'connected') {
269
+ throw new n8n_workflow_1.NodeApiError({}, {
270
+ message: `WhatsApp connection failed (status: ${socketStatus}). Try running Connect node again.`,
266
271
  });
267
272
  }
268
273
  return sock;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raevon/n8n-nodes-whatsapp",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "n8n community node for WhatsApp — send and receive messages with anti-ban protection via the Baileys library",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -36,10 +36,12 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@whiskeysockets/baileys": "^7.0.0-rc13",
39
- "p-queue": "^8.0.1"
39
+ "p-queue": "^8.0.1",
40
+ "qrcode": "^1.5.4"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/node": "^20.19.39",
44
+ "@types/qrcode": "^1.5.6",
43
45
  "@typescript-eslint/eslint-plugin": "^6.21.0",
44
46
  "@typescript-eslint/parser": "^6.21.0",
45
47
  "eslint": "^8.57.1",