waengine 1.1.2 → 1.7.3
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.
- package/FEATURES.md +618 -2
- package/README.md +400 -34
- package/package.json +5 -3
- package/src/advanced-features.js +776 -0
- package/src/client.js +415 -32
- package/src/device-manager.js +35 -10
- package/src/easy-advanced.js +673 -0
- package/src/easy-bot.js +430 -4
- package/src/index.js +17 -0
- package/src/message.js +193 -0
- package/src/multi-client.js +64 -6
- package/src/qr.js +433 -81
package/src/client.js
CHANGED
|
@@ -9,6 +9,7 @@ import { AIIntegration } from "./ai-integration.js";
|
|
|
9
9
|
import { HTTPClient } from "./http-client.js";
|
|
10
10
|
import { Scheduler } from "./scheduler.js";
|
|
11
11
|
import { PluginManager } from "./plugin-manager-fixed.js";
|
|
12
|
+
import { AdvancedGroup, AdvancedPrivacy, AdvancedAnalytics, AdvancedStatus, AdvancedBusiness, AdvancedSystem } from "./advanced-features.js";
|
|
12
13
|
|
|
13
14
|
export class WhatsAppClient {
|
|
14
15
|
constructor(options = {}) {
|
|
@@ -20,15 +21,43 @@ export class WhatsAppClient {
|
|
|
20
21
|
autoCleanup: options.autoCleanup !== false, // Auto-Cleanup bei Logout
|
|
21
22
|
autoRestart: options.autoRestart !== false, // Auto-Restart nach Logout
|
|
22
23
|
restartDelay: options.restartDelay || 5000, // 5 Sekunden Wartezeit
|
|
24
|
+
|
|
25
|
+
// QR-SPAM PREVENTION - NEU!
|
|
26
|
+
qrSpamPrevention: options.qrSpamPrevention !== false, // Anti-Spam aktiviert
|
|
27
|
+
qrDisplayInterval: options.qrDisplayInterval || 30000, // 30 Sekunden zwischen QR-Anzeigen
|
|
28
|
+
qrMaxDisplays: options.qrMaxDisplays || 5, // Max 5 QR-Anzeigen im Terminal
|
|
29
|
+
clearTerminalOnQR: options.clearTerminalOnQR !== false, // Terminal bei QR leeren
|
|
30
|
+
|
|
31
|
+
// ROBUSTE CONNECTION SETTINGS - NEU!
|
|
32
|
+
maxReconnectAttempts: options.maxReconnectAttempts || 50, // Viele Versuche
|
|
33
|
+
reconnectInterval: options.reconnectInterval || 3000, // 3 Sekunden zwischen Versuchen
|
|
34
|
+
exponentialBackoff: options.exponentialBackoff !== false, // Exponential backoff
|
|
35
|
+
maxBackoffDelay: options.maxBackoffDelay || 60000, // Max 1 Minute Wartezeit
|
|
36
|
+
heartbeatInterval: options.heartbeatInterval || 30000, // 30 Sekunden Heartbeat
|
|
37
|
+
connectionTimeout: options.connectionTimeout || 120000, // 2 Minuten Timeout (war 60s)
|
|
38
|
+
keepAlive: options.keepAlive !== false, // Keep-Alive aktiviert
|
|
39
|
+
quietHeartbeat: options.quietHeartbeat !== false, // Heartbeat-Logging deaktivieren
|
|
23
40
|
...options
|
|
24
41
|
};
|
|
25
42
|
|
|
26
43
|
// Clean initialization
|
|
27
|
-
|
|
28
44
|
this.socket = null;
|
|
29
45
|
this.isConnected = false;
|
|
30
46
|
this.eventHandlers = new Map();
|
|
31
47
|
|
|
48
|
+
// ROBUSTE CONNECTION TRACKING - NEU!
|
|
49
|
+
this.reconnectAttempts = 0;
|
|
50
|
+
this.lastConnectionTime = null;
|
|
51
|
+
this.heartbeatTimer = null;
|
|
52
|
+
this.connectionWatchdog = null;
|
|
53
|
+
this.isReconnecting = false;
|
|
54
|
+
this.connectionHealth = {
|
|
55
|
+
lastPing: null,
|
|
56
|
+
pingCount: 0,
|
|
57
|
+
failedPings: 0,
|
|
58
|
+
avgResponseTime: 0
|
|
59
|
+
};
|
|
60
|
+
|
|
32
61
|
// Session Manager
|
|
33
62
|
this.sessionManager = new SessionManager(this.options.authDir);
|
|
34
63
|
|
|
@@ -55,6 +84,13 @@ export class WhatsAppClient {
|
|
|
55
84
|
// Plugin System
|
|
56
85
|
this.plugins = new PluginManager(this);
|
|
57
86
|
|
|
87
|
+
// Offline Message Ignore System - NEU!
|
|
88
|
+
this.ignoreOfflineMessages = false;
|
|
89
|
+
this.lastOnlineTimestamp = Date.now();
|
|
90
|
+
this.connectionStartTime = null;
|
|
91
|
+
this.ignoredMessagesCount = 0; // Counter für ignorierte Messages
|
|
92
|
+
this.offlineMessageTimer = null; // Timer für finale Zusammenfassung
|
|
93
|
+
|
|
58
94
|
// Load API für Plugins
|
|
59
95
|
this.load = {
|
|
60
96
|
Plugins: async (pluginName) => {
|
|
@@ -69,12 +105,84 @@ export class WhatsAppClient {
|
|
|
69
105
|
}
|
|
70
106
|
};
|
|
71
107
|
|
|
108
|
+
// Ignore API für Offline Messages - DEINE COOLE API!
|
|
109
|
+
this.ignore = {
|
|
110
|
+
message: {
|
|
111
|
+
offline: (enabled = true) => {
|
|
112
|
+
this.ignoreOfflineMessages = enabled;
|
|
113
|
+
console.log(`📵 Offline Message Ignore: ${enabled ? 'AKTIVIERT' : 'DEAKTIVIERT'}`);
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
72
119
|
// Deine eigenen API-Objekte
|
|
73
120
|
this.get = new GetAPI(this);
|
|
74
121
|
this.add = new AddAPI(this);
|
|
75
122
|
this.kick = new KickAPI(this);
|
|
76
123
|
this.promote = new PromoteAPI(this);
|
|
77
124
|
this.demote = new DemoteAPI(this);
|
|
125
|
+
|
|
126
|
+
// ===== ADVANCED FEATURES INTEGRATION - NEU! =====
|
|
127
|
+
this.advancedGroup = new AdvancedGroup(this);
|
|
128
|
+
this.advancedPrivacy = new AdvancedPrivacy(this);
|
|
129
|
+
this.advancedAnalytics = new AdvancedAnalytics(this);
|
|
130
|
+
this.advancedStatus = new AdvancedStatus(this);
|
|
131
|
+
this.advancedBusiness = new AdvancedBusiness(this);
|
|
132
|
+
this.advancedSystem = new AdvancedSystem(this);
|
|
133
|
+
|
|
134
|
+
// Convenience Methods für Advanced Features
|
|
135
|
+
this.group = {
|
|
136
|
+
setSettings: this.advancedGroup.setGroupSettings.bind(this.advancedGroup),
|
|
137
|
+
setDescription: this.advancedGroup.setGroupDescription.bind(this.advancedGroup),
|
|
138
|
+
setSubject: this.advancedGroup.setGroupSubject.bind(this.advancedGroup),
|
|
139
|
+
getInviteLink: this.advancedGroup.getGroupInviteLink.bind(this.advancedGroup),
|
|
140
|
+
revokeInviteLink: this.advancedGroup.revokeGroupInviteLink.bind(this.advancedGroup),
|
|
141
|
+
join: this.advancedGroup.joinGroupViaLink.bind(this.advancedGroup),
|
|
142
|
+
leave: this.advancedGroup.leaveGroup.bind(this.advancedGroup),
|
|
143
|
+
updatePicture: this.advancedGroup.updateGroupPicture.bind(this.advancedGroup)
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
this.privacy = {
|
|
147
|
+
block: this.advancedPrivacy.blockUser.bind(this.advancedPrivacy),
|
|
148
|
+
unblock: this.advancedPrivacy.unblockUser.bind(this.advancedPrivacy),
|
|
149
|
+
setSettings: this.advancedPrivacy.setPrivacySettings.bind(this.advancedPrivacy),
|
|
150
|
+
markRead: this.advancedPrivacy.markAsRead.bind(this.advancedPrivacy),
|
|
151
|
+
markUnread: this.advancedPrivacy.markAsUnread.bind(this.advancedPrivacy)
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
this.analytics = {
|
|
155
|
+
getDeliveryStatus: this.advancedAnalytics.getDeliveryStatus.bind(this.advancedAnalytics),
|
|
156
|
+
isOnline: this.advancedAnalytics.isUserOnline.bind(this.advancedAnalytics),
|
|
157
|
+
getLastSeen: this.advancedAnalytics.getLastSeen.bind(this.advancedAnalytics),
|
|
158
|
+
archiveChat: this.advancedAnalytics.archiveChat.bind(this.advancedAnalytics),
|
|
159
|
+
unarchiveChat: this.advancedAnalytics.unarchiveChat.bind(this.advancedAnalytics),
|
|
160
|
+
muteChat: this.advancedAnalytics.muteChat.bind(this.advancedAnalytics),
|
|
161
|
+
unmuteChat: this.advancedAnalytics.unmuteChat.bind(this.advancedAnalytics)
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
this.status = {
|
|
165
|
+
send: this.advancedStatus.sendStatusUpdate.bind(this.advancedStatus),
|
|
166
|
+
getViews: this.advancedStatus.getStatusViews.bind(this.advancedStatus),
|
|
167
|
+
getUserStatus: this.advancedStatus.getUserStatus.bind(this.advancedStatus)
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
this.business = {
|
|
171
|
+
setProfile: this.advancedBusiness.setBusinessProfile.bind(this.advancedBusiness),
|
|
172
|
+
sendProduct: this.advancedBusiness.sendProductMessage.bind(this.advancedBusiness),
|
|
173
|
+
createProduct: this.advancedBusiness.createProduct.bind(this.advancedBusiness),
|
|
174
|
+
requestPayment: this.advancedBusiness.sendPaymentRequest.bind(this.advancedBusiness)
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
this.system = {
|
|
178
|
+
backup: this.advancedSystem.createBackup.bind(this.advancedSystem),
|
|
179
|
+
restore: this.advancedSystem.restoreFromBackup.bind(this.advancedSystem),
|
|
180
|
+
exportChat: this.advancedSystem.exportChat.bind(this.advancedSystem),
|
|
181
|
+
importContacts: this.advancedSystem.importContacts.bind(this.advancedSystem),
|
|
182
|
+
sync: this.advancedSystem.syncWithPhone.bind(this.advancedSystem),
|
|
183
|
+
getDevices: this.advancedSystem.getLinkedDevices.bind(this.advancedSystem),
|
|
184
|
+
unlinkDevice: this.advancedSystem.unlinkDevice.bind(this.advancedSystem)
|
|
185
|
+
};
|
|
78
186
|
}
|
|
79
187
|
|
|
80
188
|
// ===== CONNECTION METHODS =====
|
|
@@ -154,6 +262,7 @@ export class WhatsAppClient {
|
|
|
154
262
|
|
|
155
263
|
// QR-Code Browser nur öffnen wenn nicht eingeloggt
|
|
156
264
|
if (!this.options.printQR && !isLoggedIn) {
|
|
265
|
+
console.log("🌍 Starte universelles QR-System...");
|
|
157
266
|
await generateQRCode();
|
|
158
267
|
}
|
|
159
268
|
|
|
@@ -164,16 +273,22 @@ export class WhatsAppClient {
|
|
|
164
273
|
this.socket.ev.on("connection.update", async ({ connection, lastDisconnect, qr }) => {
|
|
165
274
|
if (qr) {
|
|
166
275
|
if (this.options.printQR) {
|
|
167
|
-
// Terminal QR
|
|
168
|
-
|
|
169
|
-
|
|
276
|
+
// Terminal QR (mit Anti-Spam)
|
|
277
|
+
if (this.options.clearTerminalOnQR) {
|
|
278
|
+
console.clear();
|
|
279
|
+
}
|
|
280
|
+
console.log("\n" + "=".repeat(60));
|
|
281
|
+
console.log("📱 TERMINAL QR-CODE - SAUBER UND SPAM-FREI");
|
|
282
|
+
console.log("=".repeat(60));
|
|
170
283
|
const qrcode = await import("qrcode-terminal");
|
|
171
284
|
qrcode.default.generate(qr, { small: true });
|
|
172
|
-
console.log("
|
|
285
|
+
console.log("=".repeat(60));
|
|
173
286
|
console.log("📲 Scanne den QR-Code mit WhatsApp!");
|
|
287
|
+
console.log("💡 QR wird nur einmal angezeigt - kein Spam!");
|
|
288
|
+
console.log("=".repeat(60));
|
|
174
289
|
} else {
|
|
175
|
-
// Browser QR
|
|
176
|
-
console.log("
|
|
290
|
+
// Cross-Platform Browser QR (mit Anti-Spam)
|
|
291
|
+
console.log("🌍 QR-Code wird intelligent angezeigt (Anti-Spam aktiv)...");
|
|
177
292
|
await generateQRCode(qr);
|
|
178
293
|
}
|
|
179
294
|
}
|
|
@@ -186,15 +301,22 @@ export class WhatsAppClient {
|
|
|
186
301
|
const statusCode = lastDisconnect?.error?.output?.statusCode;
|
|
187
302
|
const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
|
|
188
303
|
|
|
304
|
+
// Cleanup timers
|
|
305
|
+
this.stopHeartbeat();
|
|
306
|
+
this.stopConnectionWatchdog();
|
|
307
|
+
|
|
189
308
|
if (shouldReconnect) {
|
|
190
|
-
console.log(
|
|
309
|
+
console.log(`🔄 Verbindung verloren (Code: ${statusCode}) - Starte robuste Wiederverbindung...`);
|
|
191
310
|
this.isConnected = false;
|
|
192
311
|
this.socket = null;
|
|
193
|
-
|
|
312
|
+
|
|
313
|
+
// Robuste Wiederverbindung mit exponential backoff
|
|
314
|
+
this.startRobustReconnection(resolve, reject);
|
|
194
315
|
} else {
|
|
195
316
|
console.log("👋 Ausgeloggt - bereinige Session...");
|
|
196
317
|
this.isConnected = false;
|
|
197
318
|
this.socket = null;
|
|
319
|
+
this.reconnectAttempts = 0;
|
|
198
320
|
|
|
199
321
|
// Auto-Cleanup bei Logout
|
|
200
322
|
if (this.options.autoCleanup) {
|
|
@@ -205,31 +327,13 @@ export class WhatsAppClient {
|
|
|
205
327
|
await closeBrowser();
|
|
206
328
|
this.emit('disconnected', { reason: 'logged_out', cleaned: this.options.autoCleanup });
|
|
207
329
|
|
|
208
|
-
// Auto-Restart Feature
|
|
330
|
+
// Auto-Restart Feature mit robuster Logik
|
|
209
331
|
if (this.options.autoRestart) {
|
|
210
332
|
console.log(`🔄 Auto-Restart in ${this.options.restartDelay / 1000} Sekunden...`);
|
|
211
333
|
console.log("📱 Neuer QR-Code wird generiert...");
|
|
212
334
|
|
|
213
335
|
setTimeout(async () => {
|
|
214
|
-
|
|
215
|
-
console.log("🚀 Starte neue Session...");
|
|
216
|
-
await this.connect();
|
|
217
|
-
console.log("✅ Auto-Restart erfolgreich!");
|
|
218
|
-
} catch (restartError) {
|
|
219
|
-
console.error("❌ Auto-Restart fehlgeschlagen:", restartError.message);
|
|
220
|
-
console.log("🔄 Versuche erneut in 10 Sekunden...");
|
|
221
|
-
|
|
222
|
-
// Retry nach 10 Sekunden
|
|
223
|
-
setTimeout(async () => {
|
|
224
|
-
try {
|
|
225
|
-
await this.connect();
|
|
226
|
-
console.log("✅ Auto-Restart Retry erfolgreich!");
|
|
227
|
-
} catch (retryError) {
|
|
228
|
-
console.error("❌ Auto-Restart Retry fehlgeschlagen:", retryError.message);
|
|
229
|
-
console.log("⚠️ Manuelle Neustart erforderlich");
|
|
230
|
-
}
|
|
231
|
-
}, 10000);
|
|
232
|
-
}
|
|
336
|
+
await this.startRobustRestart(resolve, reject);
|
|
233
337
|
}, this.options.restartDelay);
|
|
234
338
|
|
|
235
339
|
// Nicht rejecten bei Auto-Restart
|
|
@@ -241,7 +345,22 @@ export class WhatsAppClient {
|
|
|
241
345
|
} else if (connection === "open") {
|
|
242
346
|
console.log("✅ WhatsApp verbunden!");
|
|
243
347
|
this.isConnected = true;
|
|
348
|
+
this.lastConnectionTime = Date.now();
|
|
349
|
+
this.reconnectAttempts = 0; // Reset counter bei erfolgreicher Verbindung
|
|
350
|
+
|
|
351
|
+
// Connection Start Time für Offline Message Ignore setzen
|
|
352
|
+
this.connectionStartTime = Date.now();
|
|
353
|
+
if (this.ignoreOfflineMessages) {
|
|
354
|
+
console.log(`📵 Offline Messages werden ignoriert (seit ${new Date(this.connectionStartTime).toLocaleString()})`);
|
|
355
|
+
}
|
|
356
|
+
|
|
244
357
|
await closeBrowser(); // QR Browser schließen
|
|
358
|
+
|
|
359
|
+
// ROBUSTE CONNECTION FEATURES - NEU!
|
|
360
|
+
this.startHeartbeat(); // Heartbeat starten
|
|
361
|
+
this.startConnectionWatchdog(); // Connection Watchdog starten
|
|
362
|
+
|
|
363
|
+
console.log("💪 Robuste Verbindung etabliert - 24/7 bereit!");
|
|
245
364
|
this.emit('connected');
|
|
246
365
|
|
|
247
366
|
// 🔌 Plugins werden NICHT automatisch geladen
|
|
@@ -253,16 +372,26 @@ export class WhatsAppClient {
|
|
|
253
372
|
|
|
254
373
|
this.socket.ev.on("creds.update", saveCreds);
|
|
255
374
|
|
|
375
|
+
// ROBUSTES TIMEOUT SYSTEM - NEU!
|
|
256
376
|
setTimeout(() => {
|
|
257
377
|
if (!this.isConnected) {
|
|
258
|
-
console.log(
|
|
259
|
-
|
|
378
|
+
console.log(`⏰ Verbindungs-Timeout nach ${this.options.connectionTimeout / 1000} Sekunden`);
|
|
379
|
+
console.log("🔄 Starte robuste Wiederverbindung...");
|
|
380
|
+
|
|
381
|
+
// Nicht sofort rejecten, sondern robuste Wiederverbindung versuchen
|
|
382
|
+
this.startRobustReconnection(resolve, reject);
|
|
260
383
|
}
|
|
261
|
-
},
|
|
384
|
+
}, this.options.connectionTimeout); // Längeres Timeout (2 Minuten statt 1)
|
|
262
385
|
});
|
|
263
386
|
}
|
|
264
387
|
|
|
265
388
|
async disconnect() {
|
|
389
|
+
console.log("🔌 Trenne Verbindung...");
|
|
390
|
+
|
|
391
|
+
// Cleanup timers
|
|
392
|
+
this.stopHeartbeat();
|
|
393
|
+
this.stopConnectionWatchdog();
|
|
394
|
+
|
|
266
395
|
if (this.socket) {
|
|
267
396
|
this.socket.end();
|
|
268
397
|
this.socket = null;
|
|
@@ -272,6 +401,218 @@ export class WhatsAppClient {
|
|
|
272
401
|
}
|
|
273
402
|
}
|
|
274
403
|
|
|
404
|
+
// ===== ROBUSTE CONNECTION METHODS - NEU! =====
|
|
405
|
+
|
|
406
|
+
startHeartbeat() {
|
|
407
|
+
if (this.heartbeatTimer) {
|
|
408
|
+
clearInterval(this.heartbeatTimer);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
this.heartbeatTimer = setInterval(async () => {
|
|
412
|
+
if (this.isConnected && this.socket) {
|
|
413
|
+
try {
|
|
414
|
+
const startTime = Date.now();
|
|
415
|
+
|
|
416
|
+
// Ping WhatsApp Server
|
|
417
|
+
await this.socket.query({
|
|
418
|
+
tag: 'iq',
|
|
419
|
+
attrs: { type: 'get', xmlns: 'w:p', id: 'ping' + Date.now() },
|
|
420
|
+
content: [{ tag: 'ping' }]
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const responseTime = Date.now() - startTime;
|
|
424
|
+
this.connectionHealth.lastPing = Date.now();
|
|
425
|
+
this.connectionHealth.pingCount++;
|
|
426
|
+
this.connectionHealth.avgResponseTime =
|
|
427
|
+
(this.connectionHealth.avgResponseTime + responseTime) / 2;
|
|
428
|
+
|
|
429
|
+
// Nur bei Debug-Modus, langsamen Pings oder wenn quietHeartbeat deaktiviert ist
|
|
430
|
+
if (!this.options.quietHeartbeat || this.options.logLevel === 'debug' || responseTime > 5000) {
|
|
431
|
+
console.log(`💓 Heartbeat OK (${responseTime}ms)`);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
} catch (error) {
|
|
435
|
+
this.connectionHealth.failedPings++;
|
|
436
|
+
|
|
437
|
+
// Nur bei mehreren Fehlern, Debug-Modus oder wenn quietHeartbeat deaktiviert ist
|
|
438
|
+
if (!this.options.quietHeartbeat || this.options.logLevel === 'debug' || this.connectionHealth.failedPings >= 2) {
|
|
439
|
+
console.log(`💔 Heartbeat failed (${this.connectionHealth.failedPings} failures)`);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Bei 3 fehlgeschlagenen Pings Wiederverbindung
|
|
443
|
+
if (this.connectionHealth.failedPings >= 3) {
|
|
444
|
+
console.log("🚨 Verbindung instabil - starte Wiederverbindung...");
|
|
445
|
+
this.forceReconnect();
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}, this.options.heartbeatInterval);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
stopHeartbeat() {
|
|
453
|
+
if (this.heartbeatTimer) {
|
|
454
|
+
clearInterval(this.heartbeatTimer);
|
|
455
|
+
this.heartbeatTimer = null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
startConnectionWatchdog() {
|
|
460
|
+
if (this.connectionWatchdog) {
|
|
461
|
+
clearInterval(this.connectionWatchdog);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
this.connectionWatchdog = setInterval(() => {
|
|
465
|
+
if (this.isConnected) {
|
|
466
|
+
const timeSinceLastPing = Date.now() - (this.connectionHealth.lastPing || 0);
|
|
467
|
+
|
|
468
|
+
// Wenn länger als 2 Minuten kein Ping, Verbindung prüfen
|
|
469
|
+
if (timeSinceLastPing > 120000) {
|
|
470
|
+
console.log("🔍 Connection Watchdog: Verbindung prüfen...");
|
|
471
|
+
this.checkConnectionHealth();
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}, 60000); // Jede Minute prüfen
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
stopConnectionWatchdog() {
|
|
478
|
+
if (this.connectionWatchdog) {
|
|
479
|
+
clearInterval(this.connectionWatchdog);
|
|
480
|
+
this.connectionWatchdog = null;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async checkConnectionHealth() {
|
|
485
|
+
try {
|
|
486
|
+
if (!this.socket || !this.isConnected) {
|
|
487
|
+
throw new Error("Socket not connected");
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Test-Query senden
|
|
491
|
+
await this.socket.query({
|
|
492
|
+
tag: 'iq',
|
|
493
|
+
attrs: { type: 'get', xmlns: 'w:p', id: 'health' + Date.now() },
|
|
494
|
+
content: [{ tag: 'ping' }]
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
console.log("✅ Connection Health Check OK");
|
|
498
|
+
this.connectionHealth.failedPings = 0; // Reset failures
|
|
499
|
+
|
|
500
|
+
} catch (error) {
|
|
501
|
+
console.log("❌ Connection Health Check failed - starte Wiederverbindung...");
|
|
502
|
+
this.forceReconnect();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
async forceReconnect() {
|
|
507
|
+
if (this.isReconnecting) {
|
|
508
|
+
console.log("🔄 Wiederverbindung bereits aktiv...");
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
console.log("🔄 Erzwinge Wiederverbindung...");
|
|
513
|
+
this.isReconnecting = true;
|
|
514
|
+
this.isConnected = false;
|
|
515
|
+
|
|
516
|
+
// Socket schließen
|
|
517
|
+
if (this.socket) {
|
|
518
|
+
try {
|
|
519
|
+
this.socket.end();
|
|
520
|
+
} catch (error) {
|
|
521
|
+
// Ignoriere Fehler beim Schließen
|
|
522
|
+
}
|
|
523
|
+
this.socket = null;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Robuste Wiederverbindung starten
|
|
527
|
+
setTimeout(async () => {
|
|
528
|
+
try {
|
|
529
|
+
await this.connect();
|
|
530
|
+
console.log("✅ Erzwungene Wiederverbindung erfolgreich!");
|
|
531
|
+
} catch (error) {
|
|
532
|
+
console.error("❌ Erzwungene Wiederverbindung fehlgeschlagen:", error.message);
|
|
533
|
+
this.startRobustReconnection();
|
|
534
|
+
} finally {
|
|
535
|
+
this.isReconnecting = false;
|
|
536
|
+
}
|
|
537
|
+
}, 2000);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
async startRobustReconnection(resolve = null, reject = null) {
|
|
541
|
+
if (this.isReconnecting) {
|
|
542
|
+
console.log("🔄 Robuste Wiederverbindung bereits aktiv...");
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
this.isReconnecting = true;
|
|
547
|
+
|
|
548
|
+
const attemptReconnection = async () => {
|
|
549
|
+
if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
|
|
550
|
+
console.error(`❌ Maximale Wiederverbindungsversuche erreicht (${this.options.maxReconnectAttempts})`);
|
|
551
|
+
this.isReconnecting = false;
|
|
552
|
+
if (reject) reject(new Error('Max reconnection attempts reached'));
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
this.reconnectAttempts++;
|
|
557
|
+
|
|
558
|
+
// Exponential backoff berechnen
|
|
559
|
+
let delay = this.options.reconnectInterval;
|
|
560
|
+
if (this.options.exponentialBackoff) {
|
|
561
|
+
delay = Math.min(
|
|
562
|
+
this.options.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1),
|
|
563
|
+
this.options.maxBackoffDelay
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
console.log(`🔄 Wiederverbindungsversuch ${this.reconnectAttempts}/${this.options.maxReconnectAttempts} in ${delay / 1000}s...`);
|
|
568
|
+
|
|
569
|
+
setTimeout(async () => {
|
|
570
|
+
try {
|
|
571
|
+
await this.connect();
|
|
572
|
+
console.log(`✅ Robuste Wiederverbindung erfolgreich nach ${this.reconnectAttempts} Versuchen!`);
|
|
573
|
+
this.isReconnecting = false;
|
|
574
|
+
if (resolve) resolve(this);
|
|
575
|
+
} catch (error) {
|
|
576
|
+
console.log(`❌ Wiederverbindungsversuch ${this.reconnectAttempts} fehlgeschlagen: ${error.message}`);
|
|
577
|
+
attemptReconnection(); // Nächster Versuch
|
|
578
|
+
}
|
|
579
|
+
}, delay);
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
attemptReconnection();
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
async startRobustRestart(resolve = null, reject = null) {
|
|
586
|
+
const maxRestartAttempts = 5;
|
|
587
|
+
let restartAttempts = 0;
|
|
588
|
+
|
|
589
|
+
const attemptRestart = async () => {
|
|
590
|
+
if (restartAttempts >= maxRestartAttempts) {
|
|
591
|
+
console.error(`❌ Maximale Restart-Versuche erreicht (${maxRestartAttempts})`);
|
|
592
|
+
if (reject) reject(new Error('Max restart attempts reached'));
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
restartAttempts++;
|
|
597
|
+
console.log(`🚀 Restart-Versuch ${restartAttempts}/${maxRestartAttempts}...`);
|
|
598
|
+
|
|
599
|
+
try {
|
|
600
|
+
await this.connect();
|
|
601
|
+
console.log(`✅ Robuster Restart erfolgreich nach ${restartAttempts} Versuchen!`);
|
|
602
|
+
if (resolve) resolve(this);
|
|
603
|
+
} catch (restartError) {
|
|
604
|
+
console.error(`❌ Restart-Versuch ${restartAttempts} fehlgeschlagen:`, restartError.message);
|
|
605
|
+
|
|
606
|
+
const delay = 10000 * restartAttempts; // Längere Wartezeit bei jedem Versuch
|
|
607
|
+
console.log(`🔄 Nächster Restart-Versuch in ${delay / 1000} Sekunden...`);
|
|
608
|
+
|
|
609
|
+
setTimeout(attemptRestart, delay);
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
attemptRestart();
|
|
614
|
+
}
|
|
615
|
+
|
|
275
616
|
// ===== AUTO-RESTART SYSTEM =====
|
|
276
617
|
|
|
277
618
|
enableAutoRestart(enabled = true, delay = 5000) {
|
|
@@ -378,6 +719,38 @@ export class WhatsAppClient {
|
|
|
378
719
|
// Bessere Message-Validierung
|
|
379
720
|
if (!msg.message || msg.key.fromMe) return;
|
|
380
721
|
|
|
722
|
+
// OFFLINE MESSAGE IGNORE - DEINE NEUE FUNKTION!
|
|
723
|
+
if (this.ignoreOfflineMessages && this.connectionStartTime) {
|
|
724
|
+
const messageTimestamp = msg.messageTimestamp * 1000; // Convert to milliseconds
|
|
725
|
+
|
|
726
|
+
// Ignoriere Messages die vor der Verbindung gesendet wurden
|
|
727
|
+
if (messageTimestamp < this.connectionStartTime) {
|
|
728
|
+
this.ignoredMessagesCount++;
|
|
729
|
+
|
|
730
|
+
// Nur alle 10 Messages oder bei der ersten Message loggen
|
|
731
|
+
if (this.ignoredMessagesCount === 1) {
|
|
732
|
+
console.log(`📵 Offline Messages werden ignoriert...`);
|
|
733
|
+
} else if (this.ignoredMessagesCount % 10 === 0) {
|
|
734
|
+
console.log(`📵 ${this.ignoredMessagesCount} Offline Messages ignoriert...`);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Timer für finale Zusammenfassung zurücksetzen
|
|
738
|
+
if (this.offlineMessageTimer) {
|
|
739
|
+
clearTimeout(this.offlineMessageTimer);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Nach 3 Sekunden ohne neue Offline Messages finale Zusammenfassung
|
|
743
|
+
this.offlineMessageTimer = setTimeout(() => {
|
|
744
|
+
if (this.ignoredMessagesCount > 0) {
|
|
745
|
+
console.log(`✅ Insgesamt ${this.ignoredMessagesCount} Offline Messages ignoriert`);
|
|
746
|
+
this.ignoredMessagesCount = 0; // Reset counter
|
|
747
|
+
}
|
|
748
|
+
}, 3000);
|
|
749
|
+
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
381
754
|
// Ignoriere System-Messages (protocolMessage, etc.)
|
|
382
755
|
if (msg.message.protocolMessage ||
|
|
383
756
|
msg.message.reactionMessage ||
|
|
@@ -630,6 +1003,16 @@ class GetAPI {
|
|
|
630
1003
|
const participants = await this.GroupParticipants(groupId);
|
|
631
1004
|
return participants.filter(p => p.admin === 'admin' || p.admin === 'superadmin');
|
|
632
1005
|
}
|
|
1006
|
+
|
|
1007
|
+
// ===== PROFILE PICTURE API - NEU! =====
|
|
1008
|
+
|
|
1009
|
+
async ProfilePicture(jid) {
|
|
1010
|
+
try {
|
|
1011
|
+
return await this.client.socket.profilePictureUrl(jid, 'image');
|
|
1012
|
+
} catch (error) {
|
|
1013
|
+
return null; // Kein Profilbild verfügbar
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
633
1016
|
}
|
|
634
1017
|
|
|
635
1018
|
class AddAPI {
|
package/src/device-manager.js
CHANGED
|
@@ -117,18 +117,43 @@ export class DeviceManager {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
async connectAll() {
|
|
120
|
-
console.log(`🚀
|
|
120
|
+
console.log(`🚀 Sequenzielle Verbindung aller ${this.devices.size} Devices...`);
|
|
121
|
+
console.log("📱 QR-Codes werden nacheinander angezeigt!");
|
|
121
122
|
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
123
|
+
const deviceIds = Array.from(this.devices.keys());
|
|
124
|
+
const results = [];
|
|
125
|
+
let connected = 0;
|
|
126
|
+
|
|
127
|
+
for (let i = 0; i < deviceIds.length; i++) {
|
|
128
|
+
const deviceId = deviceIds[i];
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
console.log(`\n📱 Device ${i + 1}/${deviceIds.length}: '${deviceId}'`);
|
|
132
|
+
console.log("⏳ Scanne den QR-Code für dieses Device...");
|
|
133
|
+
|
|
134
|
+
await this.connectDevice(deviceId);
|
|
135
|
+
connected++;
|
|
136
|
+
results.push({ deviceId, status: 'connected' });
|
|
137
|
+
|
|
138
|
+
console.log(`✅ Device '${deviceId}' verbunden! Weiter zum nächsten...`);
|
|
139
|
+
|
|
140
|
+
// Kurze Pause zwischen Devices
|
|
141
|
+
if (i < deviceIds.length - 1) {
|
|
142
|
+
console.log("⏸️ 3 Sekunden Pause...");
|
|
143
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error(`❌ Device '${deviceId}' fehlgeschlagen:`, error.message);
|
|
148
|
+
results.push({ deviceId, status: 'failed', error: error.message });
|
|
149
|
+
|
|
150
|
+
// Weiter mit nächstem Device
|
|
151
|
+
console.log("➡️ Weiter mit nächstem Device...");
|
|
152
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
131
155
|
|
|
156
|
+
console.log(`\n🎉 Alle Devices verarbeitet!`);
|
|
132
157
|
console.log(`✅ ${connected}/${this.devices.size} Devices erfolgreich verbunden`);
|
|
133
158
|
|
|
134
159
|
if (connected === 0) {
|