waengine 1.0.4 → 1.0.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waengine",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "🚀 WAEngine - The most powerful WhatsApp Bot Library with Multi-Device Support & EasyBot API",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/client.js CHANGED
@@ -2,6 +2,7 @@ import { makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaile
2
2
  import pino from "pino";
3
3
  import { generateQRCode, closeBrowser } from "./qr.js";
4
4
  import { Message } from "./message.js";
5
+ import { SessionManager } from "./session-manager.js";
5
6
 
6
7
  export class WhatsAppClient {
7
8
  constructor(options = {}) {
@@ -10,6 +11,7 @@ export class WhatsAppClient {
10
11
  printQR: false,
11
12
  browser: options.browser || ["Chrome", "121.0.0", ""], // Aktueller Chrome
12
13
  logLevel: options.logLevel || "silent", // Sauber ohne Debug
14
+ autoCleanup: options.autoCleanup !== false, // Auto-Cleanup bei Logout
13
15
  ...options
14
16
  };
15
17
 
@@ -19,6 +21,9 @@ export class WhatsAppClient {
19
21
  this.isConnected = false;
20
22
  this.eventHandlers = new Map();
21
23
 
24
+ // Session Manager
25
+ this.sessionManager = new SessionManager(this.options.authDir);
26
+
22
27
  // Prefix System
23
28
  this.prefix = null;
24
29
  this.commands = new Map();
@@ -34,10 +39,27 @@ export class WhatsAppClient {
34
39
  // ===== CONNECTION METHODS =====
35
40
 
36
41
  async connect() {
42
+ console.log("🔌 WAEngine startet...");
43
+
37
44
  if (this.socket && this.isConnected) {
38
45
  return this.socket;
39
46
  }
40
47
 
48
+ // Session-Validierung und Auto-Repair
49
+ await this.sessionManager.ensureAuthDir();
50
+ const sessionValidation = await this.sessionManager.validateSession();
51
+
52
+ if (!sessionValidation.valid) {
53
+ console.log(`📋 Session-Status: ${sessionValidation.reason}`);
54
+
55
+ if (sessionValidation.reason === 'corrupted') {
56
+ console.log("🔧 Repariere korrupte Session...");
57
+ await this.sessionManager.repairSession();
58
+ }
59
+ } else {
60
+ console.log(`✅ Gültige Session gefunden (User: ${sessionValidation.userId})`);
61
+ }
62
+
41
63
  const { state, saveCreds } = await useMultiFileAuthState(this.options.authDir);
42
64
  const isLoggedIn = !!state.creds?.me?.id;
43
65
 
@@ -87,7 +109,7 @@ export class WhatsAppClient {
87
109
  });
88
110
  }
89
111
 
90
- console.log("🔌 Socket erstellt");
112
+ console.log("🔌 WAEngine startet...");
91
113
 
92
114
  // QR-Code Browser nur öffnen wenn nicht eingeloggt
93
115
  if (!this.options.printQR && !isLoggedIn) {
@@ -99,10 +121,7 @@ export class WhatsAppClient {
99
121
  this.setupEventHandlers();
100
122
 
101
123
  this.socket.ev.on("connection.update", async ({ connection, lastDisconnect, qr }) => {
102
- console.log(`🔄 Connection Update: ${connection}`);
103
-
104
124
  if (qr) {
105
- console.log("📱 QR-Code empfangen");
106
125
  if (this.options.printQR) {
107
126
  // Terminal QR
108
127
  console.log("\n📱 QR-CODE IM TERMINAL:");
@@ -113,28 +132,37 @@ export class WhatsAppClient {
113
132
  console.log("📲 Scanne den QR-Code mit WhatsApp!");
114
133
  } else {
115
134
  // Browser QR
135
+ console.log("📱 QR-Code im Browser angezeigt");
116
136
  await generateQRCode(qr);
117
137
  }
118
138
  }
119
139
 
120
140
  if (connection === "connecting") {
121
- console.log("🔄 Verbinde mit WhatsApp...");
141
+ console.log("🔄 Verbinde...");
122
142
  }
123
143
 
124
144
  if (connection === "close") {
125
- console.log("🔴 Verbindung geschlossen");
126
145
  const statusCode = lastDisconnect?.error?.output?.statusCode;
127
146
  const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
128
147
 
129
148
  if (shouldReconnect) {
130
- console.log("🔄 Wiederverbindung in 3 Sekunden...");
149
+ console.log("🔄 Wiederverbindung...");
131
150
  this.isConnected = false;
132
151
  this.socket = null;
133
152
  setTimeout(() => this.connect().then(resolve).catch(reject), 3000);
134
153
  } else {
135
- console.log("👋 Ausgeloggt");
154
+ console.log("👋 Ausgeloggt - bereinige Session...");
155
+ this.isConnected = false;
156
+ this.socket = null;
157
+
158
+ // Auto-Cleanup bei Logout
159
+ if (this.options.autoCleanup) {
160
+ await this.sessionManager.cleanupSession();
161
+ console.log("🧹 Session automatisch bereinigt");
162
+ }
163
+
136
164
  await closeBrowser();
137
- this.emit('disconnected', { reason: 'logged_out' });
165
+ this.emit('disconnected', { reason: 'logged_out', cleaned: this.options.autoCleanup });
138
166
  reject(new Error('Logged out'));
139
167
  }
140
168
  } else if (connection === "open") {
@@ -167,6 +195,50 @@ export class WhatsAppClient {
167
195
  }
168
196
  }
169
197
 
198
+ // ===== SESSION MANAGEMENT =====
199
+
200
+ async getSessionStatus() {
201
+ return await this.sessionManager.getSessionStatus();
202
+ }
203
+
204
+ async validateSession() {
205
+ return await this.sessionManager.validateSession();
206
+ }
207
+
208
+ async cleanupSession() {
209
+ console.log("🧹 Manuelle Session-Bereinigung...");
210
+ const success = await this.sessionManager.cleanupSession();
211
+ if (success) {
212
+ console.log("✅ Session erfolgreich bereinigt");
213
+ }
214
+ return success;
215
+ }
216
+
217
+ async repairSession() {
218
+ console.log("🔧 Session-Reparatur...");
219
+ return await this.sessionManager.repairSession();
220
+ }
221
+
222
+ async backupSession() {
223
+ return await this.sessionManager.backupSession();
224
+ }
225
+
226
+ // Logout mit automatischer Bereinigung
227
+ async logout() {
228
+ if (this.socket) {
229
+ console.log("👋 Logout wird durchgeführt...");
230
+ this.socket.logout();
231
+
232
+ // Warte kurz und bereinige dann
233
+ setTimeout(async () => {
234
+ if (this.options.autoCleanup) {
235
+ await this.sessionManager.cleanupSession();
236
+ console.log("🧹 Session nach Logout bereinigt");
237
+ }
238
+ }, 1000);
239
+ }
240
+ }
241
+
170
242
  // ===== EVENT SYSTEM =====
171
243
 
172
244
  on(event, handler) {
@@ -201,49 +273,37 @@ export class WhatsAppClient {
201
273
  }
202
274
 
203
275
  setupEventHandlers() {
204
- console.log("🔧 Registriere Event-Handler...");
205
-
206
- // Messages - Verbesserte Message-Erkennung
276
+ // Messages - Saubere Message-Erkennung ohne Debug-Spam
207
277
  this.socket.ev.on("messages.upsert", ({ messages, type }) => {
208
- console.log(`📨 Messages.upsert - Type: ${type}, Count: ${messages.length}`);
209
-
210
- // Alle Message-Types verarbeiten, nicht nur "notify"
211
- if (type !== "notify" && type !== "append") {
212
- console.log(`⚠️ Ignoriere Message-Type: ${type}`);
213
- return;
214
- }
278
+ // Nur relevante Message-Types verarbeiten
279
+ if (type !== "notify" && type !== "append") return;
215
280
 
216
- messages.forEach((msg, index) => {
217
- console.log(`🔍 Processing message ${index + 1}/${messages.length}`);
218
- console.log(` - From: ${msg.key.remoteJid}`);
219
- console.log(` - FromMe: ${msg.key.fromMe}`);
220
- console.log(` - Message Keys: ${Object.keys(msg.message || {}).join(', ')}`);
221
-
281
+ messages.forEach((msg) => {
222
282
  // Bessere Message-Validierung
223
- if (!msg.message) {
224
- console.log(" ❌ Keine Message-Daten");
225
- return;
226
- }
283
+ if (!msg.message || msg.key.fromMe) return;
227
284
 
228
- if (msg.key.fromMe) {
229
- console.log(" ❌ Eigene Nachricht - ignoriert");
230
- return;
285
+ // Ignoriere System-Messages (protocolMessage, etc.)
286
+ if (msg.message.protocolMessage ||
287
+ msg.message.reactionMessage ||
288
+ msg.message.ephemeralMessage ||
289
+ msg.message.viewOnceMessage) {
290
+ return; // Ignoriere ohne Debug-Output
231
291
  }
232
292
 
233
293
  // Ignoriere Broadcast-Messages
234
- if (msg.key.remoteJid && isJidBroadcast(msg.key.remoteJid)) {
235
- console.log(" ❌ Broadcast-Message - ignoriert");
236
- return;
237
- }
294
+ if (msg.key.remoteJid && isJidBroadcast(msg.key.remoteJid)) return;
238
295
 
239
296
  const messageData = this.parseMessage(msg);
240
- console.log(` ✅ Text extrahiert: "${messageData.text}"`);
241
- console.log(` ✅ Type: ${messageData.type}`);
242
297
 
243
- // Nur verarbeiten wenn Text vorhanden oder andere unterstützte Typen
244
- if (!messageData.text && messageData.type === 'unknown') {
245
- console.log(" ❌ Kein Text und unbekannter Typ");
246
- return;
298
+ // Nur verarbeiten wenn Text vorhanden oder unterstützte Typen
299
+ if (!messageData.text &&
300
+ !['image', 'video', 'audio', 'document', 'sticker', 'location', 'contact'].includes(messageData.type)) {
301
+ return; // Ignoriere ohne Debug-Output
302
+ }
303
+
304
+ // Nur bei echten Nachrichten loggen
305
+ if (messageData.text || messageData.type !== 'unknown') {
306
+ console.log(`📨 ${messageData.type}: "${messageData.text || '[Media]'}" von ${messageData.from}`);
247
307
  }
248
308
 
249
309
  const messageObj = new Message(this, messageData);
@@ -253,7 +313,7 @@ export class WhatsAppClient {
253
313
  const commandText = messageData.text.slice(this.prefix.length).trim();
254
314
  const [command, ...args] = commandText.split(' ');
255
315
 
256
- console.log(` ⚡ Command erkannt: ${command}`);
316
+ console.log(`⚡ Command: ${this.prefix}${command}`);
257
317
 
258
318
  messageObj.isCommand = true;
259
319
  messageObj.command = command.toLowerCase();
@@ -266,59 +326,42 @@ export class WhatsAppClient {
266
326
  // Spezifischen Command Handler aufrufen falls vorhanden
267
327
  if (this.commands.has(command.toLowerCase())) {
268
328
  const handler = this.commands.get(command.toLowerCase());
269
- console.log(` 🎯 Führe Command-Handler aus: ${command}`);
270
329
  try {
271
330
  handler(messageObj, args);
272
331
  } catch (error) {
273
332
  console.error(`❌ Fehler in Command '${command}':`, error);
274
333
  }
275
- } else {
276
- console.log(` ❓ Kein Handler für Command: ${command}`);
277
334
  }
278
335
  } else {
279
336
  messageObj.isCommand = false;
280
337
  messageObj.command = null;
281
338
  messageObj.args = [];
282
- console.log(" 📝 Normale Nachricht");
283
339
  }
284
340
 
285
- console.log(" 📤 Emittiere Message-Event");
286
341
  this.emit('message', messageObj);
287
- console.log(" ✅ Message verarbeitet");
288
342
  });
289
343
  });
290
344
 
291
- // Zusätzliche Events für bessere Kompatibilität
345
+ // Andere Events ohne Debug-Spam
292
346
  this.socket.ev.on("messages.update", (updates) => {
293
- console.log(`📝 Messages.update - Count: ${updates.length}`);
294
347
  this.emit('messages.update', updates);
295
348
  });
296
349
 
297
- // Bessere Presence-Handling
298
350
  this.socket.ev.on("presence.update", (update) => {
299
- console.log(`👤 Presence.update - ID: ${update.id}`);
300
351
  this.emit('presence.update', update);
301
352
  });
302
353
 
303
- // Group updates
304
354
  this.socket.ev.on("group-participants.update", (update) => {
305
- console.log(`👥 Group-participants.update - Group: ${update.id}`);
306
355
  this.emit('group.participants.update', update);
307
356
  });
308
357
 
309
- // Chats updates für bessere Synchronisation
310
358
  this.socket.ev.on("chats.upsert", (chats) => {
311
- console.log(`💬 Chats.upsert - Count: ${chats.length}`);
312
359
  this.emit('chats.upsert', chats);
313
360
  });
314
361
 
315
- // Contacts updates
316
362
  this.socket.ev.on("contacts.upsert", (contacts) => {
317
- console.log(`📞 Contacts.upsert - Count: ${contacts.length}`);
318
363
  this.emit('contacts.upsert', contacts);
319
364
  });
320
-
321
- console.log("✅ Event-Handler registriert!");
322
365
  }
323
366
 
324
367
  parseMessage(msg) {
@@ -0,0 +1,154 @@
1
+ // Session Manager für WAEngine v1.0.6
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+
5
+ export class SessionManager {
6
+ constructor(authDir) {
7
+ this.authDir = authDir;
8
+ }
9
+
10
+ // Prüft ob Session existiert und gültig ist
11
+ async validateSession() {
12
+ try {
13
+ if (!fs.existsSync(this.authDir)) {
14
+ return { valid: false, reason: 'no_auth_dir' };
15
+ }
16
+
17
+ const credsPath = path.join(this.authDir, 'creds.json');
18
+ if (!fs.existsSync(credsPath)) {
19
+ return { valid: false, reason: 'no_creds' };
20
+ }
21
+
22
+ const creds = JSON.parse(fs.readFileSync(credsPath, 'utf8'));
23
+
24
+ // Prüfe ob User-ID vorhanden (eingeloggt)
25
+ if (!creds.me?.id) {
26
+ return { valid: false, reason: 'not_logged_in' };
27
+ }
28
+
29
+ // Prüfe ob Session nicht zu alt ist (optional)
30
+ const stats = fs.statSync(credsPath);
31
+ const ageInDays = (Date.now() - stats.mtime.getTime()) / (1000 * 60 * 60 * 24);
32
+
33
+ if (ageInDays > 30) { // Session älter als 30 Tage
34
+ return { valid: false, reason: 'session_too_old' };
35
+ }
36
+
37
+ return {
38
+ valid: true,
39
+ userId: creds.me.id,
40
+ lastModified: stats.mtime,
41
+ ageInDays: Math.round(ageInDays)
42
+ };
43
+
44
+ } catch (error) {
45
+ return { valid: false, reason: 'corrupted', error: error.message };
46
+ }
47
+ }
48
+
49
+ // Bereinigt Session komplett
50
+ async cleanupSession() {
51
+ try {
52
+ if (fs.existsSync(this.authDir)) {
53
+ console.log("🧹 Bereinige Session...");
54
+
55
+ // Alle Auth-Dateien löschen
56
+ const files = fs.readdirSync(this.authDir);
57
+ for (const file of files) {
58
+ const filePath = path.join(this.authDir, file);
59
+ fs.unlinkSync(filePath);
60
+ }
61
+
62
+ // Auth-Ordner löschen
63
+ fs.rmdirSync(this.authDir);
64
+ console.log("✅ Session bereinigt");
65
+ return true;
66
+ }
67
+ return true;
68
+ } catch (error) {
69
+ console.error("❌ Fehler beim Session-Cleanup:", error);
70
+ return false;
71
+ }
72
+ }
73
+
74
+ // Erstellt Auth-Ordner falls nicht vorhanden
75
+ async ensureAuthDir() {
76
+ if (!fs.existsSync(this.authDir)) {
77
+ fs.mkdirSync(this.authDir, { recursive: true });
78
+ console.log(`📁 Auth-Ordner erstellt: ${this.authDir}`);
79
+ }
80
+ }
81
+
82
+ // Backup der Session erstellen
83
+ async backupSession() {
84
+ try {
85
+ if (!fs.existsSync(this.authDir)) return false;
86
+
87
+ const backupDir = `${this.authDir}_backup_${Date.now()}`;
88
+ fs.mkdirSync(backupDir, { recursive: true });
89
+
90
+ const files = fs.readdirSync(this.authDir);
91
+ for (const file of files) {
92
+ const srcPath = path.join(this.authDir, file);
93
+ const destPath = path.join(backupDir, file);
94
+ fs.copyFileSync(srcPath, destPath);
95
+ }
96
+
97
+ console.log(`💾 Session-Backup erstellt: ${backupDir}`);
98
+ return backupDir;
99
+ } catch (error) {
100
+ console.error("❌ Backup-Fehler:", error);
101
+ return false;
102
+ }
103
+ }
104
+
105
+ // Session-Status für Debugging
106
+ getSessionStatus() {
107
+ try {
108
+ if (!fs.existsSync(this.authDir)) {
109
+ return { status: 'no_session', files: [] };
110
+ }
111
+
112
+ const files = fs.readdirSync(this.authDir);
113
+ const fileDetails = files.map(file => {
114
+ const filePath = path.join(this.authDir, file);
115
+ const stats = fs.statSync(filePath);
116
+ return {
117
+ name: file,
118
+ size: stats.size,
119
+ modified: stats.mtime
120
+ };
121
+ });
122
+
123
+ return {
124
+ status: 'session_exists',
125
+ files: fileDetails,
126
+ totalFiles: files.length,
127
+ authDir: this.authDir
128
+ };
129
+ } catch (error) {
130
+ return { status: 'error', error: error.message };
131
+ }
132
+ }
133
+
134
+ // Repariert korrupte Session
135
+ async repairSession() {
136
+ console.log("🔧 Versuche Session-Reparatur...");
137
+
138
+ const validation = await this.validateSession();
139
+
140
+ if (validation.reason === 'corrupted') {
141
+ console.log("🗑️ Korrupte Session erkannt - bereinige...");
142
+ await this.cleanupSession();
143
+ return { repaired: true, action: 'cleanup' };
144
+ }
145
+
146
+ if (validation.reason === 'session_too_old') {
147
+ console.log("⏰ Session zu alt - bereinige...");
148
+ await this.cleanupSession();
149
+ return { repaired: true, action: 'cleanup_old' };
150
+ }
151
+
152
+ return { repaired: false, reason: validation.reason };
153
+ }
154
+ }