waengine 2.3.8 → 2.3.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/README.md +1 -1
- package/package.json +1 -1
- package/src/advanced-features.js +49 -21
- package/src/console-renderer.js +282 -0
- package/src/http-advanced.js +299 -0
- package/src/index.js +3 -0
- package/src/message.js +94 -0
- package/src/ui-components.js +60 -10
package/README.md
CHANGED
|
@@ -100,7 +100,7 @@ client.on('truly_connected', (data) => {
|
|
|
100
100
|
- **Button Messages** - Interactive buttons with callbacks
|
|
101
101
|
- **List Messages** - Organized lists with sections
|
|
102
102
|
- **Template Messages** - Reusable message templates
|
|
103
|
-
- **Carousel Messages** - Swipeable card carousels
|
|
103
|
+
- **Carousel Messages** - Swipeable card carousels with VIDEO support! 🎬
|
|
104
104
|
|
|
105
105
|
### 👥 **Advanced Group Features**
|
|
106
106
|
- **Group Settings** - Control who can send messages
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "waengine",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.9",
|
|
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/advanced-features.js
CHANGED
|
@@ -237,30 +237,58 @@ export class AdvancedMessage {
|
|
|
237
237
|
|
|
238
238
|
async sendCarouselMessage(cards) {
|
|
239
239
|
try {
|
|
240
|
-
// WhatsApp Carousel
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
240
|
+
// WhatsApp Carousel mit Video & Image Support
|
|
241
|
+
const results = [];
|
|
242
|
+
|
|
243
|
+
for (let i = 0; i < cards.length; i++) {
|
|
244
|
+
const card = cards[i];
|
|
245
|
+
|
|
246
|
+
// Build card text
|
|
247
|
+
let cardText = `🎴 **${i + 1}/${cards.length}: ${card.title}**\n`;
|
|
248
|
+
if (card.subtitle) cardText += `${card.subtitle}\n\n`;
|
|
249
|
+
if (card.body) cardText += `${card.body}`;
|
|
250
|
+
if (card.footer) cardText += `\n\n_${card.footer}_`;
|
|
251
|
+
|
|
252
|
+
// Add buttons as text
|
|
253
|
+
if (card.buttons && card.buttons.length > 0) {
|
|
254
|
+
cardText += `\n\n**Options:**\n`;
|
|
255
|
+
card.buttons.forEach((btn, btnIndex) => {
|
|
256
|
+
cardText += `${btnIndex + 1}. ${btn.text || btn.title}\n`;
|
|
257
|
+
});
|
|
257
258
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
259
|
+
|
|
260
|
+
// Send with appropriate media type
|
|
261
|
+
let result;
|
|
262
|
+
if (card.video) {
|
|
263
|
+
// Video card
|
|
264
|
+
result = await this.socket.sendMessage(this.msg.from, {
|
|
265
|
+
video: { url: card.video },
|
|
266
|
+
caption: cardText,
|
|
267
|
+
gifPlayback: card.gifPlayback || false
|
|
268
|
+
});
|
|
269
|
+
} else if (card.image) {
|
|
270
|
+
// Image card
|
|
271
|
+
result = await this.socket.sendMessage(this.msg.from, {
|
|
272
|
+
image: { url: card.image },
|
|
273
|
+
caption: cardText
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
// Text-only card
|
|
277
|
+
result = await this.msg.reply(cardText);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
results.push(result);
|
|
281
|
+
|
|
282
|
+
// Small delay between cards
|
|
283
|
+
if (i < cards.length - 1) {
|
|
284
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return results;
|
|
261
289
|
} catch (error) {
|
|
262
290
|
console.error('❌ Carousel Message fehlgeschlagen:', error);
|
|
263
|
-
// Fallback: Sende Cards
|
|
291
|
+
// Fallback: Sende Cards als Text
|
|
264
292
|
const results = [];
|
|
265
293
|
for (const card of cards) {
|
|
266
294
|
try {
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// ===== CONSOLE RENDERER - Schöne Console Outputs mit Prefix & Farben =====
|
|
2
|
+
|
|
3
|
+
// ANSI Color Codes
|
|
4
|
+
const colors = {
|
|
5
|
+
// Basic Colors
|
|
6
|
+
black: '\x1b[30m',
|
|
7
|
+
red: '\x1b[31m',
|
|
8
|
+
green: '\x1b[32m',
|
|
9
|
+
yellow: '\x1b[33m',
|
|
10
|
+
blue: '\x1b[34m',
|
|
11
|
+
magenta: '\x1b[35m',
|
|
12
|
+
cyan: '\x1b[36m',
|
|
13
|
+
white: '\x1b[37m',
|
|
14
|
+
|
|
15
|
+
// Bright Colors
|
|
16
|
+
brightBlack: '\x1b[90m',
|
|
17
|
+
brightRed: '\x1b[91m',
|
|
18
|
+
brightGreen: '\x1b[92m',
|
|
19
|
+
brightYellow: '\x1b[93m',
|
|
20
|
+
brightBlue: '\x1b[94m',
|
|
21
|
+
brightMagenta: '\x1b[95m',
|
|
22
|
+
brightCyan: '\x1b[96m',
|
|
23
|
+
brightWhite: '\x1b[97m',
|
|
24
|
+
|
|
25
|
+
// Background Colors
|
|
26
|
+
bgBlack: '\x1b[40m',
|
|
27
|
+
bgRed: '\x1b[41m',
|
|
28
|
+
bgGreen: '\x1b[42m',
|
|
29
|
+
bgYellow: '\x1b[43m',
|
|
30
|
+
bgBlue: '\x1b[44m',
|
|
31
|
+
bgMagenta: '\x1b[45m',
|
|
32
|
+
bgCyan: '\x1b[46m',
|
|
33
|
+
bgWhite: '\x1b[47m',
|
|
34
|
+
|
|
35
|
+
// Styles
|
|
36
|
+
bold: '\x1b[1m',
|
|
37
|
+
dim: '\x1b[2m',
|
|
38
|
+
italic: '\x1b[3m',
|
|
39
|
+
underline: '\x1b[4m',
|
|
40
|
+
blink: '\x1b[5m',
|
|
41
|
+
reverse: '\x1b[7m',
|
|
42
|
+
hidden: '\x1b[8m',
|
|
43
|
+
|
|
44
|
+
// Reset
|
|
45
|
+
reset: '\x1b[0m'
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Global Config
|
|
49
|
+
let globalConfig = {
|
|
50
|
+
prefix: null,
|
|
51
|
+
prefixColor: 'cyan',
|
|
52
|
+
defaultColor: 'white',
|
|
53
|
+
errorColor: 'red',
|
|
54
|
+
warnColor: 'yellow',
|
|
55
|
+
infoColor: 'blue',
|
|
56
|
+
successColor: 'green',
|
|
57
|
+
enabled: true
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Original console methods
|
|
61
|
+
const originalConsole = {
|
|
62
|
+
log: console.log,
|
|
63
|
+
error: console.error,
|
|
64
|
+
warn: console.warn,
|
|
65
|
+
info: console.info
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Helper: Get color code
|
|
69
|
+
function getColor(colorName) {
|
|
70
|
+
return colors[colorName] || colors.white;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Helper: Format prefix
|
|
74
|
+
function formatPrefix(prefix, color) {
|
|
75
|
+
if (!prefix) return '';
|
|
76
|
+
const colorCode = getColor(color);
|
|
77
|
+
return `${colorCode}[${prefix}]${colors.reset} `;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Helper: Apply color to text
|
|
81
|
+
function colorize(text, color) {
|
|
82
|
+
const colorCode = getColor(color);
|
|
83
|
+
return `${colorCode}${text}${colors.reset}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Patch console.log
|
|
87
|
+
console.log = function(...args) {
|
|
88
|
+
if (!globalConfig.enabled) {
|
|
89
|
+
return originalConsole.log(...args);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const prefix = formatPrefix(globalConfig.prefix, globalConfig.prefixColor);
|
|
93
|
+
const colorCode = getColor(globalConfig.defaultColor);
|
|
94
|
+
|
|
95
|
+
if (prefix) {
|
|
96
|
+
originalConsole.log(prefix + colorCode, ...args, colors.reset);
|
|
97
|
+
} else {
|
|
98
|
+
originalConsole.log(colorCode, ...args, colors.reset);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Patch console.error
|
|
103
|
+
console.error = function(...args) {
|
|
104
|
+
if (!globalConfig.enabled) {
|
|
105
|
+
return originalConsole.error(...args);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const prefix = formatPrefix(globalConfig.prefix, globalConfig.prefixColor);
|
|
109
|
+
const colorCode = getColor(globalConfig.errorColor);
|
|
110
|
+
|
|
111
|
+
if (prefix) {
|
|
112
|
+
originalConsole.error(prefix + colorCode, ...args, colors.reset);
|
|
113
|
+
} else {
|
|
114
|
+
originalConsole.error(colorCode, ...args, colors.reset);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Patch console.warn
|
|
119
|
+
console.warn = function(...args) {
|
|
120
|
+
if (!globalConfig.enabled) {
|
|
121
|
+
return originalConsole.warn(...args);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const prefix = formatPrefix(globalConfig.prefix, globalConfig.prefixColor);
|
|
125
|
+
const colorCode = getColor(globalConfig.warnColor);
|
|
126
|
+
|
|
127
|
+
if (prefix) {
|
|
128
|
+
originalConsole.warn(prefix + colorCode, ...args, colors.reset);
|
|
129
|
+
} else {
|
|
130
|
+
originalConsole.warn(colorCode, ...args, colors.reset);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Patch console.info
|
|
135
|
+
console.info = function(...args) {
|
|
136
|
+
if (!globalConfig.enabled) {
|
|
137
|
+
return originalConsole.info(...args);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const prefix = formatPrefix(globalConfig.prefix, globalConfig.prefixColor);
|
|
141
|
+
const colorCode = getColor(globalConfig.infoColor);
|
|
142
|
+
|
|
143
|
+
if (prefix) {
|
|
144
|
+
originalConsole.info(prefix + colorCode, ...args, colors.reset);
|
|
145
|
+
} else {
|
|
146
|
+
originalConsole.info(colorCode, ...args, colors.reset);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// ===== PUBLIC API =====
|
|
151
|
+
|
|
152
|
+
export const render = {
|
|
153
|
+
// Set prefix name
|
|
154
|
+
consolePrefix(name) {
|
|
155
|
+
globalConfig.prefix = name;
|
|
156
|
+
console.log(`✅ Console Prefix gesetzt: [${name}]`);
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// Set prefix color
|
|
160
|
+
consolePrefixColor(color) {
|
|
161
|
+
if (!colors[color]) {
|
|
162
|
+
console.warn(`⚠️ Unbekannte Farbe: ${color}`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
globalConfig.prefixColor = color;
|
|
166
|
+
console.log(`🎨 Prefix Farbe gesetzt: ${color}`);
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
// Set default console.log color
|
|
170
|
+
consoleColor(color) {
|
|
171
|
+
if (!colors[color]) {
|
|
172
|
+
console.warn(`⚠️ Unbekannte Farbe: ${color}`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
globalConfig.defaultColor = color;
|
|
176
|
+
console.log(`🎨 Console Farbe gesetzt: ${color}`);
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
// Set console.error color
|
|
180
|
+
consoleError(color) {
|
|
181
|
+
if (!colors[color]) {
|
|
182
|
+
console.warn(`⚠️ Unbekannte Farbe: ${color}`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
globalConfig.errorColor = color;
|
|
186
|
+
console.log(`🎨 Error Farbe gesetzt: ${color}`);
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
// Set console.warn color
|
|
190
|
+
consoleWarn(color) {
|
|
191
|
+
if (!colors[color]) {
|
|
192
|
+
console.warn(`⚠️ Unbekannte Farbe: ${color}`);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
globalConfig.warnColor = color;
|
|
196
|
+
console.log(`🎨 Warn Farbe gesetzt: ${color}`);
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
// Set console.info color
|
|
200
|
+
consoleInfo(color) {
|
|
201
|
+
if (!colors[color]) {
|
|
202
|
+
console.warn(`⚠️ Unbekannte Farbe: ${color}`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
globalConfig.infoColor = color;
|
|
206
|
+
console.log(`🎨 Info Farbe gesetzt: ${color}`);
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
// Enable/Disable rendering
|
|
210
|
+
enable() {
|
|
211
|
+
globalConfig.enabled = true;
|
|
212
|
+
console.log('✅ Console Rendering aktiviert');
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
disable() {
|
|
216
|
+
globalConfig.enabled = false;
|
|
217
|
+
originalConsole.log('⚠️ Console Rendering deaktiviert');
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
// Reset to defaults
|
|
221
|
+
reset() {
|
|
222
|
+
globalConfig = {
|
|
223
|
+
prefix: null,
|
|
224
|
+
prefixColor: 'cyan',
|
|
225
|
+
defaultColor: 'white',
|
|
226
|
+
errorColor: 'red',
|
|
227
|
+
warnColor: 'yellow',
|
|
228
|
+
infoColor: 'blue',
|
|
229
|
+
successColor: 'green',
|
|
230
|
+
enabled: true
|
|
231
|
+
};
|
|
232
|
+
console.log('🔄 Console Rendering zurückgesetzt');
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
// Get current config
|
|
236
|
+
getConfig() {
|
|
237
|
+
return { ...globalConfig };
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
// Custom colored output
|
|
241
|
+
print(text, color = 'white') {
|
|
242
|
+
const prefix = formatPrefix(globalConfig.prefix, globalConfig.prefixColor);
|
|
243
|
+
const colored = colorize(text, color);
|
|
244
|
+
originalConsole.log(prefix + colored);
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
// Success message
|
|
248
|
+
success(text) {
|
|
249
|
+
const prefix = formatPrefix(globalConfig.prefix, globalConfig.prefixColor);
|
|
250
|
+
const colored = colorize(text, globalConfig.successColor);
|
|
251
|
+
originalConsole.log(prefix + colored);
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
// Available colors
|
|
255
|
+
colors: Object.keys(colors).filter(c => c !== 'reset'),
|
|
256
|
+
|
|
257
|
+
// Show color palette
|
|
258
|
+
showColors() {
|
|
259
|
+
originalConsole.log('\n🎨 Verfügbare Farben:\n');
|
|
260
|
+
|
|
261
|
+
const colorList = Object.keys(colors).filter(c => c !== 'reset');
|
|
262
|
+
|
|
263
|
+
colorList.forEach(colorName => {
|
|
264
|
+
const sample = `${colors[colorName]}${colorName}${colors.reset}`;
|
|
265
|
+
originalConsole.log(` ${sample}`);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
originalConsole.log('');
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// Export colors for direct use
|
|
273
|
+
export { colors };
|
|
274
|
+
|
|
275
|
+
// Auto-initialize message
|
|
276
|
+
if (globalConfig.enabled) {
|
|
277
|
+
originalConsole.log(
|
|
278
|
+
`${colors.brightCyan}╔════════════════════════════════════════╗${colors.reset}\n` +
|
|
279
|
+
`${colors.brightCyan}║ 🎨 Console Renderer aktiviert! ║${colors.reset}\n` +
|
|
280
|
+
`${colors.brightCyan}╚════════════════════════════════════════╝${colors.reset}`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
// ===== ADVANCED HTTP CLIENT - Axios-Style für WAEngine =====
|
|
2
|
+
// Wie curl, aber besser! 🚀
|
|
3
|
+
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
|
|
6
|
+
export class HTTP {
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
this.config = {
|
|
9
|
+
timeout: config.timeout || 30000,
|
|
10
|
+
retries: config.retries || 3,
|
|
11
|
+
headers: config.headers || {},
|
|
12
|
+
baseURL: config.baseURL || '',
|
|
13
|
+
...config
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Axios Instance
|
|
17
|
+
this.client = axios.create(this.config);
|
|
18
|
+
|
|
19
|
+
// Request/Response Interceptors
|
|
20
|
+
this.setupInterceptors();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setupInterceptors() {
|
|
24
|
+
// Request Interceptor
|
|
25
|
+
this.client.interceptors.request.use(
|
|
26
|
+
(config) => {
|
|
27
|
+
console.log(`🌐 ${config.method.toUpperCase()} ${config.url}`);
|
|
28
|
+
return config;
|
|
29
|
+
},
|
|
30
|
+
(error) => Promise.reject(error)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Response Interceptor
|
|
34
|
+
this.client.interceptors.response.use(
|
|
35
|
+
(response) => {
|
|
36
|
+
console.log(`✅ ${response.status} ${response.config.url}`);
|
|
37
|
+
return response;
|
|
38
|
+
},
|
|
39
|
+
(error) => {
|
|
40
|
+
console.error(`❌ ${error.response?.status || 'ERROR'} ${error.config?.url}`);
|
|
41
|
+
return Promise.reject(error);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ===== BASIC METHODS (Axios-Style) =====
|
|
47
|
+
|
|
48
|
+
async get(url, config = {}) {
|
|
49
|
+
try {
|
|
50
|
+
const response = await this.client.get(url, config);
|
|
51
|
+
return response.data;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
throw this.handleError(error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async post(url, data = {}, config = {}) {
|
|
58
|
+
try {
|
|
59
|
+
const response = await this.client.post(url, data, config);
|
|
60
|
+
return response.data;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw this.handleError(error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async put(url, data = {}, config = {}) {
|
|
67
|
+
try {
|
|
68
|
+
const response = await this.client.put(url, data, config);
|
|
69
|
+
return response.data;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
throw this.handleError(error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async patch(url, data = {}, config = {}) {
|
|
76
|
+
try {
|
|
77
|
+
const response = await this.client.patch(url, data, config);
|
|
78
|
+
return response.data;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw this.handleError(error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async delete(url, config = {}) {
|
|
85
|
+
try {
|
|
86
|
+
const response = await this.client.delete(url, config);
|
|
87
|
+
return response.data;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
throw this.handleError(error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async head(url, config = {}) {
|
|
94
|
+
try {
|
|
95
|
+
const response = await this.client.head(url, config);
|
|
96
|
+
return response.headers;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
throw this.handleError(error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async options(url, config = {}) {
|
|
103
|
+
try {
|
|
104
|
+
const response = await this.client.options(url, config);
|
|
105
|
+
return response.data;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
throw this.handleError(error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ===== CURL-STYLE REQUEST =====
|
|
112
|
+
|
|
113
|
+
async curl(options) {
|
|
114
|
+
/*
|
|
115
|
+
Curl-Style Request:
|
|
116
|
+
|
|
117
|
+
await http.curl({
|
|
118
|
+
url: 'https://api.example.com/data',
|
|
119
|
+
method: 'POST',
|
|
120
|
+
headers: { 'Authorization': 'Bearer token' },
|
|
121
|
+
data: { key: 'value' },
|
|
122
|
+
params: { page: 1 },
|
|
123
|
+
timeout: 5000
|
|
124
|
+
});
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const response = await this.client(options);
|
|
129
|
+
return response.data;
|
|
130
|
+
} catch (error) {
|
|
131
|
+
throw this.handleError(error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ===== ADVANCED FEATURES =====
|
|
136
|
+
|
|
137
|
+
// Download File
|
|
138
|
+
async download(url, savePath) {
|
|
139
|
+
try {
|
|
140
|
+
const response = await this.client.get(url, {
|
|
141
|
+
responseType: 'arraybuffer'
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const fs = await import('fs');
|
|
145
|
+
await fs.promises.writeFile(savePath, response.data);
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
path: savePath,
|
|
150
|
+
size: response.data.length,
|
|
151
|
+
contentType: response.headers['content-type']
|
|
152
|
+
};
|
|
153
|
+
} catch (error) {
|
|
154
|
+
throw this.handleError(error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Upload File
|
|
159
|
+
async upload(url, filePath, fieldName = 'file') {
|
|
160
|
+
try {
|
|
161
|
+
const fs = await import('fs');
|
|
162
|
+
const FormData = (await import('form-data')).default;
|
|
163
|
+
|
|
164
|
+
const form = new FormData();
|
|
165
|
+
form.append(fieldName, fs.createReadStream(filePath));
|
|
166
|
+
|
|
167
|
+
const response = await this.client.post(url, form, {
|
|
168
|
+
headers: form.getHeaders()
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return response.data;
|
|
172
|
+
} catch (error) {
|
|
173
|
+
throw this.handleError(error);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// JSON Request
|
|
178
|
+
async json(url, data = null, method = 'GET') {
|
|
179
|
+
const config = {
|
|
180
|
+
headers: {
|
|
181
|
+
'Content-Type': 'application/json',
|
|
182
|
+
'Accept': 'application/json'
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
if (method === 'GET') {
|
|
187
|
+
return await this.get(url, config);
|
|
188
|
+
} else {
|
|
189
|
+
return await this.post(url, data, config);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Form Data Request
|
|
194
|
+
async form(url, data = {}) {
|
|
195
|
+
const FormData = (await import('form-data')).default;
|
|
196
|
+
const form = new FormData();
|
|
197
|
+
|
|
198
|
+
for (const [key, value] of Object.entries(data)) {
|
|
199
|
+
form.append(key, value);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return await this.post(url, form, {
|
|
203
|
+
headers: form.getHeaders()
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Parallel Requests
|
|
208
|
+
async all(requests) {
|
|
209
|
+
try {
|
|
210
|
+
const promises = requests.map(req => {
|
|
211
|
+
if (typeof req === 'string') {
|
|
212
|
+
return this.get(req);
|
|
213
|
+
} else {
|
|
214
|
+
return this.curl(req);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
return await Promise.all(promises);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
throw this.handleError(error);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Retry Request
|
|
225
|
+
async retry(fn, retries = 3, delay = 1000) {
|
|
226
|
+
for (let i = 0; i < retries; i++) {
|
|
227
|
+
try {
|
|
228
|
+
return await fn();
|
|
229
|
+
} catch (error) {
|
|
230
|
+
if (i === retries - 1) throw error;
|
|
231
|
+
console.log(`🔄 Retry ${i + 1}/${retries}...`);
|
|
232
|
+
await this.sleep(delay * (i + 1));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Stream Response
|
|
238
|
+
async stream(url, onData, onEnd) {
|
|
239
|
+
try {
|
|
240
|
+
const response = await this.client.get(url, {
|
|
241
|
+
responseType: 'stream'
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
response.data.on('data', onData);
|
|
245
|
+
response.data.on('end', onEnd);
|
|
246
|
+
|
|
247
|
+
return response.data;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
throw this.handleError(error);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ===== HELPER METHODS =====
|
|
254
|
+
|
|
255
|
+
handleError(error) {
|
|
256
|
+
if (error.response) {
|
|
257
|
+
// Server responded with error
|
|
258
|
+
return new Error(`HTTP ${error.response.status}: ${error.response.statusText}`);
|
|
259
|
+
} else if (error.request) {
|
|
260
|
+
// No response received
|
|
261
|
+
return new Error('No response from server');
|
|
262
|
+
} else {
|
|
263
|
+
// Request setup error
|
|
264
|
+
return new Error(error.message);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
sleep(ms) {
|
|
269
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Set Default Headers
|
|
273
|
+
setHeader(key, value) {
|
|
274
|
+
this.client.defaults.headers.common[key] = value;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Set Authorization
|
|
278
|
+
setAuth(token, type = 'Bearer') {
|
|
279
|
+
this.setHeader('Authorization', `${type} ${token}`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Set Base URL
|
|
283
|
+
setBaseURL(url) {
|
|
284
|
+
this.client.defaults.baseURL = url;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ===== GLOBAL HTTP INSTANCE =====
|
|
289
|
+
export const http = new HTTP();
|
|
290
|
+
|
|
291
|
+
// ===== QUICK METHODS =====
|
|
292
|
+
export const get = (url, config) => http.get(url, config);
|
|
293
|
+
export const post = (url, data, config) => http.post(url, data, config);
|
|
294
|
+
export const put = (url, data, config) => http.put(url, data, config);
|
|
295
|
+
export const patch = (url, data, config) => http.patch(url, data, config);
|
|
296
|
+
export const del = (url, config) => http.delete(url, config);
|
|
297
|
+
export const curl = (options) => http.curl(options);
|
|
298
|
+
export const download = (url, path) => http.download(url, path);
|
|
299
|
+
export const upload = (url, file, field) => http.upload(url, file, field);
|
package/src/index.js
CHANGED
|
@@ -15,6 +15,9 @@ export { Message } from "./message.js";
|
|
|
15
15
|
export { ConsoleLogger, logger } from "./console-logger.js";
|
|
16
16
|
export { ErrorHandler, defaultErrorHandler } from "./error-handler.js";
|
|
17
17
|
|
|
18
|
+
// ===== CONSOLE RENDERER - NEU! =====
|
|
19
|
+
export { render, colors } from "./console-renderer.js";
|
|
20
|
+
|
|
18
21
|
// ===== ULTRA-ROBUSTE RECOVERY SYSTEME - NEU v2.0.0! =====
|
|
19
22
|
export { ConnectionRecovery } from "./connection-recovery.js";
|
|
20
23
|
export { AuthRecovery } from "./auth-recovery.js";
|
package/src/message.js
CHANGED
|
@@ -727,6 +727,100 @@ export class Message {
|
|
|
727
727
|
}
|
|
728
728
|
}
|
|
729
729
|
|
|
730
|
+
// ===== MESSAGE DEL - Lösche beliebige Message (Admin erforderlich in Gruppen) =====
|
|
731
|
+
async MessageDel(messageId, participantJid = null) {
|
|
732
|
+
try {
|
|
733
|
+
// Wenn keine Parameter, lösche die aktuelle Message
|
|
734
|
+
if (!messageId) {
|
|
735
|
+
return await this.deleteMessage();
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Prüfe in Gruppen ob Bot Admin ist
|
|
739
|
+
if (this.isGroup) {
|
|
740
|
+
const isBotAdmin = await this.isGroupAdmin(this.client.socket.user.id);
|
|
741
|
+
if (!isBotAdmin) {
|
|
742
|
+
console.log('⚠️ Bot ist kein Admin - kann nur eigene Messages löschen');
|
|
743
|
+
return {
|
|
744
|
+
success: false,
|
|
745
|
+
reason: 'not_admin',
|
|
746
|
+
error: 'Bot muss Admin sein um Messages von anderen zu löschen'
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Bot JID ermitteln
|
|
752
|
+
const botJid = this.client.socket.user?.id;
|
|
753
|
+
const botNumber = botJid?.split('@')[0]?.split(':')[0];
|
|
754
|
+
|
|
755
|
+
// Prüfe ob Message vom Bot ist
|
|
756
|
+
let isFromBot = false;
|
|
757
|
+
if (participantJid) {
|
|
758
|
+
const participantNumber = participantJid?.split('@')[0]?.split(':')[0];
|
|
759
|
+
isFromBot = botNumber === participantNumber;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// Erstelle Message Key
|
|
763
|
+
const messageKey = {
|
|
764
|
+
remoteJid: this.from,
|
|
765
|
+
id: messageId,
|
|
766
|
+
fromMe: isFromBot
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
// In Gruppen: participant hinzufügen wenn nicht vom Bot
|
|
770
|
+
if (this.isGroup && participantJid && !isFromBot) {
|
|
771
|
+
messageKey.participant = participantJid;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
console.log('🗑️ MessageDel - Lösche Message:', {
|
|
775
|
+
messageId: messageId,
|
|
776
|
+
participant: participantJid,
|
|
777
|
+
isFromBot: isFromBot,
|
|
778
|
+
isGroup: this.isGroup,
|
|
779
|
+
key: messageKey
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
// Sende Delete Request
|
|
783
|
+
const result = await this.client.socket.sendMessage(this.from, {
|
|
784
|
+
delete: messageKey
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
console.log('✅ MessageDel erfolgreich:', result);
|
|
788
|
+
return {
|
|
789
|
+
success: true,
|
|
790
|
+
messageId: messageId,
|
|
791
|
+
participant: participantJid,
|
|
792
|
+
wasFromBot: isFromBot,
|
|
793
|
+
result: result
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
} catch (error) {
|
|
797
|
+
console.error('❌ MessageDel Fehler:', error.message);
|
|
798
|
+
|
|
799
|
+
// Spezifische Fehlerbehandlung
|
|
800
|
+
if (error.message?.includes('not-found') || error.message?.includes('404')) {
|
|
801
|
+
return {
|
|
802
|
+
success: false,
|
|
803
|
+
reason: 'message_not_found',
|
|
804
|
+
error: 'Message nicht gefunden oder zu alt'
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (error.message?.includes('forbidden') || error.message?.includes('403')) {
|
|
809
|
+
return {
|
|
810
|
+
success: false,
|
|
811
|
+
reason: 'no_permission',
|
|
812
|
+
error: 'Keine Berechtigung - Bot muss Admin sein'
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
return {
|
|
817
|
+
success: false,
|
|
818
|
+
reason: 'unknown_error',
|
|
819
|
+
error: error.message
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
730
824
|
// ===== MEDIA DOWNLOAD - NEU in v1.7.9! =====
|
|
731
825
|
|
|
732
826
|
async downloadMedia(options = {}) {
|
package/src/ui-components.js
CHANGED
|
@@ -7,10 +7,11 @@ export class UIComponents {
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Send carousel message with multiple cards
|
|
10
|
+
* Supports: images, videos, and text-only cards
|
|
10
11
|
*/
|
|
11
12
|
async sendCarousel(chatId, cards, options = {}) {
|
|
12
13
|
try {
|
|
13
|
-
// WhatsApp doesn't support native carousels, so we create a rich
|
|
14
|
+
// WhatsApp doesn't support native carousels, so we create a rich media alternative
|
|
14
15
|
let carouselText = `🎠 **${options.title || 'Carousel'}**\n\n`;
|
|
15
16
|
|
|
16
17
|
cards.forEach((card, index) => {
|
|
@@ -35,19 +36,68 @@ export class UIComponents {
|
|
|
35
36
|
carouselText += `\n_${options.footer}_`;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
// Send with image
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
// Send each card with its media (image or video)
|
|
40
|
+
for (let i = 0; i < cards.length; i++) {
|
|
41
|
+
const card = cards[i];
|
|
42
|
+
|
|
43
|
+
// Build card text
|
|
44
|
+
let cardText = `**${i + 1}/${cards.length}: ${card.title}**\n`;
|
|
45
|
+
if (card.subtitle) cardText += `${card.subtitle}\n`;
|
|
46
|
+
if (card.body) cardText += `${card.body}\n`;
|
|
47
|
+
if (card.price) cardText += `💰 ${card.price}\n`;
|
|
48
|
+
|
|
49
|
+
if (card.buttons && card.buttons.length > 0) {
|
|
50
|
+
cardText += `\nOptions: `;
|
|
51
|
+
card.buttons.forEach((btn, btnIndex) => {
|
|
52
|
+
cardText += `[${btnIndex + 1}] ${btn.title} `;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (options.footer) {
|
|
57
|
+
cardText += `\n\n_${options.footer}_`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Send with appropriate media type
|
|
61
|
+
if (card.video) {
|
|
62
|
+
// Video card
|
|
63
|
+
await this.client.socket.sendMessage(chatId, {
|
|
64
|
+
video: { url: card.video },
|
|
65
|
+
caption: cardText,
|
|
66
|
+
gifPlayback: card.gifPlayback || false
|
|
67
|
+
});
|
|
68
|
+
} else if (card.image) {
|
|
69
|
+
// Image card
|
|
70
|
+
await this.client.socket.sendMessage(chatId, {
|
|
71
|
+
image: { url: card.image },
|
|
72
|
+
caption: cardText
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
// Text-only card
|
|
76
|
+
await this.client.socket.sendMessage(chatId, {
|
|
77
|
+
text: cardText
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Small delay between cards to prevent spam
|
|
82
|
+
if (i < cards.length - 1) {
|
|
83
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
84
|
+
}
|
|
46
85
|
}
|
|
47
86
|
|
|
48
|
-
return {
|
|
87
|
+
return {
|
|
88
|
+
success: true,
|
|
89
|
+
type: 'carousel',
|
|
90
|
+
cards: cards.length,
|
|
91
|
+
mediaTypes: {
|
|
92
|
+
videos: cards.filter(c => c.video).length,
|
|
93
|
+
images: cards.filter(c => c.image).length,
|
|
94
|
+
text: cards.filter(c => !c.video && !c.image).length
|
|
95
|
+
}
|
|
96
|
+
};
|
|
49
97
|
|
|
50
98
|
} catch (error) {
|
|
99
|
+
console.error('❌ Carousel error:', error);
|
|
100
|
+
|
|
51
101
|
// Fallback to simple text
|
|
52
102
|
const fallbackText = `📋 **${options.title || 'Options'}**\n\n` +
|
|
53
103
|
cards.map((card, i) => `${i + 1}. ${card.title}`).join('\n');
|