waengine 1.0.8 → 1.0.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.
@@ -0,0 +1,221 @@
1
+ // 🎵 Music Plugin mit yt-dlp
2
+ import { exec } from 'child_process';
3
+ import { promisify } from 'util';
4
+
5
+ const execAsync = promisify(exec);
6
+
7
+ export default class MusicPlugin {
8
+ constructor(client) {
9
+ this.client = client;
10
+ this.name = 'music-plugin';
11
+ this.version = '1.0.0';
12
+ this.description = 'Music System mit YouTube Download und Spotify Integration';
13
+ }
14
+
15
+ async searchYouTube(query) {
16
+ try {
17
+ const { stdout } = await execAsync(`yt-dlp --dump-json "ytsearch5:${query}"`);
18
+ const results = stdout.trim().split('\n').map(line => JSON.parse(line));
19
+
20
+ return results.map(video => ({
21
+ id: video.id,
22
+ title: video.title,
23
+ duration: video.duration,
24
+ uploader: video.uploader,
25
+ url: video.webpage_url,
26
+ thumbnail: video.thumbnail
27
+ }));
28
+ } catch (error) {
29
+ console.error('YouTube Search Error:', error);
30
+ return [];
31
+ }
32
+ }
33
+
34
+ async getVideoInfo(url) {
35
+ try {
36
+ const { stdout } = await execAsync(`yt-dlp --dump-json "${url}"`);
37
+ const info = JSON.parse(stdout);
38
+
39
+ return {
40
+ id: info.id,
41
+ title: info.title,
42
+ duration: info.duration,
43
+ uploader: info.uploader,
44
+ description: info.description,
45
+ thumbnail: info.thumbnail,
46
+ formats: info.formats
47
+ };
48
+ } catch (error) {
49
+ console.error('Video Info Error:', error);
50
+ return null;
51
+ }
52
+ }
53
+
54
+ async downloadAudio(url, quality = 'best') {
55
+ try {
56
+ const outputPath = `./downloads/%(title)s.%(ext)s`;
57
+ const command = `yt-dlp -x --audio-format mp3 --audio-quality ${quality} -o "${outputPath}" "${url}"`;
58
+
59
+ const { stdout } = await execAsync(command);
60
+ return { success: true, output: stdout };
61
+ } catch (error) {
62
+ console.error('Download Error:', error);
63
+ return { success: false, error: error.message };
64
+ }
65
+ }
66
+
67
+ formatDuration(seconds) {
68
+ const minutes = Math.floor(seconds / 60);
69
+ const remainingSeconds = seconds % 60;
70
+ return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
71
+ }
72
+
73
+ async createPlaylist(userId, name) {
74
+ const playlistId = Date.now().toString();
75
+ this.client.storage.write.in('music').set(`playlists.${playlistId}`, {
76
+ id: playlistId,
77
+ name,
78
+ owner: userId,
79
+ songs: [],
80
+ created: Date.now()
81
+ });
82
+
83
+ return playlistId;
84
+ }
85
+
86
+ async addToPlaylist(playlistId, song) {
87
+ this.client.storage.write.in('music').push(`playlists.${playlistId}.songs`, song);
88
+ }
89
+
90
+ async getUserPlaylists(userId) {
91
+ const playlists = this.client.storage.read.from('music').get('playlists') || {};
92
+ return Object.values(playlists).filter(playlist => playlist.owner === userId);
93
+ }
94
+
95
+ getCommands() {
96
+ return {
97
+ 'music': this.handleMusic.bind(this),
98
+ 'youtube': this.handleYouTube.bind(this),
99
+ 'download': this.handleDownload.bind(this),
100
+ 'playlist': this.handlePlaylist.bind(this),
101
+ 'lyrics': this.handleLyrics.bind(this),
102
+ 'spotify': this.handleSpotify.bind(this)
103
+ };
104
+ }
105
+
106
+ async handleMusic(msg, args) {
107
+ if (args.length === 0) {
108
+ return msg.reply(`🎵 **Music Plugin Commands:**
109
+
110
+ 🔍 !music search <song> - Musik suchen
111
+ 📺 !youtube <query> - YouTube suchen
112
+ ⬇️ !download <url> - Audio downloaden
113
+ 📋 !playlist - Playlist verwalten
114
+ 📝 !lyrics <song> - Songtexte suchen
115
+ 🎧 !spotify - Spotify Features`);
116
+ }
117
+
118
+ const action = args[0].toLowerCase();
119
+ const query = args.slice(1).join(' ');
120
+
121
+ if (action === 'search') {
122
+ if (!query) return msg.reply('❌ Gib einen Suchbegriff ein!');
123
+
124
+ await msg.reply('🔍 Suche Musik...');
125
+ const results = await this.searchYouTube(query);
126
+
127
+ if (results.length === 0) {
128
+ return msg.reply('❌ Keine Ergebnisse gefunden!');
129
+ }
130
+
131
+ let resultText = `🎵 **Suchergebnisse für "${query}":**\n\n`;
132
+ results.slice(0, 3).forEach((video, index) => {
133
+ resultText += `${index + 1}. **${video.title}**\n`;
134
+ resultText += `👤 ${video.uploader}\n`;
135
+ resultText += `⏱️ ${this.formatDuration(video.duration)}\n`;
136
+ resultText += `🔗 ${video.url}\n\n`;
137
+ });
138
+
139
+ await msg.reply(resultText);
140
+ }
141
+ }
142
+
143
+ async handleYouTube(msg, args) {
144
+ if (args.length === 0) {
145
+ return msg.reply('❌ Verwendung: !youtube <suchbegriff>');
146
+ }
147
+
148
+ const query = args.join(' ');
149
+ await msg.reply('📺 Suche auf YouTube...');
150
+
151
+ const results = await this.searchYouTube(query);
152
+
153
+ if (results.length === 0) {
154
+ return msg.reply('❌ Keine YouTube Videos gefunden!');
155
+ }
156
+
157
+ let resultText = `📺 **YouTube Ergebnisse:**\n\n`;
158
+ results.slice(0, 5).forEach((video, index) => {
159
+ resultText += `${index + 1}. **${video.title}**\n`;
160
+ resultText += `👤 ${video.uploader}\n`;
161
+ resultText += `⏱️ ${this.formatDuration(video.duration)}\n`;
162
+ resultText += `🔗 ${video.url}\n\n`;
163
+ });
164
+
165
+ resultText += '⬇️ Download mit: !download <url>';
166
+ await msg.reply(resultText);
167
+ }
168
+ async handleDownload(msg, args) {
169
+ if (args.length === 0) {
170
+ return msg.reply('❌ Verwendung: !download <youtube-url>');
171
+ }
172
+
173
+ const url = args[0];
174
+ await msg.reply('⬇️ Starte Download...');
175
+
176
+ const result = await this.downloadAudio(url);
177
+
178
+ if (result.success) {
179
+ await msg.reply('✅ Download erfolgreich! Audio wird verarbeitet...');
180
+ } else {
181
+ await msg.reply(`❌ Download fehlgeschlagen: ${result.error}`);
182
+ }
183
+ }
184
+
185
+ async handlePlaylist(msg, args) {
186
+ const userId = msg.getSender();
187
+
188
+ if (args.length === 0) {
189
+ const playlists = await this.getUserPlaylists(userId);
190
+
191
+ if (playlists.length === 0) {
192
+ return msg.reply('📋 **Keine Playlists gefunden!**\n\n💡 Erstelle eine mit: !playlist create <name>');
193
+ }
194
+
195
+ let playlistText = '📋 **Deine Playlists:**\n\n';
196
+ playlists.forEach((playlist, index) => {
197
+ playlistText += `${index + 1}. **${playlist.name}**\n`;
198
+ playlistText += `🎵 ${playlist.songs.length} Songs\n`;
199
+ playlistText += `📅 Erstellt: ${new Date(playlist.created).toLocaleDateString()}\n\n`;
200
+ });
201
+
202
+ await msg.reply(playlistText);
203
+ }
204
+ }
205
+
206
+ async handleLyrics(msg, args) {
207
+ if (args.length === 0) {
208
+ return msg.reply('❌ Verwendung: !lyrics <song title>');
209
+ }
210
+
211
+ const song = args.join(' ');
212
+ await msg.reply(`🔍 Suche Songtexte für "${song}"...`);
213
+
214
+ // Placeholder - hier würdest du eine Lyrics API verwenden
215
+ await msg.reply(`📝 **Songtexte für "${song}":**\n\n_Lyrics API Integration folgt..._\n\n💡 Verwende eine Lyrics API wie Genius oder AZLyrics`);
216
+ }
217
+
218
+ async handleSpotify(msg, args) {
219
+ await msg.reply(`🎧 **Spotify Integration:**\n\n_Spotify API Integration folgt..._\n\n💡 Features:\n• Now Playing\n• Playlists\n• Search\n• Recommendations`);
220
+ }
221
+ }
@@ -0,0 +1,230 @@
1
+ // 🌍 Travel Plugin
2
+ export default class TravelPlugin {
3
+ constructor(client) {
4
+ this.client = client;
5
+ this.name = 'travel-plugin';
6
+ this.version = '1.0.0';
7
+ this.description = 'Reise-System mit Wetter, Flügen, Hotels und Währungsrechner';
8
+ }
9
+
10
+ async getWeather(city) {
11
+ try {
12
+ // Verwende den HTTP Client für Wetter-API
13
+ return await this.client.http.getWeather(city);
14
+ } catch (error) {
15
+ return {
16
+ city: city,
17
+ temperature: Math.floor(Math.random() * 30) + 5,
18
+ description: 'Teilweise bewölkt',
19
+ humidity: Math.floor(Math.random() * 40) + 40,
20
+ windSpeed: Math.floor(Math.random() * 10) + 2
21
+ };
22
+ }
23
+ }
24
+
25
+ async searchFlights(from, to) {
26
+ // Simulierte Flugdaten
27
+ const airlines = ['Lufthansa', 'Ryanair', 'Eurowings', 'Turkish Airlines', 'Emirates'];
28
+ const flights = [];
29
+
30
+ for (let i = 0; i < 3; i++) {
31
+ flights.push({
32
+ airline: airlines[Math.floor(Math.random() * airlines.length)],
33
+ departure: `${Math.floor(Math.random() * 12) + 6}:${Math.floor(Math.random() * 6) * 10}`,
34
+ arrival: `${Math.floor(Math.random() * 12) + 12}:${Math.floor(Math.random() * 6) * 10}`,
35
+ price: Math.floor(Math.random() * 500) + 100,
36
+ duration: `${Math.floor(Math.random() * 8) + 2}h ${Math.floor(Math.random() * 6) * 10}m`,
37
+ stops: Math.floor(Math.random() * 3)
38
+ });
39
+ }
40
+
41
+ return flights;
42
+ }
43
+
44
+ async searchHotels(city) {
45
+ const hotelNames = ['Hotel Central', 'Grand Palace', 'City Inn', 'Comfort Suites', 'Luxury Resort'];
46
+ const hotels = [];
47
+
48
+ for (let i = 0; i < 4; i++) {
49
+ hotels.push({
50
+ name: hotelNames[Math.floor(Math.random() * hotelNames.length)],
51
+ stars: Math.floor(Math.random() * 3) + 3,
52
+ price: Math.floor(Math.random() * 200) + 50,
53
+ rating: (Math.random() * 2 + 3).toFixed(1),
54
+ amenities: ['WiFi', 'Pool', 'Gym', 'Restaurant'].slice(0, Math.floor(Math.random() * 4) + 1)
55
+ });
56
+ }
57
+
58
+ return hotels;
59
+ }
60
+
61
+ async convertCurrency(amount, from, to) {
62
+ // Simulierte Wechselkurse
63
+ const rates = {
64
+ 'USD': { 'EUR': 0.85, 'GBP': 0.73, 'JPY': 110 },
65
+ 'EUR': { 'USD': 1.18, 'GBP': 0.86, 'JPY': 130 },
66
+ 'GBP': { 'USD': 1.37, 'EUR': 1.16, 'JPY': 151 }
67
+ };
68
+
69
+ if (from === to) return amount;
70
+
71
+ const rate = rates[from]?.[to] || 1;
72
+ const converted = (amount * rate).toFixed(2);
73
+
74
+ return {
75
+ original: amount,
76
+ converted: parseFloat(converted),
77
+ fromCurrency: from,
78
+ toCurrency: to,
79
+ rate: rate
80
+ };
81
+ }
82
+
83
+ async translateText(text, targetLang) {
84
+ // Verwende AI Integration falls verfügbar
85
+ try {
86
+ return await this.client.ai.translate(text, targetLang);
87
+ } catch (error) {
88
+ return `[Übersetzung zu ${targetLang}]: ${text}`;
89
+ }
90
+ }
91
+
92
+ getCommands() {
93
+ return {
94
+ 'weather': this.handleWeather.bind(this),
95
+ 'flights': this.handleFlights.bind(this),
96
+ 'hotels': this.handleHotels.bind(this),
97
+ 'currency': this.handleCurrency.bind(this),
98
+ 'translate': this.handleTranslate.bind(this),
99
+ 'travel': this.handleTravel.bind(this)
100
+ };
101
+ }
102
+
103
+ async handleWeather(msg, args) {
104
+ if (args.length === 0) {
105
+ return msg.reply('❌ Verwendung: !weather <stadt>\n\n🌤️ Beispiel: !weather Berlin');
106
+ }
107
+
108
+ const city = args.join(' ');
109
+ await msg.reply(`🌤️ Lade Wetterdaten für ${city}...`);
110
+
111
+ const weather = await this.getWeather(city);
112
+
113
+ let weatherText = `🌤️ **Wetter in ${weather.city}:**\n\n`;
114
+ weatherText += `🌡️ Temperatur: ${weather.temperature}°C\n`;
115
+ weatherText += `☁️ Bedingungen: ${weather.description}\n`;
116
+ weatherText += `💧 Luftfeuchtigkeit: ${weather.humidity}%\n`;
117
+ weatherText += `💨 Windgeschwindigkeit: ${weather.windSpeed} km/h`;
118
+
119
+ await msg.reply(weatherText);
120
+ }
121
+
122
+ async handleFlights(msg, args) {
123
+ if (args.length < 2) {
124
+ return msg.reply('❌ Verwendung: !flights <von> <nach>\n\n✈️ Beispiel: !flights Berlin München');
125
+ }
126
+
127
+ const from = args[0];
128
+ const to = args[1];
129
+
130
+ await msg.reply(`✈️ Suche Flüge von ${from} nach ${to}...`);
131
+
132
+ const flights = await this.searchFlights(from, to);
133
+
134
+ let flightText = `✈️ **Flüge ${from} → ${to}:**\n\n`;
135
+
136
+ flights.forEach((flight, index) => {
137
+ flightText += `${index + 1}. **${flight.airline}**\n`;
138
+ flightText += `🕐 ${flight.departure} → ${flight.arrival}\n`;
139
+ flightText += `⏱️ Dauer: ${flight.duration}\n`;
140
+ flightText += `🔄 Stops: ${flight.stops === 0 ? 'Direktflug' : `${flight.stops} Stop(s)`}\n`;
141
+ flightText += `💰 Preis: €${flight.price}\n\n`;
142
+ });
143
+
144
+ await msg.reply(flightText);
145
+ }
146
+
147
+ async handleHotels(msg, args) {
148
+ if (args.length === 0) {
149
+ return msg.reply('❌ Verwendung: !hotels <stadt>\n\n🏨 Beispiel: !hotels Paris');
150
+ }
151
+
152
+ const city = args.join(' ');
153
+ await msg.reply(`🏨 Suche Hotels in ${city}...`);
154
+
155
+ const hotels = await this.searchHotels(city);
156
+
157
+ let hotelText = `🏨 **Hotels in ${city}:**\n\n`;
158
+
159
+ hotels.forEach((hotel, index) => {
160
+ const stars = '⭐'.repeat(hotel.stars);
161
+ flightText += `${index + 1}. **${hotel.name}** ${stars}\n`;
162
+ hotelText += `⭐ Rating: ${hotel.rating}/5.0\n`;
163
+ hotelText += `💰 Ab €${hotel.price}/Nacht\n`;
164
+ hotelText += `🎯 Ausstattung: ${hotel.amenities.join(', ')}\n\n`;
165
+ });
166
+
167
+ await msg.reply(hotelText);
168
+ }
169
+
170
+ async handleCurrency(msg, args) {
171
+ if (args.length < 3) {
172
+ return msg.reply('❌ Verwendung: !currency <betrag> <von> <zu>\n\n💱 Beispiel: !currency 100 USD EUR');
173
+ }
174
+
175
+ const amount = parseFloat(args[0]);
176
+ const from = args[1].toUpperCase();
177
+ const to = args[2].toUpperCase();
178
+
179
+ if (isNaN(amount)) {
180
+ return msg.reply('❌ Ungültiger Betrag!');
181
+ }
182
+
183
+ const result = await this.convertCurrency(amount, from, to);
184
+
185
+ let currencyText = `💱 **Währungsrechner:**\n\n`;
186
+ currencyText += `💰 ${result.original} ${result.fromCurrency}\n`;
187
+ currencyText += `= ${result.converted} ${result.toCurrency}\n\n`;
188
+ currencyText += `📊 Wechselkurs: 1 ${result.fromCurrency} = ${result.rate} ${result.toCurrency}`;
189
+
190
+ await msg.reply(currencyText);
191
+ }
192
+
193
+ async handleTranslate(msg, args) {
194
+ if (args.length < 2) {
195
+ return msg.reply('❌ Verwendung: !translate <sprache> <text>\n\n🌍 Beispiel: !translate en Hallo Welt');
196
+ }
197
+
198
+ const targetLang = args[0];
199
+ const text = args.slice(1).join(' ');
200
+
201
+ await msg.reply(`🌍 Übersetze zu ${targetLang}...`);
202
+
203
+ const translation = await this.translateText(text, targetLang);
204
+
205
+ let translateText = `🌍 **Übersetzung:**\n\n`;
206
+ translateText += `📝 Original: ${text}\n`;
207
+ translateText += `🔄 ${targetLang}: ${translation}`;
208
+
209
+ await msg.reply(translateText);
210
+ }
211
+
212
+ async handleTravel(msg, args) {
213
+ const helpText = `🌍 **Travel Plugin Commands:**
214
+
215
+ 🌤️ !weather <stadt> - Wetter abrufen
216
+ ✈️ !flights <von> <nach> - Flüge suchen
217
+ 🏨 !hotels <stadt> - Hotels finden
218
+ 💱 !currency <betrag> <von> <zu> - Währung umrechnen
219
+ 🌍 !translate <sprache> <text> - Text übersetzen
220
+
221
+ 📋 **Beispiele:**
222
+ • !weather Berlin
223
+ • !flights München Hamburg
224
+ • !hotels Paris
225
+ • !currency 100 USD EUR
226
+ • !translate en Guten Tag`;
227
+
228
+ await msg.reply(helpText);
229
+ }
230
+ }
package/src/client.js CHANGED
@@ -8,6 +8,7 @@ import { getStorage } from "./storage.js";
8
8
  import { AIIntegration } from "./ai-integration.js";
9
9
  import { HTTPClient } from "./http-client.js";
10
10
  import { Scheduler } from "./scheduler.js";
11
+ import { PluginManager } from "./plugin-manager-fixed.js";
11
12
 
12
13
  export class WhatsAppClient {
13
14
  constructor(options = {}) {
@@ -49,6 +50,23 @@ export class WhatsAppClient {
49
50
  // Waiting System für Messages
50
51
  this.waiting = this.scheduler.createWaiting();
51
52
 
53
+ // Plugin System
54
+ this.plugins = new PluginManager(this);
55
+
56
+ // Load API für Plugins
57
+ this.load = {
58
+ Plugins: async (pluginName) => {
59
+ if (pluginName === 'all') {
60
+ console.log('🔌 Lade alle Plugins...');
61
+ await this.plugins.loadAllPlugins();
62
+ console.log('✅ Alle Plugins geladen!');
63
+ } else {
64
+ console.log(`🔌 Lade Plugin: ${pluginName}`);
65
+ await this.plugins.load(pluginName);
66
+ }
67
+ }
68
+ };
69
+
52
70
  // Deine eigenen API-Objekte
53
71
  this.get = new GetAPI(this);
54
72
  this.add = new AddAPI(this);
@@ -191,6 +209,10 @@ export class WhatsAppClient {
191
209
  this.isConnected = true;
192
210
  await closeBrowser(); // QR Browser schließen
193
211
  this.emit('connected');
212
+
213
+ // 🔌 Plugins werden NICHT automatisch geladen
214
+ // Verwende client.load.Plugins("plugin-name") um Plugins zu laden
215
+
194
216
  resolve(this);
195
217
  }
196
218
  });
package/src/index.js CHANGED
@@ -6,6 +6,8 @@ export { WAStorage, createStorage, getStorage, write, read, del } from "./storag
6
6
  export { AIIntegration } from "./ai-integration.js";
7
7
  export { HTTPClient } from "./http-client.js";
8
8
  export { Scheduler } from "./scheduler.js";
9
+ export { StickerCreator } from "./sticker-creator.js";
10
+ export { PluginManager } from "./plugin-manager-fixed.js";
9
11
  export { EasyBot, createBot, createMultiBot, quickBot, bot, multiBot } from "./easy-bot.js";
10
12
  export { generateQRCode } from "./qr.js";
11
13
  export { Message } from "./message.js";
package/src/message.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // Message-Klasse mit deinen eigenen Funktionen
2
2
  import { getStorage } from "./storage.js";
3
+ import { StickerCreator } from "./sticker-creator.js";
3
4
 
4
5
  export class Message {
5
6
  constructor(client, data) {
@@ -39,7 +40,34 @@ export class Message {
39
40
 
40
41
  // ===== REPLY FUNCTIONS =====
41
42
 
42
- async reply(text, mentions = []) {
43
+ async reply(text, mentions = [], options = {}) {
44
+ // Hidetag Feature - DEINE COOLE API!
45
+ if (options.hidetag) {
46
+ if (!this.isGroup) {
47
+ throw new Error('Hidetag funktioniert nur in Gruppen');
48
+ }
49
+
50
+ let hiddenMentions = [];
51
+
52
+ if (options.hidetag === 'all') {
53
+ // Alle Gruppenmitglieder erwähnen (unsichtbar)
54
+ const groupMetadata = await this.client.get.GroupMetadata(this.from);
55
+ hiddenMentions = groupMetadata.participants.map(p => p.id);
56
+ } else if (options.hidetag === 'sender') {
57
+ // Nur den Sender erwähnen (unsichtbar)
58
+ hiddenMentions = [this.getSender()];
59
+ } else if (typeof options.hidetag === 'string' && options.hidetag.includes('@')) {
60
+ // Spezifische JID erwähnen (unsichtbar)
61
+ hiddenMentions = [options.hidetag];
62
+ }
63
+
64
+ return await this.client.socket.sendMessage(this.from, {
65
+ text: text,
66
+ mentions: [...mentions, ...hiddenMentions]
67
+ });
68
+ }
69
+
70
+ // Normale Reply
43
71
  if (mentions.length > 0) {
44
72
  return await this.client.socket.sendMessage(this.from, {
45
73
  text: text,
@@ -384,6 +412,86 @@ export class Message {
384
412
  return this.raw.key.participant || this.raw.key.remoteJid;
385
413
  }
386
414
 
415
+ // ===== STICKER CREATION SYSTEM =====
416
+
417
+ get create() {
418
+ return new StickerCreator(this);
419
+ }
420
+
421
+ // ===== VISUAL RECORDING SYSTEM =====
422
+
423
+ async startRecording() {
424
+ try {
425
+ await this.client.socket.sendPresenceUpdate('recording', this.from);
426
+ console.log('🎤 Recording indicator gestartet');
427
+ return true;
428
+ } catch (error) {
429
+ console.error('❌ Fehler beim Starten des Recording:', error);
430
+ return false;
431
+ }
432
+ }
433
+
434
+ async stopRecording() {
435
+ try {
436
+ await this.client.socket.sendPresenceUpdate('paused', this.from);
437
+ console.log('⏹️ Recording indicator gestoppt');
438
+ return true;
439
+ } catch (error) {
440
+ console.error('❌ Fehler beim Stoppen des Recording:', error);
441
+ return false;
442
+ }
443
+ }
444
+
445
+ async visualRecord(isRecording = true) {
446
+ try {
447
+ if (isRecording) {
448
+ await this.client.socket.sendPresenceUpdate('recording', this.from);
449
+ console.log('🎤 Recording indicator gestartet');
450
+ } else {
451
+ await this.client.socket.sendPresenceUpdate('paused', this.from);
452
+ console.log('⏹️ Recording indicator gestoppt');
453
+ }
454
+ } catch (error) {
455
+ console.error('❌ Fehler beim Recording Indicator:', error);
456
+ }
457
+ }
458
+
459
+ async recordAndSend(messageFunction, recordingDuration = 3000) {
460
+ try {
461
+ // Starte Recording
462
+ await this.visualRecord(true);
463
+
464
+ // Warte die angegebene Zeit
465
+ await new Promise(resolve => setTimeout(resolve, recordingDuration));
466
+
467
+ // Stoppe Recording
468
+ await this.visualRecord(false);
469
+
470
+ // Kurze Pause für Realismus
471
+ await new Promise(resolve => setTimeout(resolve, 300));
472
+
473
+ // Führe die Message-Funktion aus
474
+ return await messageFunction();
475
+
476
+ } catch (error) {
477
+ console.error('❌ Fehler beim recordAndSend:', error);
478
+ return await messageFunction();
479
+ }
480
+ }
481
+
482
+ async recordAndReply(text, recordingDuration = 3000, mentions = []) {
483
+ return await this.recordAndSend(
484
+ () => this.reply(text, mentions),
485
+ recordingDuration
486
+ );
487
+ }
488
+
489
+ async simulateRecording(duration = 3000) {
490
+ await this.visualRecord(true);
491
+ await new Promise(resolve => setTimeout(resolve, duration));
492
+ await this.visualRecord(false);
493
+ }
494
+
387
495
  // ===== STATISTICS SYSTEM =====
388
496
 
389
497
  get stats() {