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 +1 -1
- package/src/client.js +140 -0
- package/src/connection-recovery.js +43 -6
- package/src/message.js +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "waengine",
|
|
3
|
-
"version": "1.9.
|
|
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
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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 }
|