waengine 1.0.7 → 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.
- package/CHANGELOG.md +89 -0
- package/FEATURES.md +2354 -0
- package/PLUGIN-SYSTEM.md +271 -0
- package/package.json +14 -3
- package/plugins/analytics-plugin/config.json +91 -0
- package/plugins/analytics-plugin/index.js +461 -0
- package/plugins/creative-plugin/config.json +87 -0
- package/plugins/creative-plugin/index.js +320 -0
- package/plugins/economy-system/config.json +48 -0
- package/plugins/economy-system/index.js +237 -0
- package/plugins/education-plugin/index.js +275 -0
- package/plugins/games-plugin/config.json +35 -0
- package/plugins/games-plugin/index.js +300 -0
- package/plugins/moderation-plugin/config.json +86 -0
- package/plugins/moderation-plugin/index.js +458 -0
- package/plugins/music-plugin/config.json +32 -0
- package/plugins/music-plugin/index.js +221 -0
- package/plugins/travel-plugin/index.js +230 -0
- package/src/ai-integration.js +185 -0
- package/src/client.js +41 -0
- package/src/http-client.js +276 -0
- package/src/index.js +6 -0
- package/src/message.js +127 -1
- package/src/plugin-manager-fixed.js +116 -0
- package/src/plugin-manager.js +105 -0
- package/src/scheduler.js +322 -0
- package/src/sticker-creator.js +413 -0
- package/src/storage.js +422 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
// HTTP Client für WAEngine
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
|
|
4
|
+
export class HTTPClient {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.timeout = options.timeout || 10000;
|
|
7
|
+
this.retries = options.retries || 3;
|
|
8
|
+
this.baseHeaders = options.headers || {};
|
|
9
|
+
|
|
10
|
+
// Axios Instance erstellen
|
|
11
|
+
this.axios = axios.create({
|
|
12
|
+
timeout: this.timeout,
|
|
13
|
+
headers: this.baseHeaders
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
console.log('🌐 HTTP Client initialisiert');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ===== BASIC HTTP METHODS =====
|
|
20
|
+
|
|
21
|
+
async get(url, options = {}) {
|
|
22
|
+
return await this.request('GET', url, null, options);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async post(url, data = null, options = {}) {
|
|
26
|
+
return await this.request('POST', url, data, options);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async put(url, data = null, options = {}) {
|
|
30
|
+
return await this.request('PUT', url, data, options);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async delete(url, options = {}) {
|
|
34
|
+
return await this.request('DELETE', url, null, options);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ===== CORE REQUEST METHOD =====
|
|
38
|
+
|
|
39
|
+
async request(method, url, data = null, options = {}) {
|
|
40
|
+
let lastError;
|
|
41
|
+
|
|
42
|
+
for (let attempt = 1; attempt <= this.retries; attempt++) {
|
|
43
|
+
try {
|
|
44
|
+
const config = {
|
|
45
|
+
method,
|
|
46
|
+
url,
|
|
47
|
+
...options
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (data) {
|
|
51
|
+
config.data = data;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const response = await this.axios(config);
|
|
55
|
+
return response.data;
|
|
56
|
+
|
|
57
|
+
} catch (error) {
|
|
58
|
+
lastError = error;
|
|
59
|
+
|
|
60
|
+
if (attempt < this.retries && this.shouldRetry(error)) {
|
|
61
|
+
console.log(`🔄 HTTP Retry ${attempt}/${this.retries} für ${url}`);
|
|
62
|
+
await this.delay(1000 * attempt); // Exponential backoff
|
|
63
|
+
} else {
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
throw new Error(`HTTP Request failed: ${lastError.message}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
shouldRetry(error) {
|
|
73
|
+
// Retry bei Netzwerk-Fehlern oder 5xx Status Codes
|
|
74
|
+
return !error.response || error.response.status >= 500;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
delay(ms) {
|
|
78
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ===== API WRAPPERS =====
|
|
82
|
+
|
|
83
|
+
// Weather API
|
|
84
|
+
async getWeather(city, apiKey = process.env.WEATHER_API_KEY) {
|
|
85
|
+
if (!apiKey) {
|
|
86
|
+
throw new Error('❌ Weather API Key fehlt! Setze WEATHER_API_KEY');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const data = await this.get(`https://api.openweathermap.org/data/2.5/weather`, {
|
|
91
|
+
params: {
|
|
92
|
+
q: city,
|
|
93
|
+
appid: apiKey,
|
|
94
|
+
units: 'metric',
|
|
95
|
+
lang: 'de'
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
city: data.name,
|
|
101
|
+
country: data.sys.country,
|
|
102
|
+
temperature: Math.round(data.main.temp),
|
|
103
|
+
description: data.weather[0].description,
|
|
104
|
+
humidity: data.main.humidity,
|
|
105
|
+
windSpeed: data.wind.speed,
|
|
106
|
+
icon: data.weather[0].icon
|
|
107
|
+
};
|
|
108
|
+
} catch (error) {
|
|
109
|
+
throw new Error(`Wetter-Fehler: ${error.message}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// News API
|
|
114
|
+
async getNews(category = 'general', apiKey = process.env.NEWS_API_KEY) {
|
|
115
|
+
if (!apiKey) {
|
|
116
|
+
throw new Error('❌ News API Key fehlt! Setze NEWS_API_KEY');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const data = await this.get(`https://newsapi.org/v2/top-headlines`, {
|
|
121
|
+
params: {
|
|
122
|
+
country: 'de',
|
|
123
|
+
category: category,
|
|
124
|
+
apiKey: apiKey,
|
|
125
|
+
pageSize: 5
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return data.articles.map(article => ({
|
|
130
|
+
title: article.title,
|
|
131
|
+
description: article.description,
|
|
132
|
+
url: article.url,
|
|
133
|
+
source: article.source.name,
|
|
134
|
+
publishedAt: new Date(article.publishedAt).toLocaleDateString('de-DE')
|
|
135
|
+
}));
|
|
136
|
+
} catch (error) {
|
|
137
|
+
throw new Error(`News-Fehler: ${error.message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Crypto Prices
|
|
142
|
+
async getCryptoPrice(symbol = 'bitcoin') {
|
|
143
|
+
try {
|
|
144
|
+
const data = await this.get(`https://api.coingecko.com/api/v3/simple/price`, {
|
|
145
|
+
params: {
|
|
146
|
+
ids: symbol,
|
|
147
|
+
vs_currencies: 'eur,usd',
|
|
148
|
+
include_24hr_change: true
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const coin = data[symbol];
|
|
153
|
+
return {
|
|
154
|
+
symbol: symbol,
|
|
155
|
+
priceEUR: coin.eur,
|
|
156
|
+
priceUSD: coin.usd,
|
|
157
|
+
change24h: coin.eur_24h_change?.toFixed(2) || 0
|
|
158
|
+
};
|
|
159
|
+
} catch (error) {
|
|
160
|
+
throw new Error(`Crypto-Fehler: ${error.message}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// QR Code Generator
|
|
165
|
+
async generateQRCode(text, size = 200) {
|
|
166
|
+
try {
|
|
167
|
+
const url = `https://api.qrserver.com/v1/create-qr-code/?size=${size}x${size}&data=${encodeURIComponent(text)}`;
|
|
168
|
+
|
|
169
|
+
// Return URL instead of downloading
|
|
170
|
+
return {
|
|
171
|
+
url: url,
|
|
172
|
+
text: text,
|
|
173
|
+
size: size
|
|
174
|
+
};
|
|
175
|
+
} catch (error) {
|
|
176
|
+
throw new Error(`QR-Code-Fehler: ${error.message}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// URL Shortener
|
|
181
|
+
async shortenUrl(longUrl, apiKey = process.env.BITLY_API_KEY) {
|
|
182
|
+
if (!apiKey) {
|
|
183
|
+
// Fallback zu kostenlosem Service
|
|
184
|
+
try {
|
|
185
|
+
const data = await this.post('https://is.gd/create.php', null, {
|
|
186
|
+
params: {
|
|
187
|
+
format: 'json',
|
|
188
|
+
url: longUrl
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
shortUrl: data.shorturl,
|
|
194
|
+
longUrl: longUrl,
|
|
195
|
+
service: 'is.gd'
|
|
196
|
+
};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
throw new Error(`URL-Shortener-Fehler: ${error.message}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Bitly API
|
|
203
|
+
try {
|
|
204
|
+
const data = await this.post('https://api-ssl.bitly.com/v4/shorten', {
|
|
205
|
+
long_url: longUrl
|
|
206
|
+
}, {
|
|
207
|
+
headers: {
|
|
208
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
209
|
+
'Content-Type': 'application/json'
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
shortUrl: data.link,
|
|
215
|
+
longUrl: longUrl,
|
|
216
|
+
service: 'bitly'
|
|
217
|
+
};
|
|
218
|
+
} catch (error) {
|
|
219
|
+
throw new Error(`Bitly-Fehler: ${error.message}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Random Facts
|
|
224
|
+
async getRandomFact() {
|
|
225
|
+
try {
|
|
226
|
+
const data = await this.get('https://uselessfacts.jsph.pl/random.json?language=en');
|
|
227
|
+
return data.text;
|
|
228
|
+
} catch (error) {
|
|
229
|
+
throw new Error(`Random-Fact-Fehler: ${error.message}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Random Joke
|
|
234
|
+
async getRandomJoke() {
|
|
235
|
+
try {
|
|
236
|
+
const data = await this.get('https://official-joke-api.appspot.com/random_joke');
|
|
237
|
+
return `${data.setup}\n\n${data.punchline}`;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
throw new Error(`Joke-Fehler: ${error.message}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// IP Info
|
|
244
|
+
async getIPInfo(ip = '') {
|
|
245
|
+
try {
|
|
246
|
+
const url = ip ? `http://ip-api.com/json/${ip}` : 'http://ip-api.com/json/';
|
|
247
|
+
const data = await this.get(url);
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
ip: data.query,
|
|
251
|
+
country: data.country,
|
|
252
|
+
city: data.city,
|
|
253
|
+
region: data.regionName,
|
|
254
|
+
timezone: data.timezone,
|
|
255
|
+
isp: data.isp
|
|
256
|
+
};
|
|
257
|
+
} catch (error) {
|
|
258
|
+
throw new Error(`IP-Info-Fehler: ${error.message}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Website Screenshot (via API)
|
|
263
|
+
async getWebsiteScreenshot(url, width = 1280, height = 720) {
|
|
264
|
+
try {
|
|
265
|
+
const screenshotUrl = `https://api.screenshotmachine.com/?key=${process.env.SCREENSHOT_API_KEY}&url=${encodeURIComponent(url)}&dimension=${width}x${height}`;
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
screenshotUrl: screenshotUrl,
|
|
269
|
+
originalUrl: url,
|
|
270
|
+
dimensions: `${width}x${height}`
|
|
271
|
+
};
|
|
272
|
+
} catch (error) {
|
|
273
|
+
throw new Error(`Screenshot-Fehler: ${error.message}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
package/src/index.js
CHANGED
|
@@ -2,6 +2,12 @@ export { WhatsAppClient } from "./client.js";
|
|
|
2
2
|
export { MultiWhatsAppClient } from "./multi-client.js";
|
|
3
3
|
export { DeviceManager } from "./device-manager.js";
|
|
4
4
|
export { PrefixManager } from "./prefix-manager.js";
|
|
5
|
+
export { WAStorage, createStorage, getStorage, write, read, del } from "./storage.js";
|
|
6
|
+
export { AIIntegration } from "./ai-integration.js";
|
|
7
|
+
export { HTTPClient } from "./http-client.js";
|
|
8
|
+
export { Scheduler } from "./scheduler.js";
|
|
9
|
+
export { StickerCreator } from "./sticker-creator.js";
|
|
10
|
+
export { PluginManager } from "./plugin-manager-fixed.js";
|
|
5
11
|
export { EasyBot, createBot, createMultiBot, quickBot, bot, multiBot } from "./easy-bot.js";
|
|
6
12
|
export { generateQRCode } from "./qr.js";
|
|
7
13
|
export { Message } from "./message.js";
|
package/src/message.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// Message-Klasse mit deinen eigenen Funktionen
|
|
2
|
+
import { getStorage } from "./storage.js";
|
|
3
|
+
import { StickerCreator } from "./sticker-creator.js";
|
|
2
4
|
|
|
3
5
|
export class Message {
|
|
4
6
|
constructor(client, data) {
|
|
@@ -17,11 +19,55 @@ export class Message {
|
|
|
17
19
|
this.command = null;
|
|
18
20
|
this.args = [];
|
|
19
21
|
this.commandText = null;
|
|
22
|
+
|
|
23
|
+
// Storage System
|
|
24
|
+
this.storage = getStorage();
|
|
25
|
+
this.write = this.storage.write;
|
|
26
|
+
this.read = this.storage.read;
|
|
27
|
+
this.delete = this.storage.delete;
|
|
28
|
+
|
|
29
|
+
// Waiting System - DEINE COOLE API!
|
|
30
|
+
this.waiting = {
|
|
31
|
+
after: {
|
|
32
|
+
message: (ms) => {
|
|
33
|
+
return new Promise(resolve => {
|
|
34
|
+
setTimeout(resolve, ms);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
20
39
|
}
|
|
21
40
|
|
|
22
41
|
// ===== REPLY FUNCTIONS =====
|
|
23
42
|
|
|
24
|
-
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
|
|
25
71
|
if (mentions.length > 0) {
|
|
26
72
|
return await this.client.socket.sendMessage(this.from, {
|
|
27
73
|
text: text,
|
|
@@ -366,6 +412,86 @@ export class Message {
|
|
|
366
412
|
return this.raw.key.participant || this.raw.key.remoteJid;
|
|
367
413
|
}
|
|
368
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
|
+
|
|
369
495
|
// ===== STATISTICS SYSTEM =====
|
|
370
496
|
|
|
371
497
|
get stats() {
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// 🔌 WAEngine Plugin Manager - Auto-Plugin System
|
|
2
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { pathToFileURL } from 'url';
|
|
5
|
+
|
|
6
|
+
export class PluginManager {
|
|
7
|
+
constructor(client) {
|
|
8
|
+
this.client = client;
|
|
9
|
+
this.plugins = new Map();
|
|
10
|
+
this.pluginsDir = './plugins';
|
|
11
|
+
this.availablePlugins = [
|
|
12
|
+
'economy-system',
|
|
13
|
+
'games-plugin',
|
|
14
|
+
'music-plugin',
|
|
15
|
+
'travel-plugin',
|
|
16
|
+
'education-plugin',
|
|
17
|
+
'moderation-plugin',
|
|
18
|
+
'creative-plugin',
|
|
19
|
+
'analytics-plugin'
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
this.ensurePluginsDirectory();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ensurePluginsDirectory() {
|
|
26
|
+
if (!existsSync(this.pluginsDir)) {
|
|
27
|
+
mkdirSync(this.pluginsDir, { recursive: true });
|
|
28
|
+
console.log('📁 Plugins Ordner erstellt');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async load(pluginName) {
|
|
33
|
+
try {
|
|
34
|
+
console.log(`🔌 Lade Plugin: ${pluginName}`);
|
|
35
|
+
|
|
36
|
+
// Plugin importieren mit korrekter Windows file:// URL
|
|
37
|
+
const pluginPath = join(process.cwd(), this.pluginsDir, pluginName, 'index.js');
|
|
38
|
+
|
|
39
|
+
if (!existsSync(pluginPath)) {
|
|
40
|
+
console.log(`📝 Plugin ${pluginName} nicht gefunden - wird übersprungen`);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Windows-kompatible file:// URL erstellen
|
|
45
|
+
const pluginUrl = pathToFileURL(pluginPath).href;
|
|
46
|
+
console.log(`📂 Plugin Pfad: ${pluginUrl}`);
|
|
47
|
+
|
|
48
|
+
const { default: PluginClass } = await import(pluginUrl);
|
|
49
|
+
|
|
50
|
+
// Plugin instanziieren
|
|
51
|
+
const plugin = new PluginClass(this.client);
|
|
52
|
+
this.plugins.set(pluginName, plugin);
|
|
53
|
+
|
|
54
|
+
// Commands registrieren
|
|
55
|
+
await this.registerPluginCommands(plugin);
|
|
56
|
+
|
|
57
|
+
console.log(`✅ Plugin geladen: ${pluginName} v${plugin.version}`);
|
|
58
|
+
return plugin;
|
|
59
|
+
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(`❌ Plugin Fehler: ${pluginName}`, error.message);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async loadAllPlugins() {
|
|
67
|
+
console.log('🚀 Lade alle verfügbaren Plugins...');
|
|
68
|
+
|
|
69
|
+
for (const pluginName of this.availablePlugins) {
|
|
70
|
+
await this.load(pluginName);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.log(`✅ ${this.plugins.size} Plugins geladen`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async registerPluginCommands(plugin) {
|
|
77
|
+
const commands = plugin.getCommands();
|
|
78
|
+
|
|
79
|
+
Object.entries(commands).forEach(([commandName, handler]) => {
|
|
80
|
+
this.client.addCommand(commandName, async (msg, args) => {
|
|
81
|
+
try {
|
|
82
|
+
// Plugin-Context zu Message hinzufügen
|
|
83
|
+
msg.plugin = this.getPluginContext();
|
|
84
|
+
await handler(msg, args);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error(`❌ Plugin Command Fehler: ${commandName}`, error);
|
|
87
|
+
await msg.reply(`❌ Plugin Fehler: ${error.message}`);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getPluginContext() {
|
|
94
|
+
const context = {};
|
|
95
|
+
this.plugins.forEach((plugin, name) => {
|
|
96
|
+
context[name.replace('-', '_')] = plugin;
|
|
97
|
+
});
|
|
98
|
+
return context;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get(pluginName) {
|
|
102
|
+
return this.plugins.get(pluginName);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
list() {
|
|
106
|
+
return Array.from(this.plugins.keys());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
getStats() {
|
|
110
|
+
return {
|
|
111
|
+
loaded: this.plugins.size,
|
|
112
|
+
available: this.availablePlugins.length,
|
|
113
|
+
plugins: this.list()
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// 🔌 WAEngine Plugin Manager - Auto-Plugin System
|
|
2
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
export class PluginManager {
|
|
6
|
+
constructor(client) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
this.plugins = new Map();
|
|
9
|
+
this.pluginsDir = './plugins';
|
|
10
|
+
this.availablePlugins = [
|
|
11
|
+
'economy-system',
|
|
12
|
+
'games-plugin'
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
this.ensurePluginsDirectory();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
ensurePluginsDirectory() {
|
|
19
|
+
if (!existsSync(this.pluginsDir)) {
|
|
20
|
+
mkdirSync(this.pluginsDir, { recursive: true });
|
|
21
|
+
console.log('📁 Plugins Ordner erstellt');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async load(pluginName) {
|
|
26
|
+
try {
|
|
27
|
+
console.log(`🔌 Lade Plugin: ${pluginName}`);
|
|
28
|
+
|
|
29
|
+
// Plugin importieren
|
|
30
|
+
const pluginPath = join(process.cwd(), this.pluginsDir, pluginName, 'index.js');
|
|
31
|
+
|
|
32
|
+
if (!existsSync(pluginPath)) {
|
|
33
|
+
console.log(`📝 Plugin ${pluginName} nicht gefunden - wird übersprungen`);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { default: PluginClass } = await import(pluginPath);
|
|
38
|
+
|
|
39
|
+
// Plugin instanziieren
|
|
40
|
+
const plugin = new PluginClass(this.client);
|
|
41
|
+
this.plugins.set(pluginName, plugin);
|
|
42
|
+
|
|
43
|
+
// Commands registrieren
|
|
44
|
+
await this.registerPluginCommands(plugin);
|
|
45
|
+
|
|
46
|
+
console.log(`✅ Plugin geladen: ${pluginName} v${plugin.version}`);
|
|
47
|
+
return plugin;
|
|
48
|
+
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(`❌ Plugin Fehler: ${pluginName}`, error.message);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async loadAllPlugins() {
|
|
56
|
+
console.log('🚀 Lade alle verfügbaren Plugins...');
|
|
57
|
+
|
|
58
|
+
for (const pluginName of this.availablePlugins) {
|
|
59
|
+
await this.load(pluginName);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log(`✅ ${this.plugins.size} Plugins geladen`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async registerPluginCommands(plugin) {
|
|
66
|
+
const commands = plugin.getCommands();
|
|
67
|
+
|
|
68
|
+
Object.entries(commands).forEach(([commandName, handler]) => {
|
|
69
|
+
this.client.addCommand(commandName, async (msg, args) => {
|
|
70
|
+
try {
|
|
71
|
+
// Plugin-Context zu Message hinzufügen
|
|
72
|
+
msg.plugin = this.getPluginContext();
|
|
73
|
+
await handler(msg, args);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(`❌ Plugin Command Fehler: ${commandName}`, error);
|
|
76
|
+
await msg.reply(`❌ Plugin Fehler: ${error.message}`);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getPluginContext() {
|
|
83
|
+
const context = {};
|
|
84
|
+
this.plugins.forEach((plugin, name) => {
|
|
85
|
+
context[name.replace('-', '_')] = plugin;
|
|
86
|
+
});
|
|
87
|
+
return context;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get(pluginName) {
|
|
91
|
+
return this.plugins.get(pluginName);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
list() {
|
|
95
|
+
return Array.from(this.plugins.keys());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
getStats() {
|
|
99
|
+
return {
|
|
100
|
+
loaded: this.plugins.size,
|
|
101
|
+
available: this.availablePlugins.length,
|
|
102
|
+
plugins: this.list()
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|