waengine 1.9.4 → 1.9.8

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.4",
3
+ "version": "1.9.8",
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);
@@ -1192,6 +1213,125 @@ export class WhatsAppClient {
1192
1213
  return await this.setPresence('paused', chatId);
1193
1214
  }
1194
1215
 
1216
+ // ===== BOT PROFILE UPDATE METHODS =====
1217
+
1218
+ /**
1219
+ * Aktualisiert das Profilbild des Bots
1220
+ * @param {string|Buffer} imagePath - Pfad zum Bild oder Buffer
1221
+ * @returns {Promise<boolean>} - Erfolg oder Fehler
1222
+ */
1223
+ async updateProfilePicture(imagePath) {
1224
+ try {
1225
+ const fs = await import('fs');
1226
+ let imageBuffer;
1227
+
1228
+ // Prüfe ob es ein Buffer oder Pfad ist
1229
+ if (Buffer.isBuffer(imagePath)) {
1230
+ imageBuffer = imagePath;
1231
+ } else {
1232
+ // Lade Bild von Pfad
1233
+ imageBuffer = fs.readFileSync(imagePath);
1234
+ }
1235
+
1236
+ // Hole eigene JID
1237
+ const myJid = this.socket.user.id;
1238
+
1239
+ // Update Profilbild
1240
+ await this.socket.updateProfilePicture(myJid, imageBuffer);
1241
+
1242
+ console.log('✅ Profilbild erfolgreich aktualisiert!');
1243
+ return true;
1244
+ } catch (error) {
1245
+ this.errorHandler.handleError(error, {
1246
+ action: 'update_profile_picture',
1247
+ details: 'Profilbild-Update fehlgeschlagen'
1248
+ });
1249
+ console.error('❌ Fehler beim Aktualisieren des Profilbilds:', error);
1250
+ return false;
1251
+ }
1252
+ }
1253
+
1254
+ /**
1255
+ * Aktualisiert den Namen/Nickname des Bots
1256
+ * @param {string} name - Neuer Name
1257
+ * @returns {Promise<boolean>} - Erfolg oder Fehler
1258
+ */
1259
+ async updateProfileName(name) {
1260
+ try {
1261
+ if (!name || typeof name !== 'string') {
1262
+ throw new Error('Name muss ein String sein');
1263
+ }
1264
+
1265
+ // Update Profilname
1266
+ await this.socket.updateProfileName(name);
1267
+
1268
+ console.log(`✅ Profilname erfolgreich aktualisiert: "${name}"`);
1269
+ return true;
1270
+ } catch (error) {
1271
+ this.errorHandler.handleError(error, {
1272
+ action: 'update_profile_name',
1273
+ name: name,
1274
+ details: 'Profilname-Update fehlgeschlagen'
1275
+ });
1276
+ console.error('❌ Fehler beim Aktualisieren des Profilnamens:', error);
1277
+ return false;
1278
+ }
1279
+ }
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
+
1195
1335
  // ===== SENDCHAT API - Nachrichten an beliebige Chats senden! =====
1196
1336
 
1197
1337
  /**
@@ -54,21 +54,58 @@ export class ConnectionRecovery {
54
54
  // Perform connection health check
55
55
  async performHealthCheck() {
56
56
  try {
57
+ // Basis-Check: Socket und Connection-Status
57
58
  if (!this.client.isConnected || !this.client.socket) {
58
59
  throw new Error('Not connected');
59
60
  }
60
61
 
61
- // Ping test
62
- await this.client.socket.query({
63
- tag: 'iq',
64
- attrs: { type: 'get', xmlns: 'w:p', id: 'health_' + Date.now() },
65
- content: [{ tag: 'ping' }]
66
- });
62
+ // Prüfe ob Socket wirklich tot ist oder nur inaktiv
63
+ const socketState = this.client.socket.ws?.readyState;
64
+
65
+ // WebSocket States: 0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED
66
+ if (socketState === 1) {
67
+ // Socket ist offen - alles gut, auch wenn inaktiv
68
+ this.state.lastSuccessTime = Date.now();
69
+ this.state.retryCount = 0;
70
+ return;
71
+ }
72
+
73
+ if (socketState === 0) {
74
+ // Socket verbindet noch - warten
75
+ console.log('🔄 Socket is connecting...');
76
+ return;
77
+ }
78
+
79
+ // Nur bei CLOSED oder CLOSING einen Ping-Test machen
80
+ if (socketState === 2 || socketState === 3) {
81
+ // Versuche Ping mit Timeout
82
+ const pingPromise = this.client.socket.query({
83
+ tag: 'iq',
84
+ attrs: { type: 'get', xmlns: 'w:p', id: 'health_' + Date.now() },
85
+ content: [{ tag: 'ping' }]
86
+ });
87
+
88
+ const timeoutPromise = new Promise((_, reject) =>
89
+ setTimeout(() => reject(new Error('Ping timeout')), 5000)
90
+ );
91
+
92
+ await Promise.race([pingPromise, timeoutPromise]);
93
+ }
67
94
 
68
95
  this.state.lastSuccessTime = Date.now();
69
96
  this.state.retryCount = 0;
70
97
 
71
98
  } catch (error) {
99
+ // Nur bei echten Verbindungsproblemen Recovery starten
100
+ const socketState = this.client.socket?.ws?.readyState;
101
+
102
+ if (socketState === 1) {
103
+ // Socket ist eigentlich offen - ignoriere Ping-Fehler
104
+ console.log('ℹ️ Ping failed but socket is open (device might be idle)');
105
+ this.state.lastSuccessTime = Date.now();
106
+ return;
107
+ }
108
+
72
109
  console.log('⚠️ Health check failed:', error.message);
73
110
  await this.initiateRecovery(error);
74
111
  }
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 }