waengine 1.0.8 → 1.0.10

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,461 @@
1
+ // 📊 Analytics Plugin
2
+ export default class AnalyticsPlugin {
3
+ constructor(client) {
4
+ this.client = client;
5
+ this.name = 'analytics-plugin';
6
+ this.version = '1.0.0';
7
+ this.description = 'Detaillierte Statistiken und Analytics für Gruppen und User';
8
+
9
+ this.initTracking();
10
+ }
11
+
12
+ initTracking() {
13
+ // Tracking bei jeder Nachricht
14
+ this.client.on('message', async (msg) => {
15
+ if (msg.fromMe) return;
16
+
17
+ await this.trackMessage(msg);
18
+ });
19
+ }
20
+
21
+ async trackMessage(msg) {
22
+ const userId = msg.getSender();
23
+ const groupId = msg.isGroup ? msg.from : 'private';
24
+ const timestamp = Date.now();
25
+ const hour = new Date().getHours();
26
+ const day = new Date().getDay(); // 0 = Sonntag
27
+ const messageLength = msg.text ? msg.text.length : 0;
28
+
29
+ // User-Statistiken
30
+ this.client.storage.write.in('analytics').increment(`users.${userId}.totalMessages`, 1);
31
+ this.client.storage.write.in('analytics').increment(`users.${userId}.totalChars`, messageLength);
32
+ this.client.storage.write.in('analytics').set(`users.${userId}.lastSeen`, timestamp);
33
+ this.client.storage.write.in('analytics').increment(`users.${userId}.hourly.${hour}`, 1);
34
+ this.client.storage.write.in('analytics').increment(`users.${userId}.daily.${day}`, 1);
35
+
36
+ // Gruppen-Statistiken (falls Gruppe)
37
+ if (msg.isGroup) {
38
+ this.client.storage.write.in('analytics').increment(`groups.${groupId}.totalMessages`, 1);
39
+ this.client.storage.write.in('analytics').increment(`groups.${groupId}.totalChars`, messageLength);
40
+ this.client.storage.write.in('analytics').increment(`groups.${groupId}.hourly.${hour}`, 1);
41
+ this.client.storage.write.in('analytics').increment(`groups.${groupId}.daily.${day}`, 1);
42
+ this.client.storage.write.in('analytics').increment(`groups.${groupId}.users.${userId}`, 1);
43
+ this.client.storage.write.in('analytics').set(`groups.${groupId}.lastActivity`, timestamp);
44
+ }
45
+
46
+ // Globale Statistiken
47
+ this.client.storage.write.in('analytics').increment('global.totalMessages', 1);
48
+ this.client.storage.write.in('analytics').increment('global.totalChars', messageLength);
49
+ this.client.storage.write.in('analytics').increment(`global.hourly.${hour}`, 1);
50
+ this.client.storage.write.in('analytics').increment(`global.daily.${day}`, 1);
51
+
52
+ // Nachrichtentyp tracking
53
+ if (msg.type && msg.type !== 'text') {
54
+ this.client.storage.write.in('analytics').increment(`users.${userId}.mediaMessages`, 1);
55
+ if (msg.isGroup) {
56
+ this.client.storage.write.in('analytics').increment(`groups.${groupId}.mediaMessages`, 1);
57
+ }
58
+ }
59
+
60
+ // Command tracking
61
+ if (msg.text && msg.text.startsWith('!')) {
62
+ const command = msg.text.split(' ')[0].substring(1);
63
+ this.client.storage.write.in('analytics').increment(`commands.${command}`, 1);
64
+ this.client.storage.write.in('analytics').increment(`users.${userId}.commands`, 1);
65
+ }
66
+ }
67
+
68
+ getUserStats(userId) {
69
+ const userStats = this.client.storage.read.from('analytics').get(`users.${userId}`) || {};
70
+
71
+ return {
72
+ totalMessages: userStats.totalMessages || 0,
73
+ totalChars: userStats.totalChars || 0,
74
+ mediaMessages: userStats.mediaMessages || 0,
75
+ commands: userStats.commands || 0,
76
+ lastSeen: userStats.lastSeen || null,
77
+ avgMessageLength: userStats.totalMessages ? Math.round(userStats.totalChars / userStats.totalMessages) : 0,
78
+ hourly: userStats.hourly || {},
79
+ daily: userStats.daily || {}
80
+ };
81
+ }
82
+
83
+ getGroupStats(groupId) {
84
+ const groupStats = this.client.storage.read.from('analytics').get(`groups.${groupId}`) || {};
85
+
86
+ return {
87
+ totalMessages: groupStats.totalMessages || 0,
88
+ totalChars: groupStats.totalChars || 0,
89
+ mediaMessages: groupStats.mediaMessages || 0,
90
+ lastActivity: groupStats.lastActivity || null,
91
+ users: groupStats.users || {},
92
+ hourly: groupStats.hourly || {},
93
+ daily: groupStats.daily || {},
94
+ activeUsers: Object.keys(groupStats.users || {}).length
95
+ };
96
+ }
97
+
98
+ getGlobalStats() {
99
+ const globalStats = this.client.storage.read.from('analytics').get('global') || {};
100
+
101
+ return {
102
+ totalMessages: globalStats.totalMessages || 0,
103
+ totalChars: globalStats.totalChars || 0,
104
+ hourly: globalStats.hourly || {},
105
+ daily: globalStats.daily || {}
106
+ };
107
+ }
108
+
109
+ getTopUsers(limit = 10) {
110
+ const allUsers = this.client.storage.read.from('analytics').get('users') || {};
111
+
112
+ return Object.entries(allUsers)
113
+ .map(([userId, stats]) => ({
114
+ userId,
115
+ messages: stats.totalMessages || 0,
116
+ chars: stats.totalChars || 0,
117
+ avgLength: stats.totalMessages ? Math.round(stats.totalChars / stats.totalMessages) : 0
118
+ }))
119
+ .sort((a, b) => b.messages - a.messages)
120
+ .slice(0, limit);
121
+ }
122
+
123
+ getTopGroups(limit = 10) {
124
+ const allGroups = this.client.storage.read.from('analytics').get('groups') || {};
125
+
126
+ return Object.entries(allGroups)
127
+ .map(([groupId, stats]) => ({
128
+ groupId,
129
+ messages: stats.totalMessages || 0,
130
+ chars: stats.totalChars || 0,
131
+ users: Object.keys(stats.users || {}).length,
132
+ lastActivity: stats.lastActivity || null
133
+ }))
134
+ .sort((a, b) => b.messages - a.messages)
135
+ .slice(0, limit);
136
+ }
137
+
138
+ getTopCommands(limit = 10) {
139
+ const commands = this.client.storage.read.from('analytics').get('commands') || {};
140
+
141
+ return Object.entries(commands)
142
+ .map(([command, count]) => ({ command, count }))
143
+ .sort((a, b) => b.count - a.count)
144
+ .slice(0, limit);
145
+ }
146
+
147
+ getActivityHeatmap(type = 'global') {
148
+ let data;
149
+
150
+ if (type === 'global') {
151
+ data = this.getGlobalStats();
152
+ } else if (type.startsWith('user:')) {
153
+ const userId = type.split(':')[1];
154
+ data = this.getUserStats(userId);
155
+ } else if (type.startsWith('group:')) {
156
+ const groupId = type.split(':')[1];
157
+ data = this.getGroupStats(groupId);
158
+ }
159
+
160
+ const hourly = data?.hourly || {};
161
+ const daily = data?.daily || {};
162
+
163
+ // Stunden-Heatmap (0-23)
164
+ const hourlyHeatmap = [];
165
+ for (let i = 0; i < 24; i++) {
166
+ hourlyHeatmap.push({
167
+ hour: i,
168
+ messages: hourly[i] || 0,
169
+ intensity: this.getIntensity(hourly[i] || 0, Math.max(...Object.values(hourly)))
170
+ });
171
+ }
172
+
173
+ // Tages-Heatmap (0=Sonntag, 6=Samstag)
174
+ const dayNames = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
175
+ const dailyHeatmap = [];
176
+ for (let i = 0; i < 7; i++) {
177
+ dailyHeatmap.push({
178
+ day: i,
179
+ dayName: dayNames[i],
180
+ messages: daily[i] || 0,
181
+ intensity: this.getIntensity(daily[i] || 0, Math.max(...Object.values(daily)))
182
+ });
183
+ }
184
+
185
+ return { hourlyHeatmap, dailyHeatmap };
186
+ }
187
+
188
+ getIntensity(value, max) {
189
+ if (max === 0) return 0;
190
+ const percentage = (value / max) * 100;
191
+
192
+ if (percentage >= 80) return 5; // 🔥🔥🔥🔥🔥
193
+ if (percentage >= 60) return 4; // 🔥🔥🔥🔥
194
+ if (percentage >= 40) return 3; // 🔥🔥🔥
195
+ if (percentage >= 20) return 2; // 🔥🔥
196
+ if (percentage > 0) return 1; // 🔥
197
+ return 0; // ⬜
198
+ }
199
+
200
+ formatHeatmap(heatmap, type = 'hourly') {
201
+ let result = '';
202
+
203
+ if (type === 'hourly') {
204
+ result += '🕐 **Stunden-Aktivität (24h):**\n\n';
205
+
206
+ for (let i = 0; i < 24; i += 6) {
207
+ let line = '';
208
+ for (let j = 0; j < 6 && (i + j) < 24; j++) {
209
+ const hour = i + j;
210
+ const data = heatmap.find(h => h.hour === hour);
211
+ const intensity = data ? data.intensity : 0;
212
+ const emoji = ['⬜', '🔥', '🔥🔥', '🔥🔥🔥', '🔥🔥🔥🔥', '🔥🔥🔥🔥🔥'][intensity];
213
+ line += `${hour.toString().padStart(2, '0')}h${emoji} `;
214
+ }
215
+ result += line + '\n';
216
+ }
217
+ } else {
218
+ result += '📅 **Wochen-Aktivität:**\n\n';
219
+
220
+ heatmap.forEach(day => {
221
+ const emoji = ['⬜', '🔥', '🔥🔥', '🔥🔥🔥', '🔥🔥🔥🔥', '🔥🔥🔥🔥🔥'][day.intensity];
222
+ result += `${day.dayName}: ${emoji} (${day.messages})\n`;
223
+ });
224
+ }
225
+
226
+ return result;
227
+ }
228
+
229
+ getCommands() {
230
+ return {
231
+ 'stats': this.handleStats.bind(this),
232
+ 'mystats': this.handleMyStats.bind(this),
233
+ 'groupstats': this.handleGroupStats.bind(this),
234
+ 'globalstats': this.handleGlobalStats.bind(this),
235
+ 'topusers': this.handleTopUsers.bind(this),
236
+ 'topgroups': this.handleTopGroups.bind(this),
237
+ 'topcommands': this.handleTopCommands.bind(this),
238
+ 'heatmap': this.handleHeatmap.bind(this),
239
+ 'analytics': this.handleAnalytics.bind(this),
240
+ 'export': this.handleExport.bind(this)
241
+ };
242
+ }
243
+
244
+ async handleStats(msg, args) {
245
+ const mentionedUsers = msg.getMentionedUsers();
246
+
247
+ if (mentionedUsers.length > 0) {
248
+ // Stats für erwähnten User
249
+ const targetUser = mentionedUsers[0];
250
+ const stats = this.getUserStats(targetUser);
251
+
252
+ let statsText = `📊 **Statistiken für @${targetUser.split('@')[0]}**\n\n`;
253
+ statsText += `💬 Nachrichten: ${stats.totalMessages.toLocaleString()}\n`;
254
+ statsText += `📝 Zeichen: ${stats.totalChars.toLocaleString()}\n`;
255
+ statsText += `📊 Ø Länge: ${stats.avgMessageLength} Zeichen\n`;
256
+ statsText += `🎮 Commands: ${stats.commands}\n`;
257
+ statsText += `📷 Medien: ${stats.mediaMessages}\n`;
258
+
259
+ if (stats.lastSeen) {
260
+ const lastSeen = new Date(stats.lastSeen);
261
+ statsText += `👀 Zuletzt: ${lastSeen.toLocaleString('de-DE')}`;
262
+ }
263
+
264
+ await msg.reply(statsText, [targetUser]);
265
+ } else {
266
+ // Eigene Stats
267
+ await this.handleMyStats(msg, args);
268
+ }
269
+ }
270
+
271
+ async handleMyStats(msg, args) {
272
+ const userId = msg.getSender();
273
+ const stats = this.getUserStats(userId);
274
+
275
+ let statsText = `📊 **Deine Statistiken**\n\n`;
276
+ statsText += `💬 Nachrichten: ${stats.totalMessages.toLocaleString()}\n`;
277
+ statsText += `📝 Zeichen: ${stats.totalChars.toLocaleString()}\n`;
278
+ statsText += `📊 Ø Länge: ${stats.avgMessageLength} Zeichen\n`;
279
+ statsText += `🎮 Commands: ${stats.commands}\n`;
280
+ statsText += `📷 Medien: ${stats.mediaMessages}\n\n`;
281
+ statsText += `💡 Verwende !heatmap für Aktivitätsmuster`;
282
+
283
+ await msg.reply(statsText);
284
+ }
285
+
286
+ async handleGroupStats(msg, args) {
287
+ if (!msg.isGroup) {
288
+ return msg.reply('❌ Nur in Gruppen verfügbar!');
289
+ }
290
+
291
+ const groupId = msg.from;
292
+ const stats = this.getGroupStats(groupId);
293
+
294
+ let statsText = `📊 **Gruppen-Statistiken**\n\n`;
295
+ statsText += `💬 Nachrichten: ${stats.totalMessages.toLocaleString()}\n`;
296
+ statsText += `📝 Zeichen: ${stats.totalChars.toLocaleString()}\n`;
297
+ statsText += `👥 Aktive User: ${stats.activeUsers}\n`;
298
+ statsText += `📷 Medien: ${stats.mediaMessages}\n`;
299
+
300
+ if (stats.lastActivity) {
301
+ const lastActivity = new Date(stats.lastActivity);
302
+ statsText += `⏰ Letzte Aktivität: ${lastActivity.toLocaleString('de-DE')}\n`;
303
+ }
304
+
305
+ // Top 5 User in der Gruppe
306
+ const topUsers = Object.entries(stats.users)
307
+ .sort(([,a], [,b]) => b - a)
308
+ .slice(0, 5);
309
+
310
+ if (topUsers.length > 0) {
311
+ statsText += `\n🏆 **Top User:**\n`;
312
+ topUsers.forEach(([userId, count], index) => {
313
+ statsText += `${index + 1}. @${userId.split('@')[0]}: ${count}\n`;
314
+ });
315
+ }
316
+
317
+ await msg.reply(statsText);
318
+ }
319
+
320
+ async handleGlobalStats(msg, args) {
321
+ const stats = this.getGlobalStats();
322
+
323
+ let statsText = `🌍 **Globale Statistiken**\n\n`;
324
+ statsText += `💬 Gesamte Nachrichten: ${stats.totalMessages.toLocaleString()}\n`;
325
+ statsText += `📝 Gesamte Zeichen: ${stats.totalChars.toLocaleString()}\n`;
326
+
327
+ const avgLength = stats.totalMessages ? Math.round(stats.totalChars / stats.totalMessages) : 0;
328
+ statsText += `📊 Ø Nachrichtenlänge: ${avgLength} Zeichen\n\n`;
329
+
330
+ // Aktivste Stunde
331
+ const hourlyStats = stats.hourly || {};
332
+ const mostActiveHour = Object.entries(hourlyStats)
333
+ .sort(([,a], [,b]) => b - a)[0];
334
+
335
+ if (mostActiveHour) {
336
+ statsText += `🕐 Aktivste Stunde: ${mostActiveHour[0]}:00 (${mostActiveHour[1]} Nachrichten)\n`;
337
+ }
338
+
339
+ // Aktivster Tag
340
+ const dailyStats = stats.daily || {};
341
+ const dayNames = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
342
+ const mostActiveDay = Object.entries(dailyStats)
343
+ .sort(([,a], [,b]) => b - a)[0];
344
+
345
+ if (mostActiveDay) {
346
+ statsText += `📅 Aktivster Tag: ${dayNames[mostActiveDay[0]]} (${mostActiveDay[1]} Nachrichten)`;
347
+ }
348
+
349
+ await msg.reply(statsText);
350
+ }
351
+
352
+ async handleTopUsers(msg, args) {
353
+ const limit = args.length > 0 ? parseInt(args[0]) || 10 : 10;
354
+ const topUsers = this.getTopUsers(Math.min(limit, 20));
355
+
356
+ if (topUsers.length === 0) {
357
+ return msg.reply('📊 Noch keine User-Daten verfügbar!');
358
+ }
359
+
360
+ let topText = `🏆 **Top ${topUsers.length} User**\n\n`;
361
+
362
+ topUsers.forEach((user, index) => {
363
+ const medal = index === 0 ? '🥇' : index === 1 ? '🥈' : index === 2 ? '🥉' : `${index + 1}.`;
364
+ topText += `${medal} @${user.userId.split('@')[0]}\n`;
365
+ topText += ` 💬 ${user.messages.toLocaleString()} | 📝 ${user.chars.toLocaleString()} | Ø ${user.avgLength}\n\n`;
366
+ });
367
+
368
+ await msg.reply(topText);
369
+ }
370
+
371
+ async handleTopGroups(msg, args) {
372
+ const limit = args.length > 0 ? parseInt(args[0]) || 10 : 10;
373
+ const topGroups = this.getTopGroups(Math.min(limit, 20));
374
+
375
+ if (topGroups.length === 0) {
376
+ return msg.reply('📊 Noch keine Gruppen-Daten verfügbar!');
377
+ }
378
+
379
+ let topText = `🏆 **Top ${topGroups.length} Gruppen**\n\n`;
380
+
381
+ topGroups.forEach((group, index) => {
382
+ const medal = index === 0 ? '🥇' : index === 1 ? '🥈' : index === 2 ? '🥉' : `${index + 1}.`;
383
+ topText += `${medal} Gruppe\n`;
384
+ topText += ` 💬 ${group.messages.toLocaleString()} | 👥 ${group.users} User\n\n`;
385
+ });
386
+
387
+ await msg.reply(topText);
388
+ }
389
+
390
+ async handleTopCommands(msg, args) {
391
+ const limit = args.length > 0 ? parseInt(args[0]) || 10 : 10;
392
+ const topCommands = this.getTopCommands(Math.min(limit, 20));
393
+
394
+ if (topCommands.length === 0) {
395
+ return msg.reply('📊 Noch keine Command-Daten verfügbar!');
396
+ }
397
+
398
+ let topText = `🎮 **Top ${topCommands.length} Commands**\n\n`;
399
+
400
+ topCommands.forEach((cmd, index) => {
401
+ const medal = index === 0 ? '🥇' : index === 1 ? '🥈' : index === 2 ? '🥉' : `${index + 1}.`;
402
+ topText += `${medal} !${cmd.command}: ${cmd.count.toLocaleString()}x\n`;
403
+ });
404
+
405
+ await msg.reply(topText);
406
+ }
407
+
408
+ async handleHeatmap(msg, args) {
409
+ let type = 'global';
410
+
411
+ if (args.length > 0) {
412
+ if (args[0] === 'me') {
413
+ type = `user:${msg.getSender()}`;
414
+ } else if (args[0] === 'group' && msg.isGroup) {
415
+ type = `group:${msg.from}`;
416
+ }
417
+ }
418
+
419
+ const { hourlyHeatmap, dailyHeatmap } = this.getActivityHeatmap(type);
420
+
421
+ let heatmapText = `🔥 **Aktivitäts-Heatmap**\n\n`;
422
+ heatmapText += this.formatHeatmap(hourlyHeatmap, 'hourly');
423
+ heatmapText += '\n';
424
+ heatmapText += this.formatHeatmap(dailyHeatmap, 'daily');
425
+ heatmapText += '\n💡 Legende: ⬜ = Keine Aktivität, 🔥 = Niedrig, 🔥🔥🔥🔥🔥 = Sehr hoch';
426
+
427
+ await msg.reply(heatmapText);
428
+ }
429
+
430
+ async handleAnalytics(msg, args) {
431
+ let analyticsText = `📊 **Analytics Plugin - Übersicht**\n\n`;
432
+ analyticsText += `📈 **!stats** [@user] - User-Statistiken\n`;
433
+ analyticsText += `📊 **!mystats** - Deine Statistiken\n`;
434
+ analyticsText += `👥 **!groupstats** - Gruppen-Statistiken\n`;
435
+ analyticsText += `🌍 **!globalstats** - Globale Statistiken\n`;
436
+ analyticsText += `🏆 **!topusers** [anzahl] - Top User\n`;
437
+ analyticsText += `🏆 **!topgroups** [anzahl] - Top Gruppen\n`;
438
+ analyticsText += `🎮 **!topcommands** [anzahl] - Top Commands\n`;
439
+ analyticsText += `🔥 **!heatmap** [me/group] - Aktivitätsmuster\n`;
440
+ analyticsText += `📤 **!export** - Daten exportieren\n\n`;
441
+ analyticsText += `💡 Alle Daten werden automatisch erfasst!`;
442
+
443
+ await msg.reply(analyticsText);
444
+ }
445
+
446
+ async handleExport(msg, args) {
447
+ const userId = msg.getSender();
448
+ const userStats = this.getUserStats(userId);
449
+
450
+ let exportText = `📤 **Daten-Export für @${userId.split('@')[0]}**\n\n`;
451
+ exportText += `📊 **Zusammenfassung:**\n`;
452
+ exportText += `• Nachrichten: ${userStats.totalMessages}\n`;
453
+ exportText += `• Zeichen: ${userStats.totalChars}\n`;
454
+ exportText += `• Commands: ${userStats.commands}\n`;
455
+ exportText += `• Medien: ${userStats.mediaMessages}\n\n`;
456
+ exportText += `⚠️ **Datenschutz:** Deine Daten werden lokal gespeichert und nicht weitergegeben.\n`;
457
+ exportText += `🗑️ Kontaktiere einen Admin für Datenlöschung.`;
458
+
459
+ await msg.reply(exportText);
460
+ }
461
+ }
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "creative-plugin",
3
+ "displayName": "Creative Plugin",
4
+ "version": "1.0.0",
5
+ "description": "Kreative Tools für Memes, ASCII-Art, Zitate und mehr",
6
+ "author": "WAEngine",
7
+ "category": "entertainment",
8
+ "permissions": [
9
+ "send_messages",
10
+ "create_content"
11
+ ],
12
+ "commands": [
13
+ {
14
+ "name": "meme",
15
+ "description": "Meme Generator mit Templates",
16
+ "usage": "!meme <nummer> <text>",
17
+ "adminOnly": false
18
+ },
19
+ {
20
+ "name": "quote",
21
+ "description": "Inspirierende Zitate",
22
+ "usage": "!quote",
23
+ "adminOnly": false
24
+ },
25
+ {
26
+ "name": "ascii",
27
+ "description": "ASCII-Art erstellen",
28
+ "usage": "!ascii <typ>",
29
+ "adminOnly": false
30
+ },
31
+ {
32
+ "name": "textart",
33
+ "description": "Großer Text-Art",
34
+ "usage": "!textart <text>",
35
+ "adminOnly": false
36
+ },
37
+ {
38
+ "name": "colortext",
39
+ "description": "Bunter Text mit Emojis",
40
+ "usage": "!colortext <text> [stil]",
41
+ "adminOnly": false
42
+ },
43
+ {
44
+ "name": "fact",
45
+ "description": "Unglaubliche Fakten",
46
+ "usage": "!fact",
47
+ "adminOnly": false
48
+ },
49
+ {
50
+ "name": "joke",
51
+ "description": "Lustige Witze",
52
+ "usage": "!joke",
53
+ "adminOnly": false
54
+ },
55
+ {
56
+ "name": "story",
57
+ "description": "Story-Prompt Generator",
58
+ "usage": "!story",
59
+ "adminOnly": false
60
+ },
61
+ {
62
+ "name": "inspire",
63
+ "description": "Zufällige Inspiration",
64
+ "usage": "!inspire",
65
+ "adminOnly": false
66
+ },
67
+ {
68
+ "name": "creative",
69
+ "description": "Plugin-Übersicht",
70
+ "usage": "!creative",
71
+ "adminOnly": false
72
+ }
73
+ ],
74
+ "settings": {
75
+ "memeTemplates": 8,
76
+ "quotes": 8,
77
+ "asciiArt": 5,
78
+ "jokes": 10,
79
+ "facts": 10
80
+ },
81
+ "dependencies": [],
82
+ "storage": [
83
+ "user_creations",
84
+ "favorite_memes",
85
+ "custom_quotes"
86
+ ]
87
+ }