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/LICENSE +21 -0
- package/README.md +911 -0
- package/examples/easy-bot-examples.js +186 -0
- package/examples/multi-device-example.js +253 -0
- package/examples/quick-start.js +10 -0
- package/examples/simple-multi-device.js +42 -0
- package/package.json +67 -0
- package/src/client.js +412 -0
- package/src/core.js +79 -0
- package/src/device-manager.js +404 -0
- package/src/easy-bot.js +744 -0
- package/src/groups.js +156 -0
- package/src/index.js +6 -0
- package/src/message.js +628 -0
- package/src/messages.js +80 -0
- package/src/multi-client.js +374 -0
- package/src/qr.js +65 -0
- package/src/utils.js +0 -0
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
|
+
}
|
package/src/messages.js
ADDED
|
@@ -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
|
+
}
|