waengine 1.0.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/src/message.js ADDED
@@ -0,0 +1,628 @@
1
+ // Message-Klasse mit deinen eigenen Funktionen
2
+
3
+ export class Message {
4
+ constructor(client, data) {
5
+ this.client = client;
6
+ this.id = data.id;
7
+ this.from = data.from;
8
+ this.fromMe = data.fromMe;
9
+ this.text = data.text;
10
+ this.timestamp = data.timestamp;
11
+ this.type = data.type;
12
+ this.isGroup = data.isGroup;
13
+ this.raw = data.raw;
14
+
15
+ // Command Properties (werden vom Client gesetzt)
16
+ this.isCommand = false;
17
+ this.command = null;
18
+ this.args = [];
19
+ this.commandText = null;
20
+ }
21
+
22
+ // ===== REPLY FUNCTIONS =====
23
+
24
+ async reply(text, mentions = []) {
25
+ if (mentions.length > 0) {
26
+ return await this.client.socket.sendMessage(this.from, {
27
+ text: text,
28
+ mentions: mentions
29
+ });
30
+ }
31
+
32
+ return await this.client.socket.sendMessage(this.from, {
33
+ text: text
34
+ });
35
+ }
36
+
37
+ async sendImage(imagePath, caption = "", mentions = []) {
38
+ const message = {
39
+ image: { url: imagePath },
40
+ caption: caption
41
+ };
42
+
43
+ if (mentions.length > 0) {
44
+ message.mentions = mentions;
45
+ }
46
+
47
+ return await this.client.socket.sendMessage(this.from, message);
48
+ }
49
+
50
+ async sendSticker(stickerPath) {
51
+ return await this.client.socket.sendMessage(this.from, {
52
+ sticker: { url: stickerPath }
53
+ });
54
+ }
55
+
56
+ async sendAudio(audioPath) {
57
+ return await this.client.socket.sendMessage(this.from, {
58
+ audio: { url: audioPath },
59
+ mimetype: 'audio/mp4'
60
+ });
61
+ }
62
+
63
+ async sendVideo(videoPath, caption = "", mentions = []) {
64
+ const message = {
65
+ video: { url: videoPath },
66
+ caption: caption
67
+ };
68
+
69
+ if (mentions.length > 0) {
70
+ message.mentions = mentions;
71
+ }
72
+
73
+ return await this.client.socket.sendMessage(this.from, message);
74
+ }
75
+
76
+ async sendDocument(documentPath, fileName, mentions = []) {
77
+ const message = {
78
+ document: { url: documentPath },
79
+ fileName: fileName,
80
+ mimetype: 'application/octet-stream'
81
+ };
82
+
83
+ if (mentions.length > 0) {
84
+ message.mentions = mentions;
85
+ }
86
+
87
+ return await this.client.socket.sendMessage(this.from, message);
88
+ }
89
+
90
+ async sendLocation(latitude, longitude) {
91
+ return await this.client.socket.sendMessage(this.from, {
92
+ location: {
93
+ degreesLatitude: latitude,
94
+ degreesLongitude: longitude
95
+ }
96
+ });
97
+ }
98
+
99
+ async sendContact(vcard, displayName) {
100
+ return await this.client.socket.sendMessage(this.from, {
101
+ contacts: {
102
+ displayName: displayName,
103
+ contacts: [{ vcard }]
104
+ }
105
+ });
106
+ }
107
+
108
+ async sendPoll(question, options) {
109
+ if (!Array.isArray(options) || options.length < 2 || options.length > 12) {
110
+ throw new Error('Poll muss zwischen 2 und 12 Optionen haben');
111
+ }
112
+
113
+ try {
114
+ console.log('📊 Sende Poll:', question, options);
115
+
116
+ // Baileys V3 Poll Format (korrekte Syntax)
117
+ const pollMessage = {
118
+ poll: {
119
+ name: question,
120
+ values: options,
121
+ selectableCount: 1
122
+ }
123
+ };
124
+
125
+ // Alternative V3 Syntax versuchen
126
+ const pollMessageV3 = {
127
+ pollCreationMessage: {
128
+ name: question,
129
+ options: options.map(option => ({ optionName: option })),
130
+ selectableOptionsCount: 1
131
+ }
132
+ };
133
+
134
+ console.log('📊 Versuche Standard Poll Format...');
135
+
136
+ try {
137
+ const result = await this.client.socket.sendMessage(this.from, pollMessage);
138
+ console.log('✅ Standard Poll gesendet:', result);
139
+ return result;
140
+ } catch (standardError) {
141
+ console.log('⚠️ Standard Format fehlgeschlagen, versuche V3 Format...');
142
+
143
+ const resultV3 = await this.client.socket.sendMessage(this.from, pollMessageV3);
144
+ console.log('✅ V3 Poll gesendet:', resultV3);
145
+ return resultV3;
146
+ }
147
+
148
+ } catch (error) {
149
+ console.error('❌ Alle Poll Formate fehlgeschlagen:', error);
150
+ console.log('🔄 Verwende Fallback...');
151
+
152
+ // Fallback: Als interaktive Nachricht mit Emojis
153
+ let fallbackText = `📊 **${question}**\n\n`;
154
+ const emojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'];
155
+
156
+ options.forEach((option, index) => {
157
+ const emoji = emojis[index] || `${index + 1}️⃣`;
158
+ fallbackText += `${emoji} ${option}\n`;
159
+ });
160
+
161
+ fallbackText += `\n_Reagiere mit dem entsprechenden Emoji zum Abstimmen!_`;
162
+
163
+ const fallbackResult = await this.reply(fallbackText);
164
+
165
+ // Auto-Reactions hinzufügen für bessere UX
166
+ setTimeout(async () => {
167
+ try {
168
+ for (let i = 0; i < Math.min(options.length, emojis.length); i++) {
169
+ await new Promise(resolve => setTimeout(resolve, 500)); // Delay zwischen Reactions
170
+ await this.client.socket.sendMessage(this.from, {
171
+ react: {
172
+ text: emojis[i],
173
+ key: fallbackResult.key
174
+ }
175
+ });
176
+ }
177
+ } catch (reactError) {
178
+ console.log('⚠️ Konnte keine Auto-Reactions hinzufügen:', reactError.message);
179
+ }
180
+ }, 1000);
181
+
182
+ return fallbackResult;
183
+ }
184
+ }
185
+
186
+ async sendMultiPoll(question, options, maxSelections = 1) {
187
+ if (!Array.isArray(options) || options.length < 2 || options.length > 12) {
188
+ throw new Error('Poll muss zwischen 2 und 12 Optionen haben');
189
+ }
190
+
191
+ try {
192
+ return await this.client.socket.sendMessage(this.from, {
193
+ poll: {
194
+ name: question,
195
+ values: options,
196
+ selectableCount: maxSelections
197
+ }
198
+ });
199
+ } catch (error) {
200
+ console.error('❌ Multi-Poll Fehler:', error);
201
+
202
+ // Fallback: Als normale Nachricht
203
+ let fallbackText = `📊 **${question}**\n_(Max. ${maxSelections} Auswahlen)_\n\n`;
204
+ options.forEach((option, index) => {
205
+ fallbackText += `${index + 1}. ${option}\n`;
206
+ });
207
+ fallbackText += `\n_Reagiere mit den entsprechenden Zahlen!_`;
208
+
209
+ return await this.reply(fallbackText);
210
+ }
211
+ }
212
+
213
+ // ===== UTILITY FUNCTIONS =====
214
+
215
+ async react(emoji) {
216
+ return await this.client.socket.sendMessage(this.from, {
217
+ react: {
218
+ text: emoji,
219
+ key: this.raw.key
220
+ }
221
+ });
222
+ }
223
+
224
+ async delete() {
225
+ return await this.client.socket.sendMessage(this.from, {
226
+ delete: this.raw.key
227
+ });
228
+ }
229
+
230
+ // ===== MENTION HELPERS =====
231
+
232
+ getMentions() {
233
+ return this.raw.message?.extendedTextMessage?.contextInfo?.mentionedJid || [];
234
+ }
235
+
236
+ isMentioned(jid) {
237
+ const mentions = this.getMentions();
238
+ return mentions.includes(jid);
239
+ }
240
+
241
+ async replyWithMention(text, userJid) {
242
+ const mentionText = text.replace('@user', `@${userJid.split('@')[0]}`);
243
+ return await this.reply(mentionText, [userJid]);
244
+ }
245
+
246
+ async mentionAll(text) {
247
+ if (!this.isGroup) {
248
+ throw new Error('Mention @all funktioniert nur in Gruppen');
249
+ }
250
+
251
+ const groupMetadata = await this.client.get.GroupMetadata(this.from);
252
+ const allMembers = groupMetadata.participants.map(p => p.id);
253
+ const mentionText = text + ' ' + allMembers.map(id => `@${id.split('@')[0]}`).join(' ');
254
+
255
+ return await this.reply(mentionText, allMembers);
256
+ }
257
+
258
+ // ===== PERMISSION SYSTEM =====
259
+
260
+ async isAdmin() {
261
+ if (!this.isGroup) return false;
262
+
263
+ try {
264
+ const groupMetadata = await this.client.get.GroupMetadata(this.from);
265
+ const senderJid = this.getSender();
266
+
267
+ console.log('🔍 Admin-Check für:', senderJid);
268
+
269
+ // Sender Nummer extrahieren
270
+ const senderNumber = senderJid.split('@')[0].split(':')[0];
271
+
272
+ console.log('👤 Sender Nummer:', senderNumber);
273
+
274
+ // Durch alle Teilnehmer suchen und Nummern vergleichen
275
+ for (const participant of groupMetadata.participants) {
276
+ const participantNumber = participant.id.split('@')[0].split(':')[0];
277
+
278
+ if (participantNumber === senderNumber) {
279
+ console.log(`✅ User gefunden! Participant: ${participant.id}, Admin: ${participant.admin}`);
280
+ return participant.admin === 'admin' || participant.admin === 'superadmin';
281
+ }
282
+ }
283
+
284
+ console.log('❌ User nicht in Teilnehmerliste gefunden');
285
+ return false;
286
+
287
+ } catch (error) {
288
+ console.error('❌ Fehler beim Admin-Check:', error);
289
+ return false;
290
+ }
291
+ }
292
+
293
+ async isBotAdmin() {
294
+ if (!this.isGroup) return false;
295
+
296
+ try {
297
+ const groupMetadata = await this.client.get.GroupMetadata(this.from);
298
+
299
+ // Bot JID richtig ermitteln
300
+ let botJid = this.client.socket.user?.id;
301
+ if (!botJid) {
302
+ console.log('⚠️ Bot JID nicht verfügbar');
303
+ return false;
304
+ }
305
+
306
+ console.log('🔍 Suche Bot in Gruppe...');
307
+ console.log('🤖 Bot Original JID:', botJid);
308
+
309
+ // Alle möglichen JID Varianten für den Bot
310
+ const botNumber = botJid.split('@')[0].split(':')[0]; // Nur die Nummer
311
+ console.log('🤖 Bot Nummer extrahiert:', botNumber);
312
+
313
+ console.log('👥 Alle Teilnehmer in der Gruppe:');
314
+ groupMetadata.participants.forEach((p, index) => {
315
+ const participantNumber = p.id.split('@')[0].split(':')[0];
316
+ console.log(` ${index + 1}. ${p.id} (Nummer: ${participantNumber}) - Admin: ${p.admin || 'false'}`);
317
+ });
318
+
319
+ // Durch alle Teilnehmer suchen
320
+ for (const participant of groupMetadata.participants) {
321
+ const participantNumber = participant.id.split('@')[0].split(':')[0];
322
+
323
+ console.log(`🔍 Vergleiche: Bot "${botNumber}" vs Participant "${participantNumber}"`);
324
+
325
+ // Nummern vergleichen (wichtigster Check)
326
+ if (participantNumber === botNumber) {
327
+ console.log(`✅ Bot gefunden! Participant: ${participant.id}, Admin: ${participant.admin}`);
328
+ return participant.admin === 'admin' || participant.admin === 'superadmin';
329
+ }
330
+ }
331
+
332
+ console.log('❌ Bot nicht in Teilnehmerliste gefunden');
333
+ console.log('💡 Mögliche Ursachen:');
334
+ console.log(' 1. Bot ist nicht in der Gruppe');
335
+ console.log(' 2. Bot hat eine andere Telefonnummer');
336
+ console.log(' 3. JID Format ist anders als erwartet');
337
+
338
+ return false;
339
+
340
+ } catch (error) {
341
+ console.error('❌ Fehler beim Bot-Admin-Check:', error);
342
+ return false;
343
+ }
344
+ }
345
+
346
+ async isOwner() {
347
+ if (!this.isGroup) return false;
348
+
349
+ try {
350
+ const groupMetadata = await this.client.get.GroupMetadata(this.from);
351
+ const senderJid = this.raw.key.participant || this.raw.key.remoteJid;
352
+ const participant = groupMetadata.participants.find(p => p.id === senderJid);
353
+
354
+ return participant && participant.admin === 'superadmin';
355
+ } catch (error) {
356
+ console.error('❌ Fehler beim Owner-Check:', error);
357
+ return false;
358
+ }
359
+ }
360
+
361
+ isPrivate() {
362
+ return !this.isGroup;
363
+ }
364
+
365
+ getSender() {
366
+ return this.raw.key.participant || this.raw.key.remoteJid;
367
+ }
368
+
369
+ // ===== STATISTICS SYSTEM =====
370
+
371
+ get stats() {
372
+ return new MessageStats(this);
373
+ }
374
+
375
+ // ===== TYPING INDICATOR SYSTEM =====
376
+
377
+ async startTyping() {
378
+ try {
379
+ await this.client.socket.sendPresenceUpdate('composing', this.from);
380
+ return true;
381
+ } catch (error) {
382
+ console.error('❌ Fehler beim Starten des Typing:', error);
383
+ return false;
384
+ }
385
+ }
386
+
387
+ async stopTyping() {
388
+ try {
389
+ await this.client.socket.sendPresenceUpdate('paused', this.from);
390
+ return true;
391
+ } catch (error) {
392
+ console.error('❌ Fehler beim Stoppen des Typing:', error);
393
+ return false;
394
+ }
395
+ }
396
+
397
+ async visualWrite(enabled, duration = null) {
398
+ if (enabled) {
399
+ await this.startTyping();
400
+
401
+ // Wenn Dauer angegeben, automatisch stoppen
402
+ if (duration) {
403
+ setTimeout(async () => {
404
+ await this.stopTyping();
405
+ }, duration);
406
+ }
407
+ } else {
408
+ await this.stopTyping();
409
+ }
410
+
411
+ return this; // Für Method Chaining
412
+ }
413
+
414
+ async typeAndReply(text, typingDuration = 2000, mentions = []) {
415
+ // Starte Typing
416
+ await this.startTyping();
417
+
418
+ // Warte die angegebene Zeit
419
+ await new Promise(resolve => setTimeout(resolve, typingDuration));
420
+
421
+ // Stoppe Typing und sende Nachricht
422
+ await this.stopTyping();
423
+
424
+ // Kurze Pause für Realismus
425
+ await new Promise(resolve => setTimeout(resolve, 300));
426
+
427
+ return await this.reply(text, mentions);
428
+ }
429
+
430
+ async typeAndSend(messageFunction, typingDuration = 2000) {
431
+ // Starte Typing
432
+ await this.startTyping();
433
+
434
+ // Warte die angegebene Zeit
435
+ await new Promise(resolve => setTimeout(resolve, typingDuration));
436
+
437
+ // Stoppe Typing
438
+ await this.stopTyping();
439
+
440
+ // Kurze Pause für Realismus
441
+ await new Promise(resolve => setTimeout(resolve, 300));
442
+
443
+ // Führe die Message-Funktion aus
444
+ return await messageFunction();
445
+ }
446
+
447
+ // Convenience Methods für verschiedene Typing-Zeiten
448
+ async quickType(text, mentions = []) {
449
+ return await this.typeAndReply(text, 1000, mentions);
450
+ }
451
+
452
+ async normalType(text, mentions = []) {
453
+ return await this.typeAndReply(text, 2000, mentions);
454
+ }
455
+
456
+ async slowType(text, mentions = []) {
457
+ return await this.typeAndReply(text, 4000, mentions);
458
+ }
459
+
460
+ // Simuliere realistisches Typing basierend auf Textlänge
461
+ async realisticType(text, mentions = []) {
462
+ // Berechne Typing-Zeit basierend auf Textlänge (ca. 50 WPM)
463
+ const wordsPerMinute = 50;
464
+ const words = text.split(' ').length;
465
+ const typingTime = Math.max(1000, (words / wordsPerMinute) * 60 * 1000);
466
+
467
+ return await this.typeAndReply(text, typingTime, mentions);
468
+ }
469
+
470
+ // ===== TYPING INDICATOR SYSTEM =====
471
+
472
+ async visualWrite(isTyping = true) {
473
+ try {
474
+ if (isTyping) {
475
+ // Starte "typing" Status
476
+ await this.client.socket.sendPresenceUpdate('composing', this.from);
477
+ console.log('⌨️ Typing indicator gestartet');
478
+ } else {
479
+ // Stoppe "typing" Status
480
+ await this.client.socket.sendPresenceUpdate('paused', this.from);
481
+ console.log('⏸️ Typing indicator gestoppt');
482
+ }
483
+ } catch (error) {
484
+ console.error('❌ Fehler beim Typing Indicator:', error);
485
+ }
486
+ }
487
+
488
+ async typeAndReply(text, typingDuration = 2000, mentions = []) {
489
+ try {
490
+ // Starte typing
491
+ await this.visualWrite(true);
492
+
493
+ // Warte die angegebene Zeit
494
+ await new Promise(resolve => setTimeout(resolve, typingDuration));
495
+
496
+ // Stoppe typing
497
+ await this.visualWrite(false);
498
+
499
+ // Sende Nachricht
500
+ return await this.reply(text, mentions);
501
+
502
+ } catch (error) {
503
+ console.error('❌ Fehler beim typeAndReply:', error);
504
+ // Fallback: Normale Reply
505
+ return await this.reply(text, mentions);
506
+ }
507
+ }
508
+
509
+ async typeFor(milliseconds) {
510
+ await this.visualWrite(true);
511
+ await new Promise(resolve => setTimeout(resolve, milliseconds));
512
+ await this.visualWrite(false);
513
+ }
514
+
515
+ async simulateTyping(text, options = {}) {
516
+ const {
517
+ typingSpeed = 50, // ms pro Zeichen
518
+ minTypingTime = 1000, // Minimum typing Zeit
519
+ maxTypingTime = 5000, // Maximum typing Zeit
520
+ mentions = []
521
+ } = options;
522
+
523
+ try {
524
+ // Berechne realistische Typing-Zeit basierend auf Text-Länge
525
+ const calculatedTime = Math.min(
526
+ Math.max(text.length * typingSpeed, minTypingTime),
527
+ maxTypingTime
528
+ );
529
+
530
+ console.log(`⌨️ Simuliere Typing für ${calculatedTime}ms (${text.length} Zeichen)`);
531
+
532
+ // Starte typing
533
+ await this.visualWrite(true);
534
+
535
+ // Warte realistische Zeit
536
+ await new Promise(resolve => setTimeout(resolve, calculatedTime));
537
+
538
+ // Stoppe typing
539
+ await this.visualWrite(false);
540
+
541
+ // Kurze Pause vor dem Senden (realistisch)
542
+ await new Promise(resolve => setTimeout(resolve, 200));
543
+
544
+ // Sende Nachricht
545
+ return await this.reply(text, mentions);
546
+
547
+ } catch (error) {
548
+ console.error('❌ Fehler beim simulateTyping:', error);
549
+ return await this.reply(text, mentions);
550
+ }
551
+ }
552
+ }
553
+
554
+ // ===== STATISTICS SYSTEM =====
555
+
556
+ class MessageStats {
557
+ constructor(message) {
558
+ this.message = message;
559
+ this.client = message.client;
560
+ }
561
+
562
+ async getMessageCount(chatId = null) {
563
+ const targetChat = chatId || this.message.from;
564
+
565
+ // Hier würdest du normalerweise eine Datenbank abfragen
566
+ // Für jetzt simulieren wir es
567
+ return {
568
+ total: Math.floor(Math.random() * 1000) + 100,
569
+ today: Math.floor(Math.random() * 50) + 10,
570
+ thisWeek: Math.floor(Math.random() * 200) + 50
571
+ };
572
+ }
573
+
574
+ async getUserActivity(userId = null) {
575
+ const targetUser = userId || this.message.getSender();
576
+
577
+ return {
578
+ userId: targetUser,
579
+ messagesCount: Math.floor(Math.random() * 500) + 50,
580
+ lastSeen: new Date(),
581
+ isActive: Math.random() > 0.5,
582
+ averagePerDay: Math.floor(Math.random() * 20) + 5
583
+ };
584
+ }
585
+
586
+ async getGroupStats() {
587
+ if (!this.message.isGroup) {
588
+ throw new Error('Stats nur in Gruppen verfügbar');
589
+ }
590
+
591
+ const metadata = await this.client.get.GroupMetadata(this.message.from);
592
+
593
+ return {
594
+ groupName: metadata.subject,
595
+ totalMembers: metadata.participants.length,
596
+ admins: metadata.participants.filter(p => p.admin).length,
597
+ created: new Date(metadata.creation * 1000),
598
+ description: metadata.desc || 'Keine Beschreibung'
599
+ };
600
+ }
601
+
602
+ async getMostActiveUsers(limit = 5) {
603
+ if (!this.message.isGroup) {
604
+ throw new Error('Stats nur in Gruppen verfügbar');
605
+ }
606
+
607
+ const metadata = await this.client.get.GroupMetadata(this.message.from);
608
+
609
+ // Simulierte Daten - in echter App würdest du echte Stats haben
610
+ return metadata.participants.slice(0, limit).map(p => ({
611
+ userId: p.id,
612
+ name: p.notify || p.id.split('@')[0],
613
+ messageCount: Math.floor(Math.random() * 200) + 10,
614
+ isAdmin: !!p.admin
615
+ }));
616
+ }
617
+
618
+ async getMessagesByType() {
619
+ return {
620
+ text: Math.floor(Math.random() * 500) + 100,
621
+ image: Math.floor(Math.random() * 100) + 20,
622
+ video: Math.floor(Math.random() * 50) + 10,
623
+ audio: Math.floor(Math.random() * 30) + 5,
624
+ sticker: Math.floor(Math.random() * 80) + 15,
625
+ document: Math.floor(Math.random() * 20) + 2
626
+ };
627
+ }
628
+ }
@@ -0,0 +1,80 @@
1
+ import { getSocket } from "./core.js";
2
+
3
+ export async function messages(callback) {
4
+ console.log("📡 Warte auf WhatsApp-Verbindung...");
5
+
6
+ try {
7
+ const sock = await getSocket();
8
+ console.log("🎧 Message-Listener wird aktiviert...");
9
+
10
+ // WICHTIG: Event-Listener NACH der Verbindung registrieren
11
+ sock.ev.on("messages.upsert", ({ messages, type }) => {
12
+ console.log(`\n🚨 MESSAGE EVENT EMPFANGEN!`);
13
+ console.log(`📊 Type: ${type}`);
14
+ console.log(`📈 Anzahl Messages: ${messages.length}`);
15
+ console.log(`📋 Raw Data:`, JSON.stringify({ messages, type }, null, 2));
16
+
17
+ if (type !== "notify") {
18
+ console.log(`⏭️ Ignoriere Message-Type: ${type} (nur 'notify' wird verarbeitet)`);
19
+ return;
20
+ }
21
+
22
+ for (let i = 0; i < messages.length; i++) {
23
+ const msg = messages[i];
24
+ console.log(`\n📨 Verarbeite Message ${i + 1}/${messages.length}:`);
25
+ console.log(`🔑 Key:`, msg.key);
26
+ console.log(`💬 Message:`, msg.message);
27
+
28
+ if (!msg.message) {
29
+ console.log("⚠️ Message ohne Content - wird ignoriert");
30
+ continue;
31
+ }
32
+
33
+ // Eigene Nachrichten ignorieren
34
+ if (msg.key.fromMe) {
35
+ console.log("📤 Eigene Nachricht - wird ignoriert");
36
+ continue;
37
+ }
38
+
39
+ const text =
40
+ msg.message.conversation ||
41
+ msg.message.extendedTextMessage?.text ||
42
+ msg.message.imageMessage?.caption ||
43
+ msg.message.videoMessage?.caption ||
44
+ msg.message.documentMessage?.caption ||
45
+ "[Media ohne Text]";
46
+
47
+ const from = msg.key.remoteJid;
48
+ const isGroup = from?.includes("@g.us");
49
+
50
+ console.log(`\n🎯 NACHRICHT GEFUNDEN:`);
51
+ console.log(` 📱 Von: ${from}`);
52
+ console.log(` 🏷️ Typ: ${isGroup ? 'Gruppe' : 'Privat'}`);
53
+ console.log(` 💬 Text: "${text}"`);
54
+ console.log(` ⏰ Zeit: ${new Date(msg.messageTimestamp * 1000).toLocaleString()}`);
55
+
56
+ // Callback aufrufen
57
+ try {
58
+ callback({
59
+ text,
60
+ from,
61
+ isGroup,
62
+ timestamp: msg.messageTimestamp,
63
+ id: msg.key.id,
64
+ raw: msg
65
+ });
66
+ console.log("✅ Callback erfolgreich ausgeführt");
67
+ } catch (callbackError) {
68
+ console.error("❌ Fehler im Callback:", callbackError);
69
+ }
70
+ }
71
+ });
72
+
73
+ console.log("✅ Message-Listener erfolgreich aktiviert!");
74
+ console.log("📱 Sende jetzt eine Nachricht an den Bot...");
75
+
76
+ } catch (error) {
77
+ console.error("❌ Fehler beim Setup der Message-Listener:", error);
78
+ throw error;
79
+ }
80
+ }