@furlow/builtins 0.1.0

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.
Files changed (46) hide show
  1. package/dist/afk/index.d.ts +21 -0
  2. package/dist/afk/index.js +195 -0
  3. package/dist/afk/index.js.map +1 -0
  4. package/dist/auto-responder/index.d.ts +21 -0
  5. package/dist/auto-responder/index.js +356 -0
  6. package/dist/auto-responder/index.js.map +1 -0
  7. package/dist/giveaways/index.d.ts +25 -0
  8. package/dist/giveaways/index.js +416 -0
  9. package/dist/giveaways/index.js.map +1 -0
  10. package/dist/index.d.ts +15 -0
  11. package/dist/index.js +5402 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/leveling/index.d.ts +46 -0
  14. package/dist/leveling/index.js +521 -0
  15. package/dist/leveling/index.js.map +1 -0
  16. package/dist/logging/index.d.ts +52 -0
  17. package/dist/logging/index.js +519 -0
  18. package/dist/logging/index.js.map +1 -0
  19. package/dist/moderation/index.d.ts +83 -0
  20. package/dist/moderation/index.js +221 -0
  21. package/dist/moderation/index.js.map +1 -0
  22. package/dist/music/index.d.ts +33 -0
  23. package/dist/music/index.js +414 -0
  24. package/dist/music/index.js.map +1 -0
  25. package/dist/polls/index.d.ts +21 -0
  26. package/dist/polls/index.js +395 -0
  27. package/dist/polls/index.js.map +1 -0
  28. package/dist/reaction-roles/index.d.ts +19 -0
  29. package/dist/reaction-roles/index.js +551 -0
  30. package/dist/reaction-roles/index.js.map +1 -0
  31. package/dist/reminders/index.d.ts +23 -0
  32. package/dist/reminders/index.js +224 -0
  33. package/dist/reminders/index.js.map +1 -0
  34. package/dist/starboard/index.d.ts +35 -0
  35. package/dist/starboard/index.js +401 -0
  36. package/dist/starboard/index.js.map +1 -0
  37. package/dist/tickets/index.d.ts +43 -0
  38. package/dist/tickets/index.js +614 -0
  39. package/dist/tickets/index.js.map +1 -0
  40. package/dist/utilities/index.d.ts +15 -0
  41. package/dist/utilities/index.js +299 -0
  42. package/dist/utilities/index.js.map +1 -0
  43. package/dist/welcome/index.d.ts +48 -0
  44. package/dist/welcome/index.js +302 -0
  45. package/dist/welcome/index.js.map +1 -0
  46. package/package.json +109 -0
@@ -0,0 +1,519 @@
1
+ // src/logging/index.ts
2
+ var loggingEventHandlers = [
3
+ // Message Delete
4
+ {
5
+ event: "message_delete",
6
+ condition: "${config.logging.events?.messageDelete !== false && !config.logging.ignoredChannels?.includes(channel.id)}",
7
+ actions: [
8
+ {
9
+ action: "send_message",
10
+ channel: "${config.logging.channels?.messages || config.logging.channel}",
11
+ embed: {
12
+ title: "Message Deleted",
13
+ description: '${message.content || "*No text content*"}',
14
+ color: "#ed4245",
15
+ fields: [
16
+ { name: "Author", value: '${message.author ? "<@" + message.author.id + ">" : "Unknown"}', inline: true },
17
+ { name: "Channel", value: "<#${channel.id}>", inline: true },
18
+ { name: "Message ID", value: "${message.id}", inline: true }
19
+ ],
20
+ footer: {
21
+ text: 'User ID: ${message.author?.id || "Unknown"}'
22
+ },
23
+ timestamp: "${now()}"
24
+ }
25
+ }
26
+ ]
27
+ },
28
+ // Message Edit
29
+ {
30
+ event: "message_update",
31
+ condition: "${config.logging.events?.messageEdit !== false && oldMessage.content !== newMessage.content && !config.logging.ignoredChannels?.includes(channel.id)}",
32
+ actions: [
33
+ {
34
+ action: "send_message",
35
+ channel: "${config.logging.channels?.messages || config.logging.channel}",
36
+ embed: {
37
+ title: "Message Edited",
38
+ color: "#fee75c",
39
+ fields: [
40
+ { name: "Before", value: '${truncate(oldMessage.content || "*Empty*", 1024)}' },
41
+ { name: "After", value: '${truncate(newMessage.content || "*Empty*", 1024)}' },
42
+ { name: "Author", value: "<@${newMessage.author.id}>", inline: true },
43
+ { name: "Channel", value: "<#${channel.id}>", inline: true },
44
+ { name: "Jump to Message", value: "[Click here](${newMessage.url})", inline: true }
45
+ ],
46
+ footer: {
47
+ text: "User ID: ${newMessage.author.id}"
48
+ },
49
+ timestamp: "${now()}"
50
+ }
51
+ }
52
+ ]
53
+ },
54
+ // Bulk Message Delete
55
+ {
56
+ event: "message_bulk_delete",
57
+ condition: "${config.logging.events?.messageBulkDelete !== false}",
58
+ actions: [
59
+ {
60
+ action: "set",
61
+ key: "logContent",
62
+ value: '${messages | map(m => "[" + (m.author?.tag || "Unknown") + "]: " + (m.content || "*attachment/embed*")) | join("\\n")}'
63
+ },
64
+ {
65
+ action: "send_message",
66
+ channel: "${config.logging.channels?.messages || config.logging.channel}",
67
+ embed: {
68
+ title: "Bulk Messages Deleted",
69
+ description: "${messages.length} messages were deleted in <#${channel.id}>",
70
+ color: "#ed4245",
71
+ timestamp: "${now()}"
72
+ },
73
+ files: [
74
+ {
75
+ attachment: "${Buffer.from(logContent)}",
76
+ name: "deleted-messages.txt"
77
+ }
78
+ ]
79
+ }
80
+ ]
81
+ },
82
+ // Member Join
83
+ {
84
+ event: "member_join",
85
+ condition: "${config.logging.events?.memberJoin !== false}",
86
+ actions: [
87
+ {
88
+ action: "set",
89
+ key: "accountAge",
90
+ value: "${floor((now() - member.user.createdAt) / (1000 * 60 * 60 * 24))}"
91
+ },
92
+ {
93
+ action: "send_message",
94
+ channel: "${config.logging.channels?.members || config.logging.channel}",
95
+ embed: {
96
+ title: "Member Joined",
97
+ description: "<@${member.id}> joined the server",
98
+ color: "#57f287",
99
+ thumbnail: "${member.user.avatarURL}",
100
+ fields: [
101
+ { name: "Username", value: "${member.user.tag}", inline: true },
102
+ { name: "Account Age", value: "${accountAge} days", inline: true },
103
+ { name: "Member Count", value: "${guild.memberCount}", inline: true }
104
+ ],
105
+ footer: {
106
+ text: "User ID: ${member.id}"
107
+ },
108
+ timestamp: "${now()}"
109
+ }
110
+ }
111
+ ]
112
+ },
113
+ // Member Leave
114
+ {
115
+ event: "member_leave",
116
+ condition: "${config.logging.events?.memberLeave !== false}",
117
+ actions: [
118
+ {
119
+ action: "set",
120
+ key: "roles",
121
+ value: '${member.roles?.cache?.filter(r => r.id !== guild.id)?.map(r => r.name)?.join(", ") || "None"}'
122
+ },
123
+ {
124
+ action: "send_message",
125
+ channel: "${config.logging.channels?.members || config.logging.channel}",
126
+ embed: {
127
+ title: "Member Left",
128
+ description: "<@${member.id}> left the server",
129
+ color: "#ed4245",
130
+ thumbnail: "${member.user.avatarURL}",
131
+ fields: [
132
+ { name: "Username", value: "${member.user.tag}", inline: true },
133
+ { name: "Roles", value: "${truncate(roles, 1024)}", inline: false },
134
+ { name: "Joined At", value: '${timestamp(member.joinedAt, "R")}', inline: true }
135
+ ],
136
+ footer: {
137
+ text: "User ID: ${member.id}"
138
+ },
139
+ timestamp: "${now()}"
140
+ }
141
+ }
142
+ ]
143
+ },
144
+ // Member Update (roles, nickname)
145
+ {
146
+ event: "member_update",
147
+ condition: "${config.logging.events?.memberUpdate !== false}",
148
+ actions: [
149
+ // Role changes
150
+ {
151
+ action: "flow_if",
152
+ condition: "${oldMember.roles.cache.size !== newMember.roles.cache.size}",
153
+ then: [
154
+ {
155
+ action: "set",
156
+ key: "addedRoles",
157
+ value: '${newMember.roles.cache.filter(r => !oldMember.roles.cache.has(r.id)).map(r => r.name).join(", ")}'
158
+ },
159
+ {
160
+ action: "set",
161
+ key: "removedRoles",
162
+ value: '${oldMember.roles.cache.filter(r => !newMember.roles.cache.has(r.id)).map(r => r.name).join(", ")}'
163
+ },
164
+ {
165
+ action: "send_message",
166
+ channel: "${config.logging.channels?.members || config.logging.channel}",
167
+ embed: {
168
+ title: "Member Roles Updated",
169
+ description: "<@${newMember.id}>'s roles were changed",
170
+ color: "#5865f2",
171
+ fields: [
172
+ { name: "Added Roles", value: '${addedRoles || "None"}', inline: true },
173
+ { name: "Removed Roles", value: '${removedRoles || "None"}', inline: true }
174
+ ],
175
+ footer: {
176
+ text: "User ID: ${newMember.id}"
177
+ },
178
+ timestamp: "${now()}"
179
+ }
180
+ }
181
+ ]
182
+ },
183
+ // Nickname changes
184
+ {
185
+ action: "flow_if",
186
+ condition: "${oldMember.nickname !== newMember.nickname}",
187
+ then: [
188
+ {
189
+ action: "send_message",
190
+ channel: "${config.logging.channels?.members || config.logging.channel}",
191
+ embed: {
192
+ title: "Nickname Changed",
193
+ description: "<@${newMember.id}>'s nickname was changed",
194
+ color: "#5865f2",
195
+ fields: [
196
+ { name: "Before", value: "${oldMember.nickname || oldMember.user.username}", inline: true },
197
+ { name: "After", value: "${newMember.nickname || newMember.user.username}", inline: true }
198
+ ],
199
+ footer: {
200
+ text: "User ID: ${newMember.id}"
201
+ },
202
+ timestamp: "${now()}"
203
+ }
204
+ }
205
+ ]
206
+ }
207
+ ]
208
+ },
209
+ // Member Ban
210
+ {
211
+ event: "member_ban",
212
+ condition: "${config.logging.events?.memberBan !== false}",
213
+ actions: [
214
+ {
215
+ action: "send_message",
216
+ channel: "${config.logging.channels?.moderation || config.logging.channel}",
217
+ embed: {
218
+ title: "Member Banned",
219
+ description: "<@${user.id}> was banned",
220
+ color: "#ed4245",
221
+ thumbnail: "${user.avatarURL}",
222
+ fields: [
223
+ { name: "Username", value: "${user.tag}", inline: true },
224
+ { name: "Reason", value: '${ban.reason || "No reason provided"}', inline: false }
225
+ ],
226
+ footer: {
227
+ text: "User ID: ${user.id}"
228
+ },
229
+ timestamp: "${now()}"
230
+ }
231
+ }
232
+ ]
233
+ },
234
+ // Member Unban
235
+ {
236
+ event: "member_unban",
237
+ condition: "${config.logging.events?.memberUnban !== false}",
238
+ actions: [
239
+ {
240
+ action: "send_message",
241
+ channel: "${config.logging.channels?.moderation || config.logging.channel}",
242
+ embed: {
243
+ title: "Member Unbanned",
244
+ description: "<@${user.id}> was unbanned",
245
+ color: "#57f287",
246
+ thumbnail: "${user.avatarURL}",
247
+ fields: [
248
+ { name: "Username", value: "${user.tag}", inline: true }
249
+ ],
250
+ footer: {
251
+ text: "User ID: ${user.id}"
252
+ },
253
+ timestamp: "${now()}"
254
+ }
255
+ }
256
+ ]
257
+ },
258
+ // Voice Join
259
+ {
260
+ event: "voice_join",
261
+ condition: "${config.logging.events?.voiceJoin !== false}",
262
+ actions: [
263
+ {
264
+ action: "send_message",
265
+ channel: "${config.logging.channels?.voice || config.logging.channel}",
266
+ embed: {
267
+ title: "Voice Channel Joined",
268
+ description: "<@${member.id}> joined <#${channel.id}>",
269
+ color: "#57f287",
270
+ footer: {
271
+ text: "User ID: ${member.id}"
272
+ },
273
+ timestamp: "${now()}"
274
+ }
275
+ }
276
+ ]
277
+ },
278
+ // Voice Leave
279
+ {
280
+ event: "voice_leave",
281
+ condition: "${config.logging.events?.voiceLeave !== false}",
282
+ actions: [
283
+ {
284
+ action: "send_message",
285
+ channel: "${config.logging.channels?.voice || config.logging.channel}",
286
+ embed: {
287
+ title: "Voice Channel Left",
288
+ description: "<@${member.id}> left <#${channel.id}>",
289
+ color: "#ed4245",
290
+ footer: {
291
+ text: "User ID: ${member.id}"
292
+ },
293
+ timestamp: "${now()}"
294
+ }
295
+ }
296
+ ]
297
+ },
298
+ // Voice Move
299
+ {
300
+ event: "voice_move",
301
+ condition: "${config.logging.events?.voiceMove !== false}",
302
+ actions: [
303
+ {
304
+ action: "send_message",
305
+ channel: "${config.logging.channels?.voice || config.logging.channel}",
306
+ embed: {
307
+ title: "Voice Channel Switch",
308
+ description: "<@${member.id}> switched voice channels",
309
+ color: "#5865f2",
310
+ fields: [
311
+ { name: "From", value: "<#${oldChannel.id}>", inline: true },
312
+ { name: "To", value: "<#${newChannel.id}>", inline: true }
313
+ ],
314
+ footer: {
315
+ text: "User ID: ${member.id}"
316
+ },
317
+ timestamp: "${now()}"
318
+ }
319
+ }
320
+ ]
321
+ },
322
+ // Channel Create
323
+ {
324
+ event: "channel_create",
325
+ condition: "${config.logging.events?.channelCreate !== false}",
326
+ actions: [
327
+ {
328
+ action: "send_message",
329
+ channel: "${config.logging.channels?.server || config.logging.channel}",
330
+ embed: {
331
+ title: "Channel Created",
332
+ description: "<#${channel.id}> was created",
333
+ color: "#57f287",
334
+ fields: [
335
+ { name: "Name", value: "${channel.name}", inline: true },
336
+ { name: "Type", value: "${channel.type}", inline: true }
337
+ ],
338
+ timestamp: "${now()}"
339
+ }
340
+ }
341
+ ]
342
+ },
343
+ // Channel Delete
344
+ {
345
+ event: "channel_delete",
346
+ condition: "${config.logging.events?.channelDelete !== false}",
347
+ actions: [
348
+ {
349
+ action: "send_message",
350
+ channel: "${config.logging.channels?.server || config.logging.channel}",
351
+ embed: {
352
+ title: "Channel Deleted",
353
+ description: "#${channel.name} was deleted",
354
+ color: "#ed4245",
355
+ fields: [
356
+ { name: "Type", value: "${channel.type}", inline: true }
357
+ ],
358
+ timestamp: "${now()}"
359
+ }
360
+ }
361
+ ]
362
+ },
363
+ // Role Create
364
+ {
365
+ event: "role_create",
366
+ condition: "${config.logging.events?.roleCreate !== false}",
367
+ actions: [
368
+ {
369
+ action: "send_message",
370
+ channel: "${config.logging.channels?.server || config.logging.channel}",
371
+ embed: {
372
+ title: "Role Created",
373
+ description: "${role.name} was created",
374
+ color: '${role.hexColor || "#57f287"}',
375
+ fields: [
376
+ { name: "Color", value: '${role.hexColor || "None"}', inline: true },
377
+ { name: "Hoisted", value: '${role.hoist ? "Yes" : "No"}', inline: true },
378
+ { name: "Mentionable", value: '${role.mentionable ? "Yes" : "No"}', inline: true }
379
+ ],
380
+ footer: {
381
+ text: "Role ID: ${role.id}"
382
+ },
383
+ timestamp: "${now()}"
384
+ }
385
+ }
386
+ ]
387
+ },
388
+ // Role Delete
389
+ {
390
+ event: "role_delete",
391
+ condition: "${config.logging.events?.roleDelete !== false}",
392
+ actions: [
393
+ {
394
+ action: "send_message",
395
+ channel: "${config.logging.channels?.server || config.logging.channel}",
396
+ embed: {
397
+ title: "Role Deleted",
398
+ description: "${role.name} was deleted",
399
+ color: "#ed4245",
400
+ footer: {
401
+ text: "Role ID: ${role.id}"
402
+ },
403
+ timestamp: "${now()}"
404
+ }
405
+ }
406
+ ]
407
+ }
408
+ ];
409
+ var loggingCommands = [
410
+ {
411
+ name: "logging",
412
+ description: "Logging configuration commands",
413
+ subcommands: [
414
+ {
415
+ name: "set-channel",
416
+ description: "Set the logging channel",
417
+ options: [
418
+ { name: "channel", description: "Channel for logs", type: "channel", required: true },
419
+ { name: "category", description: "Log category", type: "string", required: false, choices: [
420
+ { name: "All", value: "all" },
421
+ { name: "Messages", value: "messages" },
422
+ { name: "Members", value: "members" },
423
+ { name: "Voice", value: "voice" },
424
+ { name: "Server", value: "server" },
425
+ { name: "Moderation", value: "moderation" }
426
+ ] }
427
+ ],
428
+ actions: [
429
+ {
430
+ action: "flow_if",
431
+ condition: '${!args.category || args.category === "all"}',
432
+ then: [
433
+ {
434
+ action: "set",
435
+ key: "config.logging.channel",
436
+ value: "${args.channel.id}",
437
+ scope: "guild"
438
+ }
439
+ ],
440
+ else: [
441
+ {
442
+ action: "set",
443
+ key: "config.logging.channels.${args.category}",
444
+ value: "${args.channel.id}",
445
+ scope: "guild"
446
+ }
447
+ ]
448
+ },
449
+ {
450
+ action: "reply",
451
+ content: "Logging channel updated!",
452
+ ephemeral: true
453
+ }
454
+ ]
455
+ },
456
+ {
457
+ name: "toggle",
458
+ description: "Toggle a logging event",
459
+ options: [
460
+ { name: "event", description: "Event to toggle", type: "string", required: true, choices: [
461
+ { name: "Message Delete", value: "messageDelete" },
462
+ { name: "Message Edit", value: "messageEdit" },
463
+ { name: "Member Join", value: "memberJoin" },
464
+ { name: "Member Leave", value: "memberLeave" },
465
+ { name: "Member Ban", value: "memberBan" },
466
+ { name: "Voice Join", value: "voiceJoin" },
467
+ { name: "Voice Leave", value: "voiceLeave" }
468
+ ] },
469
+ { name: "enabled", description: "Enable or disable", type: "boolean", required: true }
470
+ ],
471
+ actions: [
472
+ {
473
+ action: "set",
474
+ key: "config.logging.events.${args.event}",
475
+ value: "${args.enabled}",
476
+ scope: "guild"
477
+ },
478
+ {
479
+ action: "reply",
480
+ content: '${args.event} logging ${args.enabled ? "enabled" : "disabled"}!',
481
+ ephemeral: true
482
+ }
483
+ ]
484
+ },
485
+ {
486
+ name: "ignore-channel",
487
+ description: "Ignore a channel from logging",
488
+ options: [
489
+ { name: "channel", description: "Channel to ignore", type: "channel", required: true }
490
+ ],
491
+ actions: [
492
+ {
493
+ action: "list_push",
494
+ key: "config.logging.ignoredChannels",
495
+ value: "${args.channel.id}",
496
+ scope: "guild"
497
+ },
498
+ {
499
+ action: "reply",
500
+ content: "${args.channel} will now be ignored from logs.",
501
+ ephemeral: true
502
+ }
503
+ ]
504
+ }
505
+ ]
506
+ }
507
+ ];
508
+ function getLoggingSpec(config = {}) {
509
+ return {
510
+ events: loggingEventHandlers,
511
+ commands: loggingCommands
512
+ };
513
+ }
514
+ export {
515
+ getLoggingSpec,
516
+ loggingCommands,
517
+ loggingEventHandlers
518
+ };
519
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logging/index.ts"],"sourcesContent":["/**\n * Logging builtin module\n * Handles comprehensive server logging for messages, members, voice, and moderation\n */\n\nimport type { FurlowSpec, CommandDefinition, EventHandler } from '@furlow/schema';\n\nexport interface LoggingConfig {\n /** Default log channel */\n channel?: string;\n /** Separate channels per category */\n channels?: {\n messages?: string;\n members?: string;\n voice?: string;\n server?: string;\n moderation?: string;\n };\n /** Ignored channels */\n ignoredChannels?: string[];\n /** Ignored roles (users with these roles won't be logged) */\n ignoredRoles?: string[];\n /** Events to log */\n events?: {\n messageDelete?: boolean;\n messageEdit?: boolean;\n messageBulkDelete?: boolean;\n memberJoin?: boolean;\n memberLeave?: boolean;\n memberUpdate?: boolean;\n memberBan?: boolean;\n memberUnban?: boolean;\n voiceJoin?: boolean;\n voiceLeave?: boolean;\n voiceMove?: boolean;\n channelCreate?: boolean;\n channelDelete?: boolean;\n channelUpdate?: boolean;\n roleCreate?: boolean;\n roleDelete?: boolean;\n roleUpdate?: boolean;\n inviteCreate?: boolean;\n inviteDelete?: boolean;\n };\n /** Include images in logs */\n includeImages?: boolean;\n}\n\nexport const loggingEventHandlers: EventHandler[] = [\n // Message Delete\n {\n event: 'message_delete',\n condition: '${config.logging.events?.messageDelete !== false && !config.logging.ignoredChannels?.includes(channel.id)}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.messages || config.logging.channel}',\n embed: {\n title: 'Message Deleted',\n description: '${message.content || \"*No text content*\"}',\n color: '#ed4245',\n fields: [\n { name: 'Author', value: '${message.author ? \"<@\" + message.author.id + \">\" : \"Unknown\"}', inline: true },\n { name: 'Channel', value: '<#${channel.id}>', inline: true },\n { name: 'Message ID', value: '${message.id}', inline: true },\n ],\n footer: {\n text: 'User ID: ${message.author?.id || \"Unknown\"}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Message Edit\n {\n event: 'message_update',\n condition: '${config.logging.events?.messageEdit !== false && oldMessage.content !== newMessage.content && !config.logging.ignoredChannels?.includes(channel.id)}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.messages || config.logging.channel}',\n embed: {\n title: 'Message Edited',\n color: '#fee75c',\n fields: [\n { name: 'Before', value: '${truncate(oldMessage.content || \"*Empty*\", 1024)}' },\n { name: 'After', value: '${truncate(newMessage.content || \"*Empty*\", 1024)}' },\n { name: 'Author', value: '<@${newMessage.author.id}>', inline: true },\n { name: 'Channel', value: '<#${channel.id}>', inline: true },\n { name: 'Jump to Message', value: '[Click here](${newMessage.url})', inline: true },\n ],\n footer: {\n text: 'User ID: ${newMessage.author.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Bulk Message Delete\n {\n event: 'message_bulk_delete',\n condition: '${config.logging.events?.messageBulkDelete !== false}',\n actions: [\n {\n action: 'set',\n key: 'logContent',\n value: '${messages | map(m => \"[\" + (m.author?.tag || \"Unknown\") + \"]: \" + (m.content || \"*attachment/embed*\")) | join(\"\\\\n\")}',\n },\n {\n action: 'send_message',\n channel: '${config.logging.channels?.messages || config.logging.channel}',\n embed: {\n title: 'Bulk Messages Deleted',\n description: '${messages.length} messages were deleted in <#${channel.id}>',\n color: '#ed4245',\n timestamp: '${now()}',\n },\n files: [\n {\n attachment: '${Buffer.from(logContent)}',\n name: 'deleted-messages.txt',\n },\n ],\n },\n ],\n },\n // Member Join\n {\n event: 'member_join',\n condition: '${config.logging.events?.memberJoin !== false}',\n actions: [\n {\n action: 'set',\n key: 'accountAge',\n value: '${floor((now() - member.user.createdAt) / (1000 * 60 * 60 * 24))}',\n },\n {\n action: 'send_message',\n channel: '${config.logging.channels?.members || config.logging.channel}',\n embed: {\n title: 'Member Joined',\n description: '<@${member.id}> joined the server',\n color: '#57f287',\n thumbnail: '${member.user.avatarURL}',\n fields: [\n { name: 'Username', value: '${member.user.tag}', inline: true },\n { name: 'Account Age', value: '${accountAge} days', inline: true },\n { name: 'Member Count', value: '${guild.memberCount}', inline: true },\n ],\n footer: {\n text: 'User ID: ${member.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Member Leave\n {\n event: 'member_leave',\n condition: '${config.logging.events?.memberLeave !== false}',\n actions: [\n {\n action: 'set',\n key: 'roles',\n value: '${member.roles?.cache?.filter(r => r.id !== guild.id)?.map(r => r.name)?.join(\", \") || \"None\"}',\n },\n {\n action: 'send_message',\n channel: '${config.logging.channels?.members || config.logging.channel}',\n embed: {\n title: 'Member Left',\n description: '<@${member.id}> left the server',\n color: '#ed4245',\n thumbnail: '${member.user.avatarURL}',\n fields: [\n { name: 'Username', value: '${member.user.tag}', inline: true },\n { name: 'Roles', value: '${truncate(roles, 1024)}', inline: false },\n { name: 'Joined At', value: '${timestamp(member.joinedAt, \"R\")}', inline: true },\n ],\n footer: {\n text: 'User ID: ${member.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Member Update (roles, nickname)\n {\n event: 'member_update',\n condition: '${config.logging.events?.memberUpdate !== false}',\n actions: [\n // Role changes\n {\n action: 'flow_if',\n condition: '${oldMember.roles.cache.size !== newMember.roles.cache.size}',\n then: [\n {\n action: 'set',\n key: 'addedRoles',\n value: '${newMember.roles.cache.filter(r => !oldMember.roles.cache.has(r.id)).map(r => r.name).join(\", \")}',\n },\n {\n action: 'set',\n key: 'removedRoles',\n value: '${oldMember.roles.cache.filter(r => !newMember.roles.cache.has(r.id)).map(r => r.name).join(\", \")}',\n },\n {\n action: 'send_message',\n channel: '${config.logging.channels?.members || config.logging.channel}',\n embed: {\n title: 'Member Roles Updated',\n description: '<@${newMember.id}>\\'s roles were changed',\n color: '#5865f2',\n fields: [\n { name: 'Added Roles', value: '${addedRoles || \"None\"}', inline: true },\n { name: 'Removed Roles', value: '${removedRoles || \"None\"}', inline: true },\n ],\n footer: {\n text: 'User ID: ${newMember.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Nickname changes\n {\n action: 'flow_if',\n condition: '${oldMember.nickname !== newMember.nickname}',\n then: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.members || config.logging.channel}',\n embed: {\n title: 'Nickname Changed',\n description: '<@${newMember.id}>\\'s nickname was changed',\n color: '#5865f2',\n fields: [\n { name: 'Before', value: '${oldMember.nickname || oldMember.user.username}', inline: true },\n { name: 'After', value: '${newMember.nickname || newMember.user.username}', inline: true },\n ],\n footer: {\n text: 'User ID: ${newMember.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n ],\n },\n // Member Ban\n {\n event: 'member_ban',\n condition: '${config.logging.events?.memberBan !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.moderation || config.logging.channel}',\n embed: {\n title: 'Member Banned',\n description: '<@${user.id}> was banned',\n color: '#ed4245',\n thumbnail: '${user.avatarURL}',\n fields: [\n { name: 'Username', value: '${user.tag}', inline: true },\n { name: 'Reason', value: '${ban.reason || \"No reason provided\"}', inline: false },\n ],\n footer: {\n text: 'User ID: ${user.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Member Unban\n {\n event: 'member_unban',\n condition: '${config.logging.events?.memberUnban !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.moderation || config.logging.channel}',\n embed: {\n title: 'Member Unbanned',\n description: '<@${user.id}> was unbanned',\n color: '#57f287',\n thumbnail: '${user.avatarURL}',\n fields: [\n { name: 'Username', value: '${user.tag}', inline: true },\n ],\n footer: {\n text: 'User ID: ${user.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Voice Join\n {\n event: 'voice_join',\n condition: '${config.logging.events?.voiceJoin !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.voice || config.logging.channel}',\n embed: {\n title: 'Voice Channel Joined',\n description: '<@${member.id}> joined <#${channel.id}>',\n color: '#57f287',\n footer: {\n text: 'User ID: ${member.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Voice Leave\n {\n event: 'voice_leave',\n condition: '${config.logging.events?.voiceLeave !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.voice || config.logging.channel}',\n embed: {\n title: 'Voice Channel Left',\n description: '<@${member.id}> left <#${channel.id}>',\n color: '#ed4245',\n footer: {\n text: 'User ID: ${member.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Voice Move\n {\n event: 'voice_move',\n condition: '${config.logging.events?.voiceMove !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.voice || config.logging.channel}',\n embed: {\n title: 'Voice Channel Switch',\n description: '<@${member.id}> switched voice channels',\n color: '#5865f2',\n fields: [\n { name: 'From', value: '<#${oldChannel.id}>', inline: true },\n { name: 'To', value: '<#${newChannel.id}>', inline: true },\n ],\n footer: {\n text: 'User ID: ${member.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Channel Create\n {\n event: 'channel_create',\n condition: '${config.logging.events?.channelCreate !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.server || config.logging.channel}',\n embed: {\n title: 'Channel Created',\n description: '<#${channel.id}> was created',\n color: '#57f287',\n fields: [\n { name: 'Name', value: '${channel.name}', inline: true },\n { name: 'Type', value: '${channel.type}', inline: true },\n ],\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Channel Delete\n {\n event: 'channel_delete',\n condition: '${config.logging.events?.channelDelete !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.server || config.logging.channel}',\n embed: {\n title: 'Channel Deleted',\n description: '#${channel.name} was deleted',\n color: '#ed4245',\n fields: [\n { name: 'Type', value: '${channel.type}', inline: true },\n ],\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Role Create\n {\n event: 'role_create',\n condition: '${config.logging.events?.roleCreate !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.server || config.logging.channel}',\n embed: {\n title: 'Role Created',\n description: '${role.name} was created',\n color: '${role.hexColor || \"#57f287\"}',\n fields: [\n { name: 'Color', value: '${role.hexColor || \"None\"}', inline: true },\n { name: 'Hoisted', value: '${role.hoist ? \"Yes\" : \"No\"}', inline: true },\n { name: 'Mentionable', value: '${role.mentionable ? \"Yes\" : \"No\"}', inline: true },\n ],\n footer: {\n text: 'Role ID: ${role.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n // Role Delete\n {\n event: 'role_delete',\n condition: '${config.logging.events?.roleDelete !== false}',\n actions: [\n {\n action: 'send_message',\n channel: '${config.logging.channels?.server || config.logging.channel}',\n embed: {\n title: 'Role Deleted',\n description: '${role.name} was deleted',\n color: '#ed4245',\n footer: {\n text: 'Role ID: ${role.id}',\n },\n timestamp: '${now()}',\n },\n },\n ],\n },\n];\n\nexport const loggingCommands: CommandDefinition[] = [\n {\n name: 'logging',\n description: 'Logging configuration commands',\n subcommands: [\n {\n name: 'set-channel',\n description: 'Set the logging channel',\n options: [\n { name: 'channel', description: 'Channel for logs', type: 'channel', required: true },\n { name: 'category', description: 'Log category', type: 'string', required: false, choices: [\n { name: 'All', value: 'all' },\n { name: 'Messages', value: 'messages' },\n { name: 'Members', value: 'members' },\n { name: 'Voice', value: 'voice' },\n { name: 'Server', value: 'server' },\n { name: 'Moderation', value: 'moderation' },\n ]},\n ],\n actions: [\n {\n action: 'flow_if',\n condition: '${!args.category || args.category === \"all\"}',\n then: [\n {\n action: 'set',\n key: 'config.logging.channel',\n value: '${args.channel.id}',\n scope: 'guild',\n },\n ],\n else: [\n {\n action: 'set',\n key: 'config.logging.channels.${args.category}',\n value: '${args.channel.id}',\n scope: 'guild',\n },\n ],\n },\n {\n action: 'reply',\n content: 'Logging channel updated!',\n ephemeral: true,\n },\n ],\n },\n {\n name: 'toggle',\n description: 'Toggle a logging event',\n options: [\n { name: 'event', description: 'Event to toggle', type: 'string', required: true, choices: [\n { name: 'Message Delete', value: 'messageDelete' },\n { name: 'Message Edit', value: 'messageEdit' },\n { name: 'Member Join', value: 'memberJoin' },\n { name: 'Member Leave', value: 'memberLeave' },\n { name: 'Member Ban', value: 'memberBan' },\n { name: 'Voice Join', value: 'voiceJoin' },\n { name: 'Voice Leave', value: 'voiceLeave' },\n ]},\n { name: 'enabled', description: 'Enable or disable', type: 'boolean', required: true },\n ],\n actions: [\n {\n action: 'set',\n key: 'config.logging.events.${args.event}',\n value: '${args.enabled}',\n scope: 'guild',\n },\n {\n action: 'reply',\n content: '${args.event} logging ${args.enabled ? \"enabled\" : \"disabled\"}!',\n ephemeral: true,\n },\n ],\n },\n {\n name: 'ignore-channel',\n description: 'Ignore a channel from logging',\n options: [\n { name: 'channel', description: 'Channel to ignore', type: 'channel', required: true },\n ],\n actions: [\n {\n action: 'list_push',\n key: 'config.logging.ignoredChannels',\n value: '${args.channel.id}',\n scope: 'guild',\n },\n {\n action: 'reply',\n content: '${args.channel} will now be ignored from logs.',\n ephemeral: true,\n },\n ],\n },\n ],\n },\n];\n\nexport function getLoggingSpec(config: LoggingConfig = {}): Partial<FurlowSpec> {\n return {\n events: loggingEventHandlers,\n commands: loggingCommands,\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,83 @@
1
+ import { FurlowSpec, CommandDefinition } from '@furlow/schema';
2
+
3
+ /**
4
+ * Moderation builtin module
5
+ */
6
+
7
+ interface ModerationConfig {
8
+ /** Log channel for moderation actions */
9
+ logChannel?: string;
10
+ /** Whether to DM users on moderation actions */
11
+ dmOnAction?: boolean;
12
+ /** Roles exempt from moderation */
13
+ exemptRoles?: string[];
14
+ /** Enable warning system */
15
+ warnings?: {
16
+ enabled?: boolean;
17
+ maxWarnings?: number;
18
+ escalation?: Array<{
19
+ count: number;
20
+ action: 'kick' | 'ban' | 'timeout';
21
+ duration?: string;
22
+ }>;
23
+ };
24
+ }
25
+ declare const moderationCommands: CommandDefinition[];
26
+ declare const moderationTables: {
27
+ warnings: {
28
+ columns: {
29
+ id: {
30
+ type: "number";
31
+ primary: boolean;
32
+ };
33
+ user_id: {
34
+ type: "string";
35
+ index: boolean;
36
+ };
37
+ guild_id: {
38
+ type: "string";
39
+ index: boolean;
40
+ };
41
+ moderator_id: {
42
+ type: "string";
43
+ };
44
+ reason: {
45
+ type: "string";
46
+ };
47
+ created_at: {
48
+ type: "timestamp";
49
+ };
50
+ };
51
+ };
52
+ mod_cases: {
53
+ columns: {
54
+ id: {
55
+ type: "number";
56
+ primary: boolean;
57
+ };
58
+ guild_id: {
59
+ type: "string";
60
+ index: boolean;
61
+ };
62
+ user_id: {
63
+ type: "string";
64
+ index: boolean;
65
+ };
66
+ moderator_id: {
67
+ type: "string";
68
+ };
69
+ action: {
70
+ type: "string";
71
+ };
72
+ reason: {
73
+ type: "string";
74
+ };
75
+ created_at: {
76
+ type: "timestamp";
77
+ };
78
+ };
79
+ };
80
+ };
81
+ declare function getModerationSpec(config?: ModerationConfig): Partial<FurlowSpec>;
82
+
83
+ export { type ModerationConfig, getModerationSpec, moderationCommands, moderationTables };