waengine 1.7.3 → 1.7.4
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 +29 -0
- package/README.md +34 -3
- package/package.json +3 -2
- package/src/ab-testing.js +698 -0
- package/src/advanced-scheduler.js +577 -0
- package/src/ai-features.js +459 -0
- package/src/ai-integration.js +2 -1
- package/src/analytics-manager.js +458 -0
- package/src/business-manager.js +362 -0
- package/src/client.js +447 -39
- package/src/console-logger.js +256 -0
- package/src/core.js +28 -3
- package/src/cross-platform.js +538 -0
- package/src/database-manager.js +766 -0
- package/src/device-manager.js +1 -1
- package/src/easy-bot-fixed.js +341 -0
- package/src/easy-bot.js +503 -22
- package/src/error-handler.js +230 -0
- package/src/gaming-manager.js +842 -0
- package/src/http-client.js +1 -1
- package/src/index.js +15 -0
- package/src/message.js +197 -94
- package/src/multi-client.js +26 -12
- package/src/plugin-manager.js +59 -10
- package/src/prefix-manager.js +48 -1
- package/src/qr-terminal-fix.js +239 -0
- package/src/qr.js +170 -27
- package/src/quick-bot.js +63 -0
- package/src/reporting-manager.js +867 -0
- package/src/scheduler.js +14 -1
- package/src/security-manager.js +678 -0
- package/src/session-manager-old.js +314 -0
- package/src/session-manager.js +429 -24
- package/src/storage.js +254 -194
- package/src/ui-components.js +560 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
import { getStorage } from "./storage.js";
|
|
2
|
+
|
|
3
|
+
export class AnalyticsManager {
|
|
4
|
+
constructor(client) {
|
|
5
|
+
this.client = client;
|
|
6
|
+
this.storage = getStorage();
|
|
7
|
+
this.metrics = new Map();
|
|
8
|
+
this.alerts = [];
|
|
9
|
+
this.monitoring = {
|
|
10
|
+
cpu: 0,
|
|
11
|
+
memory: 0,
|
|
12
|
+
responseTime: 0,
|
|
13
|
+
uptime: Date.now()
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Start monitoring
|
|
17
|
+
this.startMonitoring();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ===== MESSAGE ANALYTICS =====
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Track message event
|
|
24
|
+
*/
|
|
25
|
+
trackMessage(messageData) {
|
|
26
|
+
const timestamp = Date.now();
|
|
27
|
+
const date = new Date().toISOString().split('T')[0];
|
|
28
|
+
const hour = new Date().getHours();
|
|
29
|
+
|
|
30
|
+
// Daily stats
|
|
31
|
+
this.storage.write.in("analytics").increment(`daily.${date}.messages`, 1);
|
|
32
|
+
this.storage.write.in("analytics").increment(`hourly.${date}.${hour}`, 1);
|
|
33
|
+
|
|
34
|
+
// Message type stats
|
|
35
|
+
this.storage.write.in("analytics").increment(`messageTypes.${messageData.type}`, 1);
|
|
36
|
+
|
|
37
|
+
// User stats
|
|
38
|
+
if (messageData.from) {
|
|
39
|
+
this.storage.write.in("analytics").increment(`users.${messageData.from}.messages`, 1);
|
|
40
|
+
this.storage.write.in("analytics").set(`users.${messageData.from}.lastSeen`, timestamp);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Group stats
|
|
44
|
+
if (messageData.isGroup) {
|
|
45
|
+
this.storage.write.in("analytics").increment(`groups.${messageData.chatId}.messages`, 1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Geographic data (if available)
|
|
49
|
+
if (messageData.location) {
|
|
50
|
+
this.storage.write.in("analytics").increment(`geographic.${messageData.location.country}`, 1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Track command usage
|
|
56
|
+
*/
|
|
57
|
+
trackCommand(command, userId, success = true) {
|
|
58
|
+
const date = new Date().toISOString().split('T')[0];
|
|
59
|
+
|
|
60
|
+
this.storage.write.in("analytics").increment(`commands.${command}.total`, 1);
|
|
61
|
+
this.storage.write.in("analytics").increment(`commands.${command}.daily.${date}`, 1);
|
|
62
|
+
|
|
63
|
+
if (success) {
|
|
64
|
+
this.storage.write.in("analytics").increment(`commands.${command}.success`, 1);
|
|
65
|
+
} else {
|
|
66
|
+
this.storage.write.in("analytics").increment(`commands.${command}.errors`, 1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// User command stats
|
|
70
|
+
this.storage.write.in("analytics").increment(`users.${userId}.commands.${command}`, 1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Track response time
|
|
75
|
+
*/
|
|
76
|
+
trackResponseTime(duration) {
|
|
77
|
+
const date = new Date().toISOString().split('T')[0];
|
|
78
|
+
|
|
79
|
+
// Store response times for averaging
|
|
80
|
+
const responseTimes = this.storage.read.from("analytics").get(`responseTimes.${date}`) || [];
|
|
81
|
+
responseTimes.push(duration);
|
|
82
|
+
|
|
83
|
+
// Keep only last 1000 response times per day
|
|
84
|
+
if (responseTimes.length > 1000) {
|
|
85
|
+
responseTimes.shift();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.storage.write.in("analytics").set(`responseTimes.${date}`, responseTimes);
|
|
89
|
+
|
|
90
|
+
// Update current monitoring
|
|
91
|
+
this.monitoring.responseTime = duration;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ===== USER ANALYTICS =====
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get user engagement metrics
|
|
98
|
+
*/
|
|
99
|
+
getUserEngagement(userId) {
|
|
100
|
+
const userData = this.storage.read.from("analytics").get(`users.${userId}`) || {};
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
totalMessages: userData.messages || 0,
|
|
104
|
+
lastSeen: userData.lastSeen ? new Date(userData.lastSeen) : null,
|
|
105
|
+
commands: userData.commands || {},
|
|
106
|
+
isActive: userData.lastSeen && (Date.now() - userData.lastSeen) < 24 * 60 * 60 * 1000,
|
|
107
|
+
engagementScore: this.calculateEngagementScore(userData)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Calculate user engagement score
|
|
113
|
+
*/
|
|
114
|
+
calculateEngagementScore(userData) {
|
|
115
|
+
const messages = userData.messages || 0;
|
|
116
|
+
const commands = Object.values(userData.commands || {}).reduce((sum, count) => sum + count, 0);
|
|
117
|
+
const lastSeen = userData.lastSeen || 0;
|
|
118
|
+
const daysSinceLastSeen = (Date.now() - lastSeen) / (24 * 60 * 60 * 1000);
|
|
119
|
+
|
|
120
|
+
let score = 0;
|
|
121
|
+
|
|
122
|
+
// Message activity (0-40 points)
|
|
123
|
+
score += Math.min(messages * 0.1, 40);
|
|
124
|
+
|
|
125
|
+
// Command usage (0-30 points)
|
|
126
|
+
score += Math.min(commands * 0.5, 30);
|
|
127
|
+
|
|
128
|
+
// Recency (0-30 points)
|
|
129
|
+
if (daysSinceLastSeen < 1) score += 30;
|
|
130
|
+
else if (daysSinceLastSeen < 7) score += 20;
|
|
131
|
+
else if (daysSinceLastSeen < 30) score += 10;
|
|
132
|
+
|
|
133
|
+
return Math.round(score);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get most active users
|
|
138
|
+
*/
|
|
139
|
+
getMostActiveUsers(limit = 10) {
|
|
140
|
+
const users = this.storage.read.from("analytics").get("users") || {};
|
|
141
|
+
|
|
142
|
+
return Object.entries(users)
|
|
143
|
+
.map(([userId, data]) => ({
|
|
144
|
+
userId,
|
|
145
|
+
messages: data.messages || 0,
|
|
146
|
+
commands: Object.values(data.commands || {}).reduce((sum, count) => sum + count, 0),
|
|
147
|
+
lastSeen: data.lastSeen ? new Date(data.lastSeen) : null,
|
|
148
|
+
engagementScore: this.calculateEngagementScore(data)
|
|
149
|
+
}))
|
|
150
|
+
.sort((a, b) => b.engagementScore - a.engagementScore)
|
|
151
|
+
.slice(0, limit);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ===== PERFORMANCE MONITORING =====
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Start system monitoring
|
|
158
|
+
*/
|
|
159
|
+
startMonitoring() {
|
|
160
|
+
setInterval(() => {
|
|
161
|
+
this.updateSystemMetrics();
|
|
162
|
+
this.checkAlerts();
|
|
163
|
+
}, 30000); // Every 30 seconds
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Update system metrics
|
|
168
|
+
*/
|
|
169
|
+
updateSystemMetrics() {
|
|
170
|
+
const memUsage = process.memoryUsage();
|
|
171
|
+
|
|
172
|
+
this.monitoring = {
|
|
173
|
+
cpu: process.cpuUsage(),
|
|
174
|
+
memory: {
|
|
175
|
+
used: memUsage.heapUsed,
|
|
176
|
+
total: memUsage.heapTotal,
|
|
177
|
+
percentage: (memUsage.heapUsed / memUsage.heapTotal) * 100
|
|
178
|
+
},
|
|
179
|
+
uptime: Date.now() - this.monitoring.uptime,
|
|
180
|
+
timestamp: Date.now()
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Store metrics
|
|
184
|
+
const date = new Date().toISOString().split('T')[0];
|
|
185
|
+
const hour = new Date().getHours();
|
|
186
|
+
|
|
187
|
+
this.storage.write.in("analytics").set(`performance.${date}.${hour}`, {
|
|
188
|
+
memory: this.monitoring.memory.percentage,
|
|
189
|
+
responseTime: this.monitoring.responseTime,
|
|
190
|
+
timestamp: Date.now()
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check for performance alerts
|
|
196
|
+
*/
|
|
197
|
+
checkAlerts() {
|
|
198
|
+
const alerts = [];
|
|
199
|
+
|
|
200
|
+
// Memory usage alert
|
|
201
|
+
if (this.monitoring.memory.percentage > 80) {
|
|
202
|
+
alerts.push({
|
|
203
|
+
type: 'memory',
|
|
204
|
+
level: 'warning',
|
|
205
|
+
message: `High memory usage: ${this.monitoring.memory.percentage.toFixed(1)}%`,
|
|
206
|
+
timestamp: Date.now()
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Response time alert
|
|
211
|
+
if (this.monitoring.responseTime > 5000) {
|
|
212
|
+
alerts.push({
|
|
213
|
+
type: 'response_time',
|
|
214
|
+
level: 'warning',
|
|
215
|
+
message: `Slow response time: ${this.monitoring.responseTime}ms`,
|
|
216
|
+
timestamp: Date.now()
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Store alerts
|
|
221
|
+
if (alerts.length > 0) {
|
|
222
|
+
this.alerts.push(...alerts);
|
|
223
|
+
this.storage.write.in("analytics").push("alerts", alerts);
|
|
224
|
+
|
|
225
|
+
// Emit alert events
|
|
226
|
+
alerts.forEach(alert => {
|
|
227
|
+
this.client.emit('performance_alert', alert);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ===== DETAILED STATISTICS =====
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get comprehensive analytics report
|
|
236
|
+
*/
|
|
237
|
+
getDetailedStats(days = 7) {
|
|
238
|
+
const endDate = new Date();
|
|
239
|
+
const startDate = new Date(endDate.getTime() - (days * 24 * 60 * 60 * 1000));
|
|
240
|
+
|
|
241
|
+
const stats = {
|
|
242
|
+
overview: this.getOverviewStats(),
|
|
243
|
+
messages: this.getMessageStats(days),
|
|
244
|
+
users: this.getUserStats(days),
|
|
245
|
+
commands: this.getCommandStats(days),
|
|
246
|
+
performance: this.getPerformanceStats(days),
|
|
247
|
+
geographic: this.getGeographicStats(),
|
|
248
|
+
timeDistribution: this.getTimeDistribution(days)
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
return stats;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Get overview statistics
|
|
256
|
+
*/
|
|
257
|
+
getOverviewStats() {
|
|
258
|
+
const users = this.storage.read.from("analytics").get("users") || {};
|
|
259
|
+
const messageTypes = this.storage.read.from("analytics").get("messageTypes") || {};
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
totalUsers: Object.keys(users).length,
|
|
263
|
+
activeUsers: Object.values(users).filter(user =>
|
|
264
|
+
user.lastSeen && (Date.now() - user.lastSeen) < 24 * 60 * 60 * 1000
|
|
265
|
+
).length,
|
|
266
|
+
totalMessages: Object.values(messageTypes).reduce((sum, count) => sum + count, 0),
|
|
267
|
+
uptime: Date.now() - this.monitoring.uptime,
|
|
268
|
+
currentMemoryUsage: this.monitoring.memory.percentage,
|
|
269
|
+
averageResponseTime: this.monitoring.responseTime
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Get message statistics
|
|
275
|
+
*/
|
|
276
|
+
getMessageStats(days) {
|
|
277
|
+
const messageTypes = this.storage.read.from("analytics").get("messageTypes") || {};
|
|
278
|
+
const dailyStats = [];
|
|
279
|
+
|
|
280
|
+
for (let i = 0; i < days; i++) {
|
|
281
|
+
const date = new Date(Date.now() - (i * 24 * 60 * 60 * 1000))
|
|
282
|
+
.toISOString().split('T')[0];
|
|
283
|
+
const dayMessages = this.storage.read.from("analytics").get(`daily.${date}.messages`) || 0;
|
|
284
|
+
|
|
285
|
+
dailyStats.push({
|
|
286
|
+
date,
|
|
287
|
+
messages: dayMessages
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
byType: messageTypes,
|
|
293
|
+
daily: dailyStats.reverse(),
|
|
294
|
+
totalMessages: Object.values(messageTypes).reduce((sum, count) => sum + count, 0)
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Get user statistics
|
|
300
|
+
*/
|
|
301
|
+
getUserStats(days) {
|
|
302
|
+
const users = this.storage.read.from("analytics").get("users") || {};
|
|
303
|
+
const activeUsers = Object.values(users).filter(user =>
|
|
304
|
+
user.lastSeen && (Date.now() - user.lastSeen) < days * 24 * 60 * 60 * 1000
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
total: Object.keys(users).length,
|
|
309
|
+
active: activeUsers.length,
|
|
310
|
+
newUsers: this.getNewUsersCount(days),
|
|
311
|
+
topUsers: this.getMostActiveUsers(10),
|
|
312
|
+
engagementDistribution: this.getEngagementDistribution()
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Get command statistics
|
|
318
|
+
*/
|
|
319
|
+
getCommandStats(days) {
|
|
320
|
+
const commands = this.storage.read.from("analytics").get("commands") || {};
|
|
321
|
+
|
|
322
|
+
return Object.entries(commands).map(([command, data]) => ({
|
|
323
|
+
command,
|
|
324
|
+
total: data.total || 0,
|
|
325
|
+
success: data.success || 0,
|
|
326
|
+
errors: data.errors || 0,
|
|
327
|
+
successRate: data.total ? ((data.success || 0) / data.total * 100).toFixed(1) : 0
|
|
328
|
+
})).sort((a, b) => b.total - a.total);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Get performance statistics
|
|
333
|
+
*/
|
|
334
|
+
getPerformanceStats(days) {
|
|
335
|
+
const performanceData = [];
|
|
336
|
+
|
|
337
|
+
for (let i = 0; i < days; i++) {
|
|
338
|
+
const date = new Date(Date.now() - (i * 24 * 60 * 60 * 1000))
|
|
339
|
+
.toISOString().split('T')[0];
|
|
340
|
+
|
|
341
|
+
for (let hour = 0; hour < 24; hour++) {
|
|
342
|
+
const hourData = this.storage.read.from("analytics").get(`performance.${date}.${hour}`);
|
|
343
|
+
if (hourData) {
|
|
344
|
+
performanceData.push({
|
|
345
|
+
date,
|
|
346
|
+
hour,
|
|
347
|
+
memory: hourData.memory,
|
|
348
|
+
responseTime: hourData.responseTime
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
data: performanceData.reverse(),
|
|
356
|
+
alerts: this.alerts.slice(-50), // Last 50 alerts
|
|
357
|
+
averageMemory: performanceData.reduce((sum, d) => sum + d.memory, 0) / performanceData.length || 0,
|
|
358
|
+
averageResponseTime: performanceData.reduce((sum, d) => sum + d.responseTime, 0) / performanceData.length || 0
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Get geographic distribution
|
|
364
|
+
*/
|
|
365
|
+
getGeographicStats() {
|
|
366
|
+
return this.storage.read.from("analytics").get("geographic") || {};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Get time distribution
|
|
371
|
+
*/
|
|
372
|
+
getTimeDistribution(days) {
|
|
373
|
+
const hourlyData = {};
|
|
374
|
+
|
|
375
|
+
for (let i = 0; i < days; i++) {
|
|
376
|
+
const date = new Date(Date.now() - (i * 24 * 60 * 60 * 1000))
|
|
377
|
+
.toISOString().split('T')[0];
|
|
378
|
+
|
|
379
|
+
for (let hour = 0; hour < 24; hour++) {
|
|
380
|
+
const messages = this.storage.read.from("analytics").get(`hourly.${date}.${hour}`) || 0;
|
|
381
|
+
hourlyData[hour] = (hourlyData[hour] || 0) + messages;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return hourlyData;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ===== HELPER METHODS =====
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get new users count
|
|
392
|
+
*/
|
|
393
|
+
getNewUsersCount(days) {
|
|
394
|
+
const cutoff = Date.now() - (days * 24 * 60 * 60 * 1000);
|
|
395
|
+
const users = this.storage.read.from("analytics").get("users") || {};
|
|
396
|
+
|
|
397
|
+
return Object.values(users).filter(user =>
|
|
398
|
+
user.firstSeen && user.firstSeen > cutoff
|
|
399
|
+
).length;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Get engagement distribution
|
|
404
|
+
*/
|
|
405
|
+
getEngagementDistribution() {
|
|
406
|
+
const users = this.storage.read.from("analytics").get("users") || {};
|
|
407
|
+
const distribution = { low: 0, medium: 0, high: 0 };
|
|
408
|
+
|
|
409
|
+
Object.values(users).forEach(userData => {
|
|
410
|
+
const score = this.calculateEngagementScore(userData);
|
|
411
|
+
if (score < 30) distribution.low++;
|
|
412
|
+
else if (score < 70) distribution.medium++;
|
|
413
|
+
else distribution.high++;
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
return distribution;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Export analytics data
|
|
421
|
+
*/
|
|
422
|
+
exportAnalytics(format = 'json') {
|
|
423
|
+
const data = this.getDetailedStats(30); // 30 days
|
|
424
|
+
|
|
425
|
+
if (format === 'csv') {
|
|
426
|
+
return this.convertToCSV(data);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return data;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Convert data to CSV format
|
|
434
|
+
*/
|
|
435
|
+
convertToCSV(data) {
|
|
436
|
+
// Simplified CSV conversion
|
|
437
|
+
const csv = [];
|
|
438
|
+
|
|
439
|
+
// Daily messages CSV
|
|
440
|
+
csv.push('Date,Messages');
|
|
441
|
+
data.messages.daily.forEach(day => {
|
|
442
|
+
csv.push(`${day.date},${day.messages}`);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
return csv.join('\n');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Reset analytics data
|
|
450
|
+
*/
|
|
451
|
+
resetAnalytics() {
|
|
452
|
+
this.storage.delete.from("analytics").all();
|
|
453
|
+
this.metrics.clear();
|
|
454
|
+
this.alerts = [];
|
|
455
|
+
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
}
|