waengine 1.9.6 → 1.9.9

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.9.6",
3
+ "version": "1.9.9",
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
@@ -144,6 +144,12 @@ export class WhatsAppClient {
144
144
  this.ignoredMessagesCount = 0; // Counter für ignorierte Messages
145
145
  this.offlineMessageTimer = null; // Timer für finale Zusammenfassung
146
146
 
147
+ // ===== GLOBAL VISUAL TYPING/RECORDING SYSTEM - NEU! =====
148
+ this.globalVisualTyping = false; // Global aktiviert/deaktiviert
149
+ this.globalVisualRecord = false; // Global aktiviert/deaktiviert
150
+ this.visualTypingDuration = 2000; // Standard: 2 Sekunden
151
+ this.visualRecordDuration = 2000; // Standard: 2 Sekunden
152
+
147
153
  // Load API für Plugins
148
154
  this.load = {
149
155
  Plugins: async (pluginName) => {
@@ -169,6 +175,21 @@ export class WhatsAppClient {
169
175
  }
170
176
  };
171
177
 
178
+ // ===== GLOBAL VISUAL TYPING/RECORDING API - NEU! =====
179
+ // Set API für Dauer-Einstellungen
180
+ this.set = {
181
+ Visualtyping: (ms) => {
182
+ this.visualTypingDuration = ms;
183
+ console.log(`⌨️ Visual Typing Dauer: ${ms}ms`);
184
+ return this;
185
+ },
186
+ Visualrecord: (ms) => {
187
+ this.visualRecordDuration = ms;
188
+ console.log(`🎤 Visual Record Dauer: ${ms}ms`);
189
+ return this;
190
+ }
191
+ };
192
+
172
193
  // Deine eigenen API-Objekte
173
194
  this.get = new GetAPI(this);
174
195
  this.add = new AddAPI(this);
@@ -1257,6 +1278,60 @@ export class WhatsAppClient {
1257
1278
  }
1258
1279
  }
1259
1280
 
1281
+ // ===== GLOBAL VISUAL TYPING/RECORDING METHODS - NEU! =====
1282
+
1283
+ /**
1284
+ * Aktiviert/Deaktiviert globales Visual Typing für ALLE Nachrichten
1285
+ * @param {boolean} enabled - true = aktiviert, false = deaktiviert
1286
+ * @returns {WhatsAppClient} - this für Chaining
1287
+ */
1288
+ startVisualtyping(enabled = true) {
1289
+ this.globalVisualTyping = enabled;
1290
+ console.log(`⌨️ Global Visual Typing: ${enabled ? 'AKTIVIERT ✅' : 'DEAKTIVIERT ❌'}`);
1291
+ if (enabled) {
1292
+ console.log(` Dauer: ${this.visualTypingDuration}ms (änderbar mit client.set.Visualtyping(ms))`);
1293
+ }
1294
+ return this;
1295
+ }
1296
+
1297
+ /**
1298
+ * Aktiviert/Deaktiviert globales Visual Recording für ALLE Nachrichten
1299
+ * @param {boolean} enabled - true = aktiviert, false = deaktiviert
1300
+ * @returns {WhatsAppClient} - this für Chaining
1301
+ */
1302
+ startVisualrecord(enabled = true) {
1303
+ this.globalVisualRecord = enabled;
1304
+ console.log(`🎤 Global Visual Record: ${enabled ? 'AKTIVIERT ✅' : 'DEAKTIVIERT ❌'}`);
1305
+ if (enabled) {
1306
+ console.log(` Dauer: ${this.visualRecordDuration}ms (änderbar mit client.set.Visualrecord(ms))`);
1307
+ }
1308
+ return this;
1309
+ }
1310
+
1311
+ /**
1312
+ * Interne Methode: Führt Visual Typing/Recording aus wenn global aktiviert
1313
+ * @param {string} jid - Chat JID
1314
+ * @private
1315
+ */
1316
+ async _executeGlobalVisual(jid) {
1317
+ try {
1318
+ if (this.globalVisualTyping === true) {
1319
+ // Typing Indicator senden
1320
+ await this.socket.sendPresenceUpdate('composing', jid);
1321
+ await new Promise(resolve => setTimeout(resolve, this.visualTypingDuration));
1322
+ await this.socket.sendPresenceUpdate('paused', jid);
1323
+ } else if (this.globalVisualRecord === true) {
1324
+ // Recording Indicator senden
1325
+ await this.socket.sendPresenceUpdate('recording', jid);
1326
+ await new Promise(resolve => setTimeout(resolve, this.visualRecordDuration));
1327
+ await this.socket.sendPresenceUpdate('paused', jid);
1328
+ }
1329
+ } catch (error) {
1330
+ // Fehler ignorieren, damit Nachricht trotzdem gesendet wird
1331
+ console.error('⚠️ Visual Indicator Fehler:', error.message);
1332
+ }
1333
+ }
1334
+
1260
1335
  // ===== SENDCHAT API - Nachrichten an beliebige Chats senden! =====
1261
1336
 
1262
1337
  /**
@@ -0,0 +1,376 @@
1
+ /**
2
+ * WhatsApp Device Detector
3
+ * Erkennt Gerätetypen anhand der Message ID
4
+ *
5
+ * Message ID Struktur:
6
+ * - WhatsApp Web: 3EB0XXXXXXXXXXXXXXXX (beginnt oft mit 3EB0)
7
+ * - Android: Meist 20 Zeichen, alphanumerisch
8
+ * - iPhone: Meist mit Bindestrichen, z.B. XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
9
+ * - Desktop: Ähnlich wie Web, aber andere Präfixe
10
+ * - Business: Spezielle Präfixe wie BAE5
11
+ */
12
+
13
+ export class DeviceDetector {
14
+ constructor() {
15
+ // Pattern-Definitionen für verschiedene Gerätetypen
16
+ this.patterns = {
17
+ // WhatsApp Web - typische Präfixe
18
+ web: {
19
+ prefixes: ['3EB0', '3AA0', '3A', '3E'],
20
+ pattern: /^3[EA][AB0-9]{2}[A-F0-9]{16,20}$/i,
21
+ confidence: 0.85
22
+ },
23
+
24
+ // iPhone/iOS - oft mit Bindestrichen oder spezifischen Mustern
25
+ iphone: {
26
+ prefixes: ['BAE5', 'ABCD'],
27
+ pattern: /^[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}$/i,
28
+ alternativePattern: /^[A-F0-9]{32}$/i,
29
+ confidence: 0.80
30
+ },
31
+
32
+ // Android - meist alphanumerisch ohne Bindestriche
33
+ android: {
34
+ pattern: /^[A-F0-9]{20,32}$/i,
35
+ excludePrefixes: ['3EB0', '3AA0', 'BAE5'],
36
+ confidence: 0.75
37
+ },
38
+
39
+ // WhatsApp Desktop (Windows/Mac)
40
+ desktop: {
41
+ prefixes: ['3EB1', '3EB2', '3AA1'],
42
+ pattern: /^3[EA][AB][12][A-F0-9]{16,20}$/i,
43
+ confidence: 0.85
44
+ },
45
+
46
+ // WhatsApp Business
47
+ business: {
48
+ prefixes: ['BAE5', 'BAE6'],
49
+ pattern: /^BAE[56][A-F0-9]{16,20}$/i,
50
+ confidence: 0.90
51
+ }
52
+ };
53
+
54
+ // Statistiken
55
+ this.stats = {
56
+ total: 0,
57
+ detected: {},
58
+ unknown: 0
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Hauptfunktion: Erkennt Gerätetyp anhand der Message ID
64
+ * @param {string} messageId - Die WhatsApp Message ID
65
+ * @returns {Object} Erkennungsergebnis mit Gerätetyp und Confidence
66
+ */
67
+ detectDevice(messageId) {
68
+ if (!messageId || typeof messageId !== 'string') {
69
+ return this.createResult('unknown', 0, 'Ungültige Message ID');
70
+ }
71
+
72
+ this.stats.total++;
73
+
74
+ // Normalisiere Message ID (Großbuchstaben, Leerzeichen entfernen)
75
+ const normalizedId = messageId.trim().toUpperCase();
76
+
77
+ // Prüfe jeden Gerätetyp
78
+ const results = [];
79
+
80
+ // 1. Business Check (höchste Priorität)
81
+ const businessResult = this.checkBusiness(normalizedId);
82
+ if (businessResult.confidence > 0.7) {
83
+ return this.recordResult(businessResult);
84
+ }
85
+ results.push(businessResult);
86
+
87
+ // 2. iPhone Check
88
+ const iphoneResult = this.checkIPhone(normalizedId);
89
+ if (iphoneResult.confidence > 0.7) {
90
+ return this.recordResult(iphoneResult);
91
+ }
92
+ results.push(iphoneResult);
93
+
94
+ // 3. Desktop Check
95
+ const desktopResult = this.checkDesktop(normalizedId);
96
+ if (desktopResult.confidence > 0.7) {
97
+ return this.recordResult(desktopResult);
98
+ }
99
+ results.push(desktopResult);
100
+
101
+ // 4. Web Check
102
+ const webResult = this.checkWeb(normalizedId);
103
+ if (webResult.confidence > 0.7) {
104
+ return this.recordResult(webResult);
105
+ }
106
+ results.push(webResult);
107
+
108
+ // 5. Android Check (niedrigste Priorität, da am unspezifischsten)
109
+ const androidResult = this.checkAndroid(normalizedId);
110
+ results.push(androidResult);
111
+
112
+ // Bestes Ergebnis zurückgeben
113
+ const bestResult = results.reduce((best, current) =>
114
+ current.confidence > best.confidence ? current : best
115
+ );
116
+
117
+ return this.recordResult(bestResult);
118
+ }
119
+
120
+ /**
121
+ * Prüft auf WhatsApp Business
122
+ */
123
+ checkBusiness(messageId) {
124
+ const { prefixes, pattern, confidence } = this.patterns.business;
125
+
126
+ // Prefix-Check
127
+ const hasPrefix = prefixes.some(prefix => messageId.startsWith(prefix));
128
+ if (hasPrefix && pattern.test(messageId)) {
129
+ return this.createResult('business', confidence, 'Business Prefix erkannt');
130
+ }
131
+
132
+ return this.createResult('business', 0, 'Kein Business Pattern');
133
+ }
134
+
135
+ /**
136
+ * Prüft auf iPhone/iOS
137
+ */
138
+ checkIPhone(messageId) {
139
+ const { prefixes, pattern, alternativePattern, confidence } = this.patterns.iphone;
140
+
141
+ // UUID-Format (mit Bindestrichen)
142
+ if (pattern.test(messageId)) {
143
+ return this.createResult('iphone', confidence, 'UUID-Format erkannt');
144
+ }
145
+
146
+ // Alternative: 32 Zeichen Hex ohne Bindestriche
147
+ if (alternativePattern.test(messageId)) {
148
+ // Zusätzliche Heuristik: iPhone IDs haben oft bestimmte Charakteristiken
149
+ const hasIPhoneCharacteristics = this.hasIPhoneCharacteristics(messageId);
150
+ if (hasIPhoneCharacteristics) {
151
+ return this.createResult('iphone', confidence * 0.9, 'iPhone Charakteristiken erkannt');
152
+ }
153
+ }
154
+
155
+ // Prefix-Check
156
+ const hasPrefix = prefixes.some(prefix => messageId.startsWith(prefix));
157
+ if (hasPrefix) {
158
+ return this.createResult('iphone', confidence * 0.8, 'iPhone Prefix erkannt');
159
+ }
160
+
161
+ return this.createResult('iphone', 0, 'Kein iPhone Pattern');
162
+ }
163
+
164
+ /**
165
+ * Prüft auf WhatsApp Desktop
166
+ */
167
+ checkDesktop(messageId) {
168
+ const { prefixes, pattern, confidence } = this.patterns.desktop;
169
+
170
+ // Prefix-Check
171
+ const hasPrefix = prefixes.some(prefix => messageId.startsWith(prefix));
172
+ if (hasPrefix && pattern.test(messageId)) {
173
+ return this.createResult('desktop', confidence, 'Desktop Prefix erkannt');
174
+ }
175
+
176
+ return this.createResult('desktop', 0, 'Kein Desktop Pattern');
177
+ }
178
+
179
+ /**
180
+ * Prüft auf WhatsApp Web
181
+ */
182
+ checkWeb(messageId) {
183
+ const { prefixes, pattern, confidence } = this.patterns.web;
184
+
185
+ // Prefix-Check
186
+ const hasPrefix = prefixes.some(prefix => messageId.startsWith(prefix));
187
+ if (hasPrefix && pattern.test(messageId)) {
188
+ return this.createResult('web', confidence, 'Web Prefix erkannt');
189
+ }
190
+
191
+ return this.createResult('web', 0, 'Kein Web Pattern');
192
+ }
193
+
194
+ /**
195
+ * Prüft auf Android
196
+ */
197
+ checkAndroid(messageId) {
198
+ const { pattern, excludePrefixes, confidence } = this.patterns.android;
199
+
200
+ // Ausschluss-Check: Nicht wenn andere spezifische Präfixe
201
+ const hasExcludedPrefix = excludePrefixes.some(prefix =>
202
+ messageId.startsWith(prefix)
203
+ );
204
+
205
+ if (hasExcludedPrefix) {
206
+ return this.createResult('android', 0, 'Ausgeschlossener Prefix');
207
+ }
208
+
209
+ // Pattern-Check
210
+ if (pattern.test(messageId)) {
211
+ // Android ist der Fallback, daher niedrigere Confidence
212
+ return this.createResult('android', confidence, 'Android Pattern erkannt');
213
+ }
214
+
215
+ return this.createResult('android', 0, 'Kein Android Pattern');
216
+ }
217
+
218
+ /**
219
+ * Heuristische Prüfung auf iPhone-Charakteristiken
220
+ */
221
+ hasIPhoneCharacteristics(messageId) {
222
+ // iPhone IDs haben oft eine gleichmäßigere Verteilung von Zeichen
223
+ const charDistribution = this.analyzeCharDistribution(messageId);
224
+
225
+ // Prüfe auf gleichmäßige Verteilung (iPhone typisch)
226
+ const isBalanced = charDistribution.variance < 0.3;
227
+
228
+ return isBalanced;
229
+ }
230
+
231
+ /**
232
+ * Analysiert die Zeichenverteilung
233
+ */
234
+ analyzeCharDistribution(str) {
235
+ const counts = {};
236
+ for (const char of str) {
237
+ counts[char] = (counts[char] || 0) + 1;
238
+ }
239
+
240
+ const values = Object.values(counts);
241
+ const mean = values.reduce((a, b) => a + b, 0) / values.length;
242
+ const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;
243
+
244
+ return { mean, variance: variance / mean };
245
+ }
246
+
247
+ /**
248
+ * Erstellt ein Erkennungsergebnis
249
+ */
250
+ createResult(deviceType, confidence, reason) {
251
+ return {
252
+ deviceType,
253
+ confidence: Math.round(confidence * 100) / 100,
254
+ reason,
255
+ timestamp: Date.now()
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Zeichnet Ergebnis in Statistiken auf
261
+ */
262
+ recordResult(result) {
263
+ if (result.confidence > 0.5) {
264
+ this.stats.detected[result.deviceType] =
265
+ (this.stats.detected[result.deviceType] || 0) + 1;
266
+ } else {
267
+ this.stats.unknown++;
268
+ }
269
+
270
+ return result;
271
+ }
272
+
273
+ /**
274
+ * Batch-Erkennung für mehrere Message IDs
275
+ */
276
+ detectBatch(messageIds) {
277
+ return messageIds.map(id => ({
278
+ messageId: id,
279
+ ...this.detectDevice(id)
280
+ }));
281
+ }
282
+
283
+ /**
284
+ * Erweiterte Analyse mit zusätzlichen Informationen
285
+ */
286
+ analyzeMessage(message) {
287
+ const messageId = message.key?.id || message.id;
288
+ const detection = this.detectDevice(messageId);
289
+
290
+ return {
291
+ messageId,
292
+ ...detection,
293
+ metadata: {
294
+ length: messageId?.length || 0,
295
+ hasHyphens: messageId?.includes('-') || false,
296
+ prefix: messageId?.substring(0, 4) || '',
297
+ timestamp: message.messageTimestamp || message.timestamp,
298
+ from: message.key?.remoteJid || message.from,
299
+ isGroup: (message.key?.remoteJid || message.from)?.includes('@g.us')
300
+ }
301
+ };
302
+ }
303
+
304
+ /**
305
+ * Gibt Statistiken zurück
306
+ */
307
+ getStats() {
308
+ return {
309
+ ...this.stats,
310
+ detectionRate: this.stats.total > 0
311
+ ? Math.round(((this.stats.total - this.stats.unknown) / this.stats.total) * 100)
312
+ : 0
313
+ };
314
+ }
315
+
316
+ /**
317
+ * Setzt Statistiken zurück
318
+ */
319
+ resetStats() {
320
+ this.stats = {
321
+ total: 0,
322
+ detected: {},
323
+ unknown: 0
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Gibt eine lesbare Beschreibung des Gerätetyps zurück
329
+ */
330
+ getDeviceDescription(deviceType) {
331
+ const descriptions = {
332
+ web: '🌐 WhatsApp Web',
333
+ iphone: '📱 iPhone/iOS',
334
+ android: '🤖 Android',
335
+ desktop: '💻 WhatsApp Desktop',
336
+ business: '💼 WhatsApp Business',
337
+ unknown: '❓ Unbekannt'
338
+ };
339
+
340
+ return descriptions[deviceType] || descriptions.unknown;
341
+ }
342
+
343
+ /**
344
+ * Formatiert ein Erkennungsergebnis für die Ausgabe
345
+ */
346
+ formatResult(result) {
347
+ const description = this.getDeviceDescription(result.deviceType);
348
+ const confidenceBar = '█'.repeat(Math.round(result.confidence * 10));
349
+
350
+ return {
351
+ device: description,
352
+ confidence: `${Math.round(result.confidence * 100)}%`,
353
+ confidenceBar,
354
+ reason: result.reason,
355
+ reliable: result.confidence >= 0.7
356
+ };
357
+ }
358
+ }
359
+
360
+ // Singleton-Instanz für einfache Verwendung
361
+ export const deviceDetector = new DeviceDetector();
362
+
363
+ /**
364
+ * Convenience-Funktionen für direkten Import
365
+ */
366
+ export function detectDevice(messageId) {
367
+ return deviceDetector.detectDevice(messageId);
368
+ }
369
+
370
+ export function detectDeviceFromMessage(message) {
371
+ return deviceDetector.analyzeMessage(message);
372
+ }
373
+
374
+ export function getDeviceStats() {
375
+ return deviceDetector.getStats();
376
+ }
package/src/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { WhatsAppClient } from "./client.js";
2
2
  export { MultiWhatsAppClient } from "./multi-client.js";
3
3
  export { DeviceManager } from "./device-manager.js";
4
+ export { DeviceDetector, deviceDetector, detectDevice, detectDeviceFromMessage, getDeviceStats } from "./device-detector.js";
4
5
  export { PrefixManager } from "./prefix-manager.js";
5
6
  export { WAStorage, createStorage, getStorage, write, read, del } from "./storage.js";
6
7
  export { AIIntegration } from "./ai-integration.js";
package/src/message.js CHANGED
@@ -60,6 +60,9 @@ export class Message {
60
60
  // ===== REPLY FUNCTIONS =====
61
61
 
62
62
  async reply(text, mentions = [], options = {}) {
63
+ // ===== GLOBAL VISUAL TYPING/RECORDING - AUTOMATISCH! =====
64
+ await this.client._executeGlobalVisual(this.from);
65
+
63
66
  // Hidetag Feature - DEINE COOLE API!
64
67
  if (options.hidetag) {
65
68
  if (!this.isGroup) {
@@ -128,6 +131,9 @@ export class Message {
128
131
  }
129
132
 
130
133
  async sendImage(imagePath, caption = "", mentions = []) {
134
+ // ===== GLOBAL VISUAL TYPING/RECORDING - AUTOMATISCH! =====
135
+ await this.client._executeGlobalVisual(this.from);
136
+
131
137
  try {
132
138
  const message = {
133
139
  image: { url: imagePath },
@@ -146,6 +152,9 @@ export class Message {
146
152
  }
147
153
 
148
154
  async sendSticker(stickerPath) {
155
+ // ===== GLOBAL VISUAL TYPING/RECORDING - AUTOMATISCH! =====
156
+ await this.client._executeGlobalVisual(this.from);
157
+
149
158
  try {
150
159
  return await this.client.socket.sendMessage(this.from, {
151
160
  sticker: { url: stickerPath }