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
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import { DeviceManager } from "./device-manager.js";
|
|
2
|
+
import { Message } from "./message.js";
|
|
3
|
+
|
|
4
|
+
export class MultiWhatsAppClient {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.deviceManager = new DeviceManager({
|
|
7
|
+
maxDevices: options.maxDevices || 3,
|
|
8
|
+
loadBalancing: options.loadBalancing || 'round-robin',
|
|
9
|
+
syncEvents: options.syncEvents !== false,
|
|
10
|
+
...options
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
this.eventHandlers = new Map();
|
|
14
|
+
this.prefix = null;
|
|
15
|
+
this.commands = new Map();
|
|
16
|
+
|
|
17
|
+
// Device Manager Events weiterleiten
|
|
18
|
+
this.setupDeviceManagerEvents();
|
|
19
|
+
|
|
20
|
+
console.log("🚀 MultiWhatsAppClient initialisiert");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ===== DEVICE MANAGEMENT =====
|
|
24
|
+
|
|
25
|
+
async addDevice(deviceId, options = {}) {
|
|
26
|
+
const client = await this.deviceManager.addDevice(deviceId, options);
|
|
27
|
+
|
|
28
|
+
// Command System für jedes Device einrichten
|
|
29
|
+
if (this.prefix) {
|
|
30
|
+
client.setPrefix(this.prefix);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Commands zu jedem Device hinzufügen
|
|
34
|
+
for (const [command, handler] of this.commands) {
|
|
35
|
+
client.addCommand(command, handler);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return client;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async removeDevice(deviceId) {
|
|
42
|
+
return await this.deviceManager.removeDevice(deviceId);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ===== CONNECTION MANAGEMENT =====
|
|
46
|
+
|
|
47
|
+
async connect(deviceIds = null) {
|
|
48
|
+
if (deviceIds) {
|
|
49
|
+
// Spezifische Devices verbinden
|
|
50
|
+
const promises = deviceIds.map(id => this.deviceManager.connectDevice(id));
|
|
51
|
+
return await Promise.allSettled(promises);
|
|
52
|
+
} else {
|
|
53
|
+
// Alle Devices verbinden
|
|
54
|
+
return await this.deviceManager.connectAll();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async disconnect(deviceIds = null) {
|
|
59
|
+
if (deviceIds) {
|
|
60
|
+
const promises = deviceIds.map(id => this.deviceManager.disconnectDevice(id));
|
|
61
|
+
return await Promise.all(promises);
|
|
62
|
+
} else {
|
|
63
|
+
return await this.deviceManager.disconnectAll();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ===== MESSAGING SYSTEM =====
|
|
68
|
+
|
|
69
|
+
async sendMessage(chatId, content, options = {}) {
|
|
70
|
+
const strategy = options.strategy || 'load-balance';
|
|
71
|
+
return await this.deviceManager.smartSend(chatId, content, { ...options, strategy });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async broadcast(chatId, content, options = {}) {
|
|
75
|
+
return await this.deviceManager.broadcast.sendMessage(chatId, content, options);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async sendWithFailover(chatId, content, options = {}) {
|
|
79
|
+
return await this.deviceManager.sendWithFailover(chatId, content, options);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Spezifisches Device verwenden
|
|
83
|
+
async sendFromDevice(deviceId, chatId, content, options = {}) {
|
|
84
|
+
const client = this.deviceManager.getDevice(deviceId);
|
|
85
|
+
return await client.socket.sendMessage(chatId, content, options);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ===== COMMAND SYSTEM =====
|
|
89
|
+
|
|
90
|
+
setPrefix(prefix) {
|
|
91
|
+
this.prefix = prefix;
|
|
92
|
+
|
|
93
|
+
// Prefix für alle existierenden Devices setzen
|
|
94
|
+
for (const [deviceId, deviceData] of this.deviceManager.devices) {
|
|
95
|
+
if (deviceData.client) {
|
|
96
|
+
deviceData.client.setPrefix(prefix);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log(`🎯 Multi-Device Prefix gesetzt: "${prefix}"`);
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
addCommand(command, handler) {
|
|
105
|
+
this.commands.set(command.toLowerCase(), handler);
|
|
106
|
+
|
|
107
|
+
// Command für alle existierenden Devices hinzufügen
|
|
108
|
+
for (const [deviceId, deviceData] of this.deviceManager.devices) {
|
|
109
|
+
if (deviceData.client) {
|
|
110
|
+
deviceData.client.addCommand(command, handler);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log(`⚡ Multi-Device Command registriert: ${this.prefix || ''}${command}`);
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
removeCommand(command) {
|
|
119
|
+
this.commands.delete(command.toLowerCase());
|
|
120
|
+
|
|
121
|
+
// Command von allen Devices entfernen
|
|
122
|
+
for (const [deviceId, deviceData] of this.deviceManager.devices) {
|
|
123
|
+
if (deviceData.client) {
|
|
124
|
+
deviceData.client.removeCommand(command);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log(`🗑️ Multi-Device Command entfernt: ${command}`);
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
getCommands() {
|
|
133
|
+
return Array.from(this.commands.keys());
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ===== EVENT SYSTEM =====
|
|
137
|
+
|
|
138
|
+
setupDeviceManagerEvents() {
|
|
139
|
+
// Message Events von allen Devices sammeln
|
|
140
|
+
this.deviceManager.on('message', (data) => {
|
|
141
|
+
const { deviceId, ...messageData } = data;
|
|
142
|
+
|
|
143
|
+
// Message Object erweitern mit Device-Info
|
|
144
|
+
const enhancedMessage = {
|
|
145
|
+
...messageData,
|
|
146
|
+
deviceId,
|
|
147
|
+
multiDevice: true,
|
|
148
|
+
|
|
149
|
+
// Multi-Device Reply Funktionen
|
|
150
|
+
replyFromSameDevice: async (content, options = {}) => {
|
|
151
|
+
const client = this.deviceManager.getDevice(deviceId);
|
|
152
|
+
const msg = new Message(client, messageData);
|
|
153
|
+
return await msg.reply(content, options);
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
replyFromAnyDevice: async (content, options = {}) => {
|
|
157
|
+
return await this.sendMessage(messageData.from, { text: content }, options);
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
broadcastReply: async (content, options = {}) => {
|
|
161
|
+
return await this.broadcast(messageData.from, { text: content }, options);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
this.emit('message', enhancedMessage);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Device Events weiterleiten
|
|
169
|
+
this.deviceManager.on('device.connected', (data) => {
|
|
170
|
+
this.emit('device.connected', data);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
this.deviceManager.on('device.disconnected', (data) => {
|
|
174
|
+
this.emit('device.disconnected', data);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
this.deviceManager.on('device.error', (data) => {
|
|
178
|
+
this.emit('device.error', data);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
on(event, handler) {
|
|
183
|
+
if (!this.eventHandlers.has(event)) {
|
|
184
|
+
this.eventHandlers.set(event, []);
|
|
185
|
+
}
|
|
186
|
+
this.eventHandlers.get(event).push(handler);
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
off(event, handler) {
|
|
191
|
+
if (this.eventHandlers.has(event)) {
|
|
192
|
+
const handlers = this.eventHandlers.get(event);
|
|
193
|
+
const index = handlers.indexOf(handler);
|
|
194
|
+
if (index > -1) {
|
|
195
|
+
handlers.splice(index, 1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return this;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
emit(event, data) {
|
|
202
|
+
if (this.eventHandlers.has(event)) {
|
|
203
|
+
this.eventHandlers.get(event).forEach(handler => {
|
|
204
|
+
try {
|
|
205
|
+
handler(data);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.error(`❌ Multi-Client Event Handler Fehler '${event}':`, error);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ===== PRESENCE SYSTEM =====
|
|
214
|
+
|
|
215
|
+
async setPresence(presence, chatId = null, deviceId = null) {
|
|
216
|
+
if (deviceId) {
|
|
217
|
+
// Spezifisches Device
|
|
218
|
+
const client = this.deviceManager.getDevice(deviceId);
|
|
219
|
+
return await client.setPresence(presence, chatId);
|
|
220
|
+
} else {
|
|
221
|
+
// Alle aktiven Devices
|
|
222
|
+
const results = [];
|
|
223
|
+
for (const activeDeviceId of this.deviceManager.activeDevices) {
|
|
224
|
+
try {
|
|
225
|
+
const client = this.deviceManager.getDevice(activeDeviceId);
|
|
226
|
+
const result = await client.setPresence(presence, chatId);
|
|
227
|
+
results.push({ deviceId: activeDeviceId, success: result });
|
|
228
|
+
} catch (error) {
|
|
229
|
+
results.push({ deviceId: activeDeviceId, success: false, error: error.message });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return results;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async setOnline(deviceId = null) {
|
|
237
|
+
return await this.setPresence('available', null, deviceId);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async setOffline(deviceId = null) {
|
|
241
|
+
return await this.setPresence('unavailable', null, deviceId);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async setTyping(chatId, deviceId = null) {
|
|
245
|
+
return await this.setPresence('composing', chatId, deviceId);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ===== GROUP MANAGEMENT =====
|
|
249
|
+
|
|
250
|
+
get group() {
|
|
251
|
+
return {
|
|
252
|
+
// Group-Aktionen mit Load Balancing
|
|
253
|
+
add: async (groupId, users, mentions = [], deviceId = null) => {
|
|
254
|
+
const client = deviceId ?
|
|
255
|
+
this.deviceManager.getDevice(deviceId) :
|
|
256
|
+
this.deviceManager.getNextDevice();
|
|
257
|
+
|
|
258
|
+
return await client.add.user(groupId, users, mentions);
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
kick: async (groupId, users, mentions = [], deviceId = null) => {
|
|
262
|
+
const client = deviceId ?
|
|
263
|
+
this.deviceManager.getDevice(deviceId) :
|
|
264
|
+
this.deviceManager.getNextDevice();
|
|
265
|
+
|
|
266
|
+
return await client.kick.user(groupId, users, mentions);
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
promote: async (groupId, users, mentions = [], deviceId = null) => {
|
|
270
|
+
const client = deviceId ?
|
|
271
|
+
this.deviceManager.getDevice(deviceId) :
|
|
272
|
+
this.deviceManager.getNextDevice();
|
|
273
|
+
|
|
274
|
+
return await client.promote.user(groupId, users, mentions);
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
demote: async (groupId, users, mentions = [], deviceId = null) => {
|
|
278
|
+
const client = deviceId ?
|
|
279
|
+
this.deviceManager.getDevice(deviceId) :
|
|
280
|
+
this.deviceManager.getNextDevice();
|
|
281
|
+
|
|
282
|
+
return await client.demote.user(groupId, users, mentions);
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
getMetadata: async (groupId, deviceId = null) => {
|
|
286
|
+
const client = deviceId ?
|
|
287
|
+
this.deviceManager.getDevice(deviceId) :
|
|
288
|
+
this.deviceManager.getNextDevice();
|
|
289
|
+
|
|
290
|
+
return await client.get.GroupMetadata(groupId);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ===== STATUS & MONITORING =====
|
|
296
|
+
|
|
297
|
+
getStatus() {
|
|
298
|
+
return this.deviceManager.getStatus();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
getHealthCheck() {
|
|
302
|
+
return this.deviceManager.getHealthCheck();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
getDeviceStats() {
|
|
306
|
+
const status = this.getStatus();
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
...status,
|
|
310
|
+
loadBalancingStrategy: this.deviceManager.config.loadBalancing,
|
|
311
|
+
totalCommands: this.commands.size,
|
|
312
|
+
prefix: this.prefix,
|
|
313
|
+
uptime: process.uptime()
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ===== UTILITY =====
|
|
318
|
+
|
|
319
|
+
getDevice(deviceId) {
|
|
320
|
+
return this.deviceManager.getDevice(deviceId);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
getActiveDevices() {
|
|
324
|
+
return Array.from(this.deviceManager.activeDevices);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
getNextDevice() {
|
|
328
|
+
return this.deviceManager.getNextDevice();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async cleanup() {
|
|
332
|
+
console.log("🧹 MultiWhatsAppClient Cleanup...");
|
|
333
|
+
await this.deviceManager.cleanup();
|
|
334
|
+
this.eventHandlers.clear();
|
|
335
|
+
this.commands.clear();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ===== ADVANCED FEATURES =====
|
|
339
|
+
|
|
340
|
+
// Device-spezifische Konfiguration
|
|
341
|
+
async configureDevice(deviceId, config) {
|
|
342
|
+
const device = this.deviceManager.devices.get(deviceId);
|
|
343
|
+
if (!device) {
|
|
344
|
+
throw new Error(`❌ Device '${deviceId}' nicht gefunden!`);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
Object.assign(device.options, config);
|
|
348
|
+
console.log(`⚙️ Device '${deviceId}' konfiguriert:`, config);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Load Balancing Strategy ändern
|
|
352
|
+
setLoadBalancingStrategy(strategy) {
|
|
353
|
+
this.deviceManager.config.loadBalancing = strategy;
|
|
354
|
+
console.log(`⚖️ Load Balancing Strategy geändert: ${strategy}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Device Rotation für gleichmäßige Nutzung
|
|
358
|
+
async rotateDevices() {
|
|
359
|
+
const devices = Array.from(this.deviceManager.activeDevices);
|
|
360
|
+
if (devices.length < 2) return;
|
|
361
|
+
|
|
362
|
+
// Erstes Device temporär deaktivieren
|
|
363
|
+
const firstDevice = devices[0];
|
|
364
|
+
this.deviceManager.activeDevices.delete(firstDevice);
|
|
365
|
+
|
|
366
|
+
// Nach 30 Sekunden wieder aktivieren
|
|
367
|
+
setTimeout(() => {
|
|
368
|
+
this.deviceManager.activeDevices.add(firstDevice);
|
|
369
|
+
console.log(`🔄 Device '${firstDevice}' wieder aktiviert`);
|
|
370
|
+
}, 30000);
|
|
371
|
+
|
|
372
|
+
console.log(`🔄 Device Rotation: '${firstDevice}' temporär deaktiviert`);
|
|
373
|
+
}
|
|
374
|
+
}
|
package/src/qr.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { chromium } from "playwright";
|
|
2
|
+
import qrcode from "qrcode-terminal";
|
|
3
|
+
|
|
4
|
+
let browser = null;
|
|
5
|
+
let page = null;
|
|
6
|
+
|
|
7
|
+
export async function generateQRCode(qrData = null) {
|
|
8
|
+
try {
|
|
9
|
+
// Browser öffnen falls noch nicht offen
|
|
10
|
+
if (!browser) {
|
|
11
|
+
console.log("🌐 Öffne Microsoft Edge...");
|
|
12
|
+
browser = await chromium.launch({
|
|
13
|
+
channel: "msedge",
|
|
14
|
+
headless: false
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Neue Seite öffnen falls noch nicht vorhanden
|
|
19
|
+
if (!page) {
|
|
20
|
+
page = await browser.newPage();
|
|
21
|
+
await page.goto("https://web.whatsapp.com");
|
|
22
|
+
console.log("🌐 Microsoft Edge mit WhatsApp Web geöffnet");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// QR-Code anzeigen falls vorhanden
|
|
26
|
+
if (qrData) {
|
|
27
|
+
console.log("\n📱 QR-CODE GENERIERT!");
|
|
28
|
+
console.log("👆 Scanne den QR-Code im Edge Browser ODER hier im Terminal:");
|
|
29
|
+
console.log("─".repeat(50));
|
|
30
|
+
|
|
31
|
+
// QR-Code im Terminal anzeigen
|
|
32
|
+
qrcode.generate(qrData, { small: true });
|
|
33
|
+
|
|
34
|
+
console.log("─".repeat(50));
|
|
35
|
+
console.log("📲 Öffne WhatsApp auf deinem Handy:");
|
|
36
|
+
console.log(" 1. Gehe zu Einstellungen");
|
|
37
|
+
console.log(" 2. Tippe auf 'Verknüpfte Geräte'");
|
|
38
|
+
console.log(" 3. Tippe auf 'Gerät verknüpfen'");
|
|
39
|
+
console.log(" 4. Scanne den QR-Code");
|
|
40
|
+
console.log("⏳ Warte auf QR-Scan...");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { browser, page };
|
|
44
|
+
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error("❌ Fehler beim Öffnen von Edge:", error);
|
|
47
|
+
|
|
48
|
+
// Fallback: QR nur im Terminal
|
|
49
|
+
if (qrData) {
|
|
50
|
+
console.log("📱 Fallback - QR-Code im Terminal:");
|
|
51
|
+
qrcode.generate(qrData, { small: true });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function closeBrowser() {
|
|
59
|
+
if (browser) {
|
|
60
|
+
await browser.close();
|
|
61
|
+
browser = null;
|
|
62
|
+
page = null;
|
|
63
|
+
console.log("🔴 Browser geschlossen");
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/utils.js
ADDED
|
File without changes
|