waengine 2.3.2 β†’ 2.3.8-rc.1

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": "2.3.2",
3
+ "version": "2.3.8-rc.1",
4
4
  "description": "πŸš€ WAEngine - The most powerful WhatsApp Bot Library with 860+ Working Features, Complete Baileys Integration & Production-Ready Stability",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/client.js CHANGED
@@ -138,12 +138,19 @@ export class WhatsAppClient {
138
138
  this.ui = new UIComponents(this);
139
139
 
140
140
  // Offline Message Ignore System - NEU!
141
- this.ignoreOfflineMessages = false;
141
+ // Automatisch aktivieren wenn Environment-Variable gesetzt ist
142
+ this.ignoreOfflineMessages = process.env.WAENGINE_IGNORE_OFFLINE_MESSAGES === 'true' || false;
142
143
  this.lastOnlineTimestamp = Date.now();
143
144
  this.connectionStartTime = null;
144
145
  this.ignoredMessagesCount = 0; // Counter fΓΌr ignorierte Messages
145
146
  this.offlineMessageTimer = null; // Timer fΓΌr finale Zusammenfassung
146
147
 
148
+ // Log wenn automatisch aktiviert
149
+ if (this.ignoreOfflineMessages) {
150
+ console.log('\nπŸ“΅ Offline Message Ignore: AUTOMATISCH AKTIVIERT');
151
+ console.log(' └─ Grund: Session ΓΌber Session Menu gestartet\n');
152
+ }
153
+
147
154
  // ===== GLOBAL VISUAL TYPING/RECORDING SYSTEM - NEU! =====
148
155
  this.globalVisualTyping = false; // Global aktiviert/deaktiviert
149
156
  this.globalVisualRecord = false; // Global aktiviert/deaktiviert
@@ -372,8 +379,9 @@ export class WhatsAppClient {
372
379
  syncFullHistory: true, // Wichtig fΓΌr Message-Empfang
373
380
  markOnlineOnConnect: true,
374
381
  getMessage: async (key) => {
375
- // Wichtig fΓΌr Message-Handling
376
- return { conversation: "Message not found" };
382
+ // WICHTIG: undefined zurΓΌckgeben statt "Message not found"
383
+ // Sonst wird es als echte Nachricht behandelt und spammt!
384
+ return undefined;
377
385
  },
378
386
  shouldIgnoreJid: jid => isJidBroadcast(jid),
379
387
  // Bessere Message-Synchronisation
@@ -392,8 +400,9 @@ export class WhatsAppClient {
392
400
  syncFullHistory: true, // Wichtig fΓΌr Message-Empfang
393
401
  markOnlineOnConnect: true,
394
402
  getMessage: async (key) => {
395
- // Wichtig fΓΌr Message-Handling
396
- return { conversation: "Message not found" };
403
+ // WICHTIG: undefined zurΓΌckgeben statt "Message not found"
404
+ // Sonst wird es als echte Nachricht behandelt und spammt!
405
+ return undefined;
397
406
  },
398
407
  shouldIgnoreJid: jid => isJidBroadcast(jid),
399
408
  // Bessere Message-Synchronisation
@@ -561,7 +570,9 @@ export class WhatsAppClient {
561
570
  // Connection Start Time fΓΌr Offline Message Ignore setzen
562
571
  this.connectionStartTime = Date.now();
563
572
  if (this.ignoreOfflineMessages) {
564
- this.logger.info(`Offline Messages werden ignoriert (seit ${new Date(this.connectionStartTime).toLocaleString()})`);
573
+ console.log(`\nπŸ“΅ Offline Message Ignore: AKTIV`);
574
+ console.log(` β”œβ”€ Verbunden seit: ${new Date(this.connectionStartTime).toLocaleString()}`);
575
+ console.log(` └─ Alle Messages vor diesem Zeitpunkt werden ignoriert\n`);
565
576
  }
566
577
 
567
578
  await closeBrowser(); // QR Browser schließen
@@ -968,17 +979,31 @@ export class WhatsAppClient {
968
979
  // DEBUG: Zeige alle Message-Types
969
980
  console.log(`πŸ“₯ Message Event - Type: ${type}, Count: ${messages.length}`);
970
981
 
971
- // WICHTIG: Alle Types akzeptieren außer explizit ausgeschlossene
972
- // Nur "prepend" (alte History) ignorieren wenn gewΓΌnscht
973
- // if (type === "prepend") return; // Optional: Alte Messages ignorieren
982
+ // WICHTIG: Alte History-Messages ignorieren (prepend)
983
+ if (type === "prepend") {
984
+ console.log(`⏭️ Ignoriere ${messages.length} History Messages (prepend)`);
985
+ return;
986
+ }
974
987
 
975
988
  messages.forEach((msg) => {
989
+ // KRITISCHE VALIDIERUNG: PrΓΌfe ob Message-Key existiert
990
+ if (!msg.key || !msg.key.remoteJid || !msg.key.id) {
991
+ console.log(`⚠️ Ungültige Message ohne Key - ignoriert`);
992
+ return;
993
+ }
994
+
976
995
  // Bessere Message-Validierung
977
996
  if (!msg.message || msg.key.fromMe) return;
978
997
 
979
998
  // OFFLINE MESSAGE IGNORE - DEINE NEUE FUNKTION!
980
999
  if (this.ignoreOfflineMessages && this.connectionStartTime) {
981
- const messageTimestamp = msg.messageTimestamp * 1000; // Convert to milliseconds
1000
+ // messageTimestamp kann in Sekunden oder Millisekunden sein
1001
+ let messageTimestamp = msg.messageTimestamp;
1002
+
1003
+ // Wenn Timestamp in Sekunden (< Jahr 2000 in Millisekunden), konvertiere zu Millisekunden
1004
+ if (messageTimestamp < 946684800000) {
1005
+ messageTimestamp = messageTimestamp * 1000;
1006
+ }
982
1007
 
983
1008
  // Ignoriere Messages die vor der Verbindung gesendet wurden
984
1009
  if (messageTimestamp < this.connectionStartTime) {
@@ -997,7 +1022,7 @@ export class WhatsAppClient {
997
1022
  }
998
1023
  }, 3000);
999
1024
 
1000
- return;
1025
+ return; // WICHTIG: Beende hier - verarbeite Message NICHT weiter!
1001
1026
  }
1002
1027
  }
1003
1028
 
@@ -285,7 +285,8 @@ let sessionMenuShown = false;
285
285
 
286
286
  export async function showSessionMenuIfNeeded() {
287
287
  // PrΓΌfe ob wir vom Session Menu selbst aufgerufen werden
288
- if (global.__WAENGINE_SKIP_SESSION_MENU__) {
288
+ // WICHTIG: PrΓΌfe sowohl global als auch Environment-Variable!
289
+ if (global.__WAENGINE_SKIP_SESSION_MENU__ || process.env.__WAENGINE_SKIP_SESSION_MENU__ === 'true') {
289
290
  return null;
290
291
  }
291
292
 
package/src/message.js CHANGED
@@ -727,6 +727,100 @@ export class Message {
727
727
  }
728
728
  }
729
729
 
730
+ // ===== MESSAGE DEL - LΓΆsche beliebige Message (Admin erforderlich in Gruppen) =====
731
+ async MessageDel(messageId, participantJid = null) {
732
+ try {
733
+ // Wenn keine Parameter, lΓΆsche die aktuelle Message
734
+ if (!messageId) {
735
+ return await this.deleteMessage();
736
+ }
737
+
738
+ // PrΓΌfe in Gruppen ob Bot Admin ist
739
+ if (this.isGroup) {
740
+ const isBotAdmin = await this.isGroupAdmin(this.client.socket.user.id);
741
+ if (!isBotAdmin) {
742
+ console.log('⚠️ Bot ist kein Admin - kann nur eigene Messages lâschen');
743
+ return {
744
+ success: false,
745
+ reason: 'not_admin',
746
+ error: 'Bot muss Admin sein um Messages von anderen zu lΓΆschen'
747
+ };
748
+ }
749
+ }
750
+
751
+ // Bot JID ermitteln
752
+ const botJid = this.client.socket.user?.id;
753
+ const botNumber = botJid?.split('@')[0]?.split(':')[0];
754
+
755
+ // PrΓΌfe ob Message vom Bot ist
756
+ let isFromBot = false;
757
+ if (participantJid) {
758
+ const participantNumber = participantJid?.split('@')[0]?.split(':')[0];
759
+ isFromBot = botNumber === participantNumber;
760
+ }
761
+
762
+ // Erstelle Message Key
763
+ const messageKey = {
764
+ remoteJid: this.from,
765
+ id: messageId,
766
+ fromMe: isFromBot
767
+ };
768
+
769
+ // In Gruppen: participant hinzufΓΌgen wenn nicht vom Bot
770
+ if (this.isGroup && participantJid && !isFromBot) {
771
+ messageKey.participant = participantJid;
772
+ }
773
+
774
+ console.log('πŸ—‘οΈ MessageDel - LΓΆsche Message:', {
775
+ messageId: messageId,
776
+ participant: participantJid,
777
+ isFromBot: isFromBot,
778
+ isGroup: this.isGroup,
779
+ key: messageKey
780
+ });
781
+
782
+ // Sende Delete Request
783
+ const result = await this.client.socket.sendMessage(this.from, {
784
+ delete: messageKey
785
+ });
786
+
787
+ console.log('βœ… MessageDel erfolgreich:', result);
788
+ return {
789
+ success: true,
790
+ messageId: messageId,
791
+ participant: participantJid,
792
+ wasFromBot: isFromBot,
793
+ result: result
794
+ };
795
+
796
+ } catch (error) {
797
+ console.error('❌ MessageDel Fehler:', error.message);
798
+
799
+ // Spezifische Fehlerbehandlung
800
+ if (error.message?.includes('not-found') || error.message?.includes('404')) {
801
+ return {
802
+ success: false,
803
+ reason: 'message_not_found',
804
+ error: 'Message nicht gefunden oder zu alt'
805
+ };
806
+ }
807
+
808
+ if (error.message?.includes('forbidden') || error.message?.includes('403')) {
809
+ return {
810
+ success: false,
811
+ reason: 'no_permission',
812
+ error: 'Keine Berechtigung - Bot muss Admin sein'
813
+ };
814
+ }
815
+
816
+ return {
817
+ success: false,
818
+ reason: 'unknown_error',
819
+ error: error.message
820
+ };
821
+ }
822
+ }
823
+
730
824
  // ===== MEDIA DOWNLOAD - NEU in v1.7.9! =====
731
825
 
732
826
  async downloadMedia(options = {}) {
@@ -18,13 +18,16 @@ const c = {
18
18
  };
19
19
 
20
20
  export class SessionMenu {
21
- constructor(baseAuthDir = './auth') { // GeΓ€ndert von './sessions' zu './auth'
21
+ constructor(baseAuthDir = './auth') {
22
22
  this.baseAuthDir = baseAuthDir;
23
- this.sessionsConfigPath = path.join(baseAuthDir, '..', 'sessions.json'); // Eine Ebene hΓΆher
24
- this.sessionStatusPath = path.join(baseAuthDir, '..', 'session-status.json'); // Status-Tracking
23
+ this.sessionsConfigPath = path.join(baseAuthDir, '..', 'sessions.json');
24
+ this.sessionStatusPath = path.join(baseAuthDir, '..', 'session-status.json');
25
25
  this.activeSessions = new Map();
26
26
  this.rl = null;
27
27
 
28
+ // Erkenne das Start-Script aus process.argv
29
+ this.userStartCommand = this.detectStartCommand();
30
+
28
31
  if (!fs.existsSync(baseAuthDir)) {
29
32
  fs.mkdirSync(baseAuthDir, { recursive: true });
30
33
  }
@@ -32,6 +35,22 @@ export class SessionMenu {
32
35
  this.loadSessionsConfig();
33
36
  this.loadSessionStatus();
34
37
  }
38
+
39
+ // Erkenne wie der User seinen Bot gestartet hat
40
+ detectStartCommand() {
41
+ // process.argv[0] = node
42
+ // process.argv[1] = script.js
43
+ const scriptPath = process.argv[1];
44
+
45
+ if (scriptPath) {
46
+ const scriptName = path.basename(scriptPath);
47
+ console.log(c.green(`βœ… Start-Command erkannt: node ${scriptName}`));
48
+ return scriptName;
49
+ }
50
+
51
+ // Fallback
52
+ return 'index.js';
53
+ }
35
54
 
36
55
  loadSessionsConfig() {
37
56
  if (fs.existsSync(this.sessionsConfigPath)) {
@@ -101,20 +120,17 @@ export class SessionMenu {
101
120
 
102
121
  console.log(c.cyan(`\nπŸš€ Γ–ffne neues Terminal fΓΌr Session: ${sessionName}...`));
103
122
 
104
- // Erstelle ein temporΓ€res Start-Script fΓΌr diese Session
105
- const scriptPath = path.join(process.cwd(), `.session-${sessionName}.js`);
123
+ // Setze Status auf "connecting"
124
+ this.updateSessionStatus(sessionName, 'connecting');
125
+
126
+ // Erstelle Wrapper-Script fΓΌr Status-Tracking
127
+ const wrapperPath = path.join(process.cwd(), `.session-${sessionName}-wrapper.js`);
106
128
  const statusPath = path.join(process.cwd(), 'session-status.json');
107
129
 
108
- const scriptContent = `
109
- // Auto-generiertes Session-Start-Script fΓΌr: ${sessionName}
110
- import { WhatsAppClient } from 'waengine';
130
+ const wrapperContent = `// Session Wrapper fΓΌr: ${sessionName}
111
131
  import fs from 'fs';
132
+ import { spawn } from 'child_process';
112
133
 
113
- console.log('╔════════════════════════════════════════╗');
114
- console.log('β•‘ WAEngine Session: ${sessionName.padEnd(20)}β•‘');
115
- console.log('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\\n');
116
-
117
- // Status-Update Funktion
118
134
  function updateStatus(status) {
119
135
  try {
120
136
  let statusData = {};
@@ -131,73 +147,57 @@ function updateStatus(status) {
131
147
 
132
148
  fs.writeFileSync('${statusPath.replace(/\\/g, '/')}', JSON.stringify(statusData, null, 2));
133
149
  } catch (error) {
134
- console.error('Status-Update Fehler:', error.message);
150
+ console.error('❌ Status-Update Fehler:', error.message);
135
151
  }
136
152
  }
137
153
 
138
- // Status: Verbindet
139
- updateStatus('connecting');
154
+ console.log('╔════════════════════════════════════════╗');
155
+ console.log('β•‘ WAEngine Session: ${sessionName.padEnd(20)}β•‘');
156
+ console.log('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\\n');
140
157
 
141
- // Deaktiviere Session Menu fΓΌr diese Session
142
- global.__WAENGINE_SKIP_SESSION_MENU__ = true;
158
+ updateStatus('connecting');
143
159
 
144
- const client = new WhatsAppClient({
145
- authDir: '${session.authDir.replace(/\\/g, '/')}',
146
- printQR: false,
147
- silent: false
160
+ // Starte User's Bot-Script mit Environment-Variablen
161
+ const botProcess = spawn('node', ['${this.userStartCommand}'], {
162
+ env: {
163
+ ...process.env,
164
+ WAENGINE_AUTH_DIR: '${session.authDir.replace(/\\/g, '/')}',
165
+ WAENGINE_SESSION_NAME: '${sessionName}',
166
+ __WAENGINE_SKIP_SESSION_MENU__: 'true',
167
+ WAENGINE_IGNORE_OFFLINE_MESSAGES: 'true' // Ignoriere Offline-Nachrichten automatisch
168
+ },
169
+ stdio: 'inherit'
148
170
  });
149
171
 
150
- console.log('πŸ”„ Starte Session ${sessionName}...\\n');
151
-
152
- try {
153
- await client.connect();
154
-
155
- // Status: Online
172
+ // Warte kurz und setze Status auf online
173
+ setTimeout(() => {
156
174
  updateStatus('online');
157
175
 
158
- console.log('\\nβœ… Session ${sessionName} lΓ€uft!');
159
- console.log('πŸ’¬ Bot wartet auf Nachrichten...\\n');
160
-
161
- // Heartbeat: Status alle 10 Sekunden aktualisieren
176
+ // Heartbeat alle 10 Sekunden
162
177
  setInterval(() => {
163
178
  updateStatus('online');
164
179
  }, 10000);
165
-
166
- // Beispiel: Message Handler
167
- client.on('message', async (msg) => {
168
- console.log(\`πŸ“¨ Nachricht von \${msg.from}: \${msg.body}\`);
169
-
170
- // Hier kann der User seinen Bot-Code einfΓΌgen
171
- if (msg.body === '!ping') {
172
- await msg.reply('πŸ“ Pong!');
173
- }
174
- });
175
-
176
- } catch (error) {
177
- console.error('❌ Fehler beim Starten:', error.message);
180
+ }, 3000);
181
+
182
+ botProcess.on('exit', (code) => {
183
+ console.log(\`\\nπŸ‘‹ Bot beendet (Code: \${code})\`);
178
184
  updateStatus('offline');
179
- }
185
+ process.exit(code);
186
+ });
180
187
 
181
- // Verhindere dass das Script beendet wird
182
188
  process.on('SIGINT', () => {
183
189
  console.log('\\nπŸ‘‹ Session ${sessionName} wird beendet...');
184
190
  updateStatus('offline');
191
+ botProcess.kill();
185
192
  process.exit(0);
186
193
  });
187
-
188
- process.on('exit', () => {
189
- updateStatus('offline');
190
- });
191
194
  `;
192
195
 
193
- // Schreibe das Script
194
- fs.writeFileSync(scriptPath, scriptContent);
195
-
196
- // Setze Status auf "connecting"
197
- this.updateSessionStatus(sessionName, 'connecting');
196
+ // Schreibe Wrapper-Script
197
+ fs.writeFileSync(wrapperPath, wrapperContent);
198
198
 
199
- // Γ–ffne neues Terminal (Windows CMD)
200
- const command = `start "WAEngine - ${sessionName}" cmd /k "node ${scriptPath}"`;
199
+ // Γ–ffne neues Terminal mit Wrapper-Script
200
+ const command = `start "WAEngine - ${sessionName}" cmd /k "node ${wrapperPath}"`;
201
201
 
202
202
  try {
203
203
  spawn(command, [], {
@@ -207,7 +207,8 @@ process.on('exit', () => {
207
207
  });
208
208
 
209
209
  console.log(c.green(`βœ… Neues Terminal geΓΆffnet fΓΌr: ${sessionName}`));
210
- console.log(c.gray(` Script: ${scriptPath}`));
210
+ console.log(c.gray(` Command: node ${this.userStartCommand}`));
211
+ console.log(c.gray(` Auth: ${session.authDir}`));
211
212
  console.log(c.gray(` Status wird automatisch aktualisiert...`));
212
213
 
213
214
  return true;
@@ -215,8 +216,8 @@ process.on('exit', () => {
215
216
  console.log(c.red(`❌ Fehler beim Γ–ffnen des Terminals: ${error.message}`));
216
217
 
217
218
  // Cleanup
218
- if (fs.existsSync(scriptPath)) {
219
- fs.unlinkSync(scriptPath);
219
+ if (fs.existsSync(wrapperPath)) {
220
+ fs.unlinkSync(wrapperPath);
220
221
  }
221
222
 
222
223
  this.updateSessionStatus(sessionName, 'offline');