@helyx/module-account-gate 1.0.1

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 (40) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +725 -0
  3. package/README.md +90 -0
  4. package/dist/challenges.d.ts +16 -0
  5. package/dist/challenges.js +233 -0
  6. package/dist/configuration.d.ts +41 -0
  7. package/dist/configuration.js +224 -0
  8. package/dist/contracts.d.ts +82 -0
  9. package/dist/contracts.js +56 -0
  10. package/dist/enforcement.d.ts +19 -0
  11. package/dist/enforcement.js +110 -0
  12. package/dist/index.d.ts +27 -0
  13. package/dist/index.js +3324 -0
  14. package/dist/managed-resource-summary.d.ts +3 -0
  15. package/dist/managed-resource-summary.js +6 -0
  16. package/dist/member-resource.d.ts +3 -0
  17. package/dist/member-resource.js +348 -0
  18. package/dist/panel-resource.d.ts +15 -0
  19. package/dist/panel-resource.js +527 -0
  20. package/dist/password-entry.d.ts +8 -0
  21. package/dist/password-entry.js +59 -0
  22. package/dist/password-resource.d.ts +8 -0
  23. package/dist/password-resource.js +208 -0
  24. package/dist/privacy.d.ts +4 -0
  25. package/dist/privacy.js +20 -0
  26. package/dist/public-channel-resource.d.ts +4 -0
  27. package/dist/public-channel-resource.js +135 -0
  28. package/dist/question-resource.d.ts +3 -0
  29. package/dist/question-resource.js +246 -0
  30. package/dist/records.d.ts +508 -0
  31. package/dist/records.js +456 -0
  32. package/dist/workflow.d.ts +43 -0
  33. package/dist/workflow.js +167 -0
  34. package/manifest.json +750 -0
  35. package/migrations/0001_account_gate_foundation.sql +303 -0
  36. package/migrations/0002_account_gate_panel_message.sql +27 -0
  37. package/migrations/0003_account_gate_revoked_member_status.sql +17 -0
  38. package/migrations/0004_account_gate_multiple_panels.sql +23 -0
  39. package/migrations/0005_account_gate_panel_passwords.sql +45 -0
  40. package/package.json +54 -0
package/manifest.json ADDED
@@ -0,0 +1,750 @@
1
+ {
2
+ "manifestVersion": "0.2",
3
+ "releaseStatus": "live",
4
+ "id": "helyx.account-gate",
5
+ "name": "Access Control",
6
+ "version": "1.0.1",
7
+ "description": "Require new members to complete configurable Discord interaction checks before gaining access.",
8
+ "entry": "./dist/index.js",
9
+ "framework": "^0.1.0",
10
+ "dependencies": [],
11
+ "permissions": [
12
+ "ADD_REACTIONS",
13
+ "EMBED_LINKS",
14
+ "KICK_MEMBERS",
15
+ "MANAGE_MESSAGES",
16
+ "MANAGE_ROLES",
17
+ "READ_MESSAGE_HISTORY",
18
+ "SEND_MESSAGES",
19
+ "VIEW_CHANNEL"
20
+ ],
21
+ "privacy": {
22
+ "containsPersonalData": true,
23
+ "providerVersion": 1,
24
+ "collections": [
25
+ {
26
+ "name": "question_creators",
27
+ "createdAtField": "created_at",
28
+ "subjectFields": [
29
+ {
30
+ "field": "creator_user_id",
31
+ "role": "question-creator",
32
+ "erasure": "delete-record"
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ "name": "attempts",
38
+ "createdAtField": "created_at",
39
+ "subjectFields": [
40
+ {
41
+ "field": "member_user_id",
42
+ "role": "member",
43
+ "erasure": "delete-record"
44
+ }
45
+ ]
46
+ },
47
+ {
48
+ "name": "member_summaries",
49
+ "createdAtField": "created_at",
50
+ "subjectFields": [
51
+ {
52
+ "field": "member_user_id",
53
+ "role": "member",
54
+ "erasure": "delete-record"
55
+ }
56
+ ]
57
+ },
58
+ {
59
+ "name": "reviews",
60
+ "createdAtField": "created_at",
61
+ "subjectFields": [
62
+ {
63
+ "field": "member_user_id",
64
+ "role": "reviewed-member",
65
+ "erasure": "delete-record"
66
+ },
67
+ {
68
+ "field": "decided_by_user_id",
69
+ "role": "staff-decision-actor",
70
+ "erasure": "set-null"
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ "name": "terminal_finalizations",
76
+ "createdAtField": "created_at",
77
+ "subjectFields": [
78
+ {
79
+ "field": "member_user_id",
80
+ "role": "member",
81
+ "erasure": "delete-record"
82
+ }
83
+ ]
84
+ },
85
+ {
86
+ "name": "role_transitions",
87
+ "createdAtField": "created_at",
88
+ "subjectFields": [
89
+ {
90
+ "field": "member_user_id",
91
+ "role": "member",
92
+ "erasure": "delete-record"
93
+ }
94
+ ]
95
+ },
96
+ {
97
+ "name": "strict_modes",
98
+ "createdAtField": "created_at",
99
+ "subjectFields": [
100
+ {
101
+ "field": "activated_by_user_id",
102
+ "role": "strict-mode-actor",
103
+ "erasure": "set-null"
104
+ }
105
+ ]
106
+ },
107
+ {
108
+ "name": "privacy_suppressions",
109
+ "createdAtField": "created_at",
110
+ "subjectFields": [
111
+ {
112
+ "field": "member_user_id",
113
+ "role": "privacy-suppression",
114
+ "erasure": "retain"
115
+ }
116
+ ]
117
+ }
118
+ ]
119
+ },
120
+ "dashboard": {
121
+ "category": "safety",
122
+ "icon": "shield-check",
123
+ "settings": [
124
+ {
125
+ "key": "accessType",
126
+ "type": "select",
127
+ "label": "Access type",
128
+ "description": "Select the type of access panel you want to configure.",
129
+ "group": "Access type",
130
+ "required": true,
131
+ "supportVisibility": "value",
132
+ "options": [
133
+ {
134
+ "value": "challenges",
135
+ "label": "Challenges"
136
+ },
137
+ {
138
+ "value": "password",
139
+ "label": "Password",
140
+ "requiredDiscordCapability": "message-content"
141
+ },
142
+ {
143
+ "value": "emoji",
144
+ "label": "Emoji"
145
+ }
146
+ ],
147
+ "default": "challenges"
148
+ },
149
+ {
150
+ "key": "gateChannelId",
151
+ "type": "discord-channel",
152
+ "label": "Gate channel",
153
+ "description": "Select the channel where the access panel will be posted.",
154
+ "group": "Discord access",
155
+ "required": true,
156
+ "supportVisibility": "value",
157
+ "channelTypes": ["guild_text"]
158
+ },
159
+ {
160
+ "key": "verifiedRoleId",
161
+ "type": "discord-role",
162
+ "label": "Access role",
163
+ "description": "Role added only after the complete configured gate succeeds.",
164
+ "group": "Discord access",
165
+ "required": true,
166
+ "supportVisibility": "value",
167
+ "multiple": false
168
+ },
169
+ {
170
+ "key": "temporaryRoleIds",
171
+ "type": "discord-role",
172
+ "label": "Temporary roles",
173
+ "description": "Roles removed after Helyx has added the access role.",
174
+ "group": "Discord access",
175
+ "required": false,
176
+ "supportVisibility": "value",
177
+ "multiple": true
178
+ },
179
+ {
180
+ "key": "reviewChannelId",
181
+ "type": "discord-channel",
182
+ "label": "Staff review channel",
183
+ "description": "Private channel that receives checks requiring a staff decision.",
184
+ "group": "Staff review",
185
+ "required": false,
186
+ "supportVisibility": "value",
187
+ "channelTypes": ["guild_text"]
188
+ },
189
+ {
190
+ "key": "preset",
191
+ "type": "select",
192
+ "label": "Challenge preset",
193
+ "description": "Standard uses two different generated challenges.",
194
+ "group": "Challenges",
195
+ "required": true,
196
+ "supportVisibility": "value",
197
+ "visibleWhen": {
198
+ "field": "accessType",
199
+ "equals": "challenges"
200
+ },
201
+ "options": [
202
+ {
203
+ "value": "light",
204
+ "label": "Light"
205
+ },
206
+ {
207
+ "value": "standard",
208
+ "label": "Standard"
209
+ },
210
+ {
211
+ "value": "strict",
212
+ "label": "Strict"
213
+ },
214
+ {
215
+ "value": "custom",
216
+ "label": "Custom"
217
+ }
218
+ ],
219
+ "default": "standard"
220
+ },
221
+ {
222
+ "key": "allocationMode",
223
+ "type": "select",
224
+ "label": "Allocation mode",
225
+ "description": "Choose random, fixed or local adaptive challenge allocation.",
226
+ "group": "Challenges",
227
+ "required": true,
228
+ "supportVisibility": "value",
229
+ "visibleWhen": {
230
+ "field": "accessType",
231
+ "equals": "challenges"
232
+ },
233
+ "options": [
234
+ {
235
+ "value": "random_one",
236
+ "label": "Random one"
237
+ },
238
+ {
239
+ "value": "random_chain",
240
+ "label": "Random chain"
241
+ },
242
+ {
243
+ "value": "fixed_chain",
244
+ "label": "Fixed chain"
245
+ },
246
+ {
247
+ "value": "adaptive_chain",
248
+ "label": "Adaptive chain"
249
+ }
250
+ ],
251
+ "default": "random_chain"
252
+ },
253
+ {
254
+ "key": "enabledChallengeTypes",
255
+ "type": "string",
256
+ "label": "Enabled challenge types",
257
+ "description": "Comma-separated challenge IDs. Static gates are not randomly allocated.",
258
+ "group": "Challenges",
259
+ "required": true,
260
+ "supportVisibility": "value",
261
+ "visibleWhen": {
262
+ "field": "accessType",
263
+ "equals": "challenges"
264
+ },
265
+ "minLength": 0,
266
+ "maxLength": 300,
267
+ "default": "quick_sum,button_sequence,number_order,symbol_match,modal_recall"
268
+ },
269
+ {
270
+ "key": "fixedChallengeChain",
271
+ "type": "string",
272
+ "label": "Fixed challenge chain",
273
+ "description": "Comma-separated enabled challenge IDs used only in fixed-chain mode.",
274
+ "group": "Challenges",
275
+ "required": false,
276
+ "supportVisibility": "value",
277
+ "visibleWhen": {
278
+ "field": "accessType",
279
+ "equals": "challenges"
280
+ },
281
+ "minLength": 0,
282
+ "maxLength": 300,
283
+ "default": ""
284
+ },
285
+ {
286
+ "key": "challengeCount",
287
+ "type": "integer",
288
+ "label": "Challenge count",
289
+ "description": "Routine checks should use no more than three challenges.",
290
+ "group": "Challenges",
291
+ "required": true,
292
+ "supportVisibility": "value",
293
+ "visibleWhen": {
294
+ "field": "accessType",
295
+ "equals": "challenges"
296
+ },
297
+ "minimum": 1,
298
+ "maximum": 4,
299
+ "default": 2
300
+ },
301
+ {
302
+ "key": "attempts",
303
+ "type": "integer",
304
+ "label": "Attempts",
305
+ "description": "Number of complete check attempts before final failure.",
306
+ "group": "Timing and attempts",
307
+ "required": true,
308
+ "supportVisibility": "value",
309
+ "minimum": 1,
310
+ "maximum": 10,
311
+ "default": 3
312
+ },
313
+ {
314
+ "key": "sessionExpirySeconds",
315
+ "type": "integer",
316
+ "label": "Session expiry",
317
+ "description": "Seconds before an unfinished interaction session expires.",
318
+ "group": "Timing and attempts",
319
+ "required": true,
320
+ "supportVisibility": "value",
321
+ "minimum": 60,
322
+ "maximum": 600,
323
+ "default": 180
324
+ },
325
+ {
326
+ "key": "retryCooldownSeconds",
327
+ "type": "integer",
328
+ "label": "Retry cooldown",
329
+ "description": "Seconds before a failed member may start another attempt.",
330
+ "group": "Timing and attempts",
331
+ "required": true,
332
+ "supportVisibility": "value",
333
+ "minimum": 0,
334
+ "maximum": 600,
335
+ "default": 30
336
+ },
337
+ {
338
+ "key": "joinDeadlineSeconds",
339
+ "type": "integer",
340
+ "label": "Join deadline",
341
+ "description": "Seconds a joining member has to complete Access Control.",
342
+ "group": "Timing and attempts",
343
+ "required": true,
344
+ "supportVisibility": "value",
345
+ "minimum": 300,
346
+ "maximum": 3600,
347
+ "default": 900
348
+ },
349
+ {
350
+ "key": "failureAction",
351
+ "type": "select",
352
+ "label": "Final failure action",
353
+ "description": "Keep restricted, request staff review or send a neutral direct message and kick.",
354
+ "group": "Final failure",
355
+ "required": true,
356
+ "supportVisibility": "value",
357
+ "options": [
358
+ {
359
+ "value": "restricted",
360
+ "label": "Keep restricted"
361
+ },
362
+ {
363
+ "value": "review",
364
+ "label": "Staff review"
365
+ },
366
+ {
367
+ "value": "kick",
368
+ "label": "Kick"
369
+ }
370
+ ],
371
+ "default": "review"
372
+ },
373
+ {
374
+ "key": "strictModeDurationMinutes",
375
+ "type": "integer",
376
+ "label": "Strict-mode duration",
377
+ "description": "Temporary strict mode expires automatically after 5 to 60 minutes.",
378
+ "group": "Temporary strict mode",
379
+ "required": true,
380
+ "supportVisibility": "value",
381
+ "minimum": 5,
382
+ "maximum": 60,
383
+ "default": 15
384
+ },
385
+ {
386
+ "key": "minimumAccountAgeDays",
387
+ "type": "integer",
388
+ "label": "Minimum account age",
389
+ "description": "Minimum Discord account age in days; zero disables this local rule.",
390
+ "group": "Local account rules",
391
+ "required": true,
392
+ "supportVisibility": "value",
393
+ "minimum": 0,
394
+ "maximum": 3650,
395
+ "default": 0
396
+ },
397
+ {
398
+ "key": "reverifyReturningMembers",
399
+ "type": "boolean",
400
+ "label": "Recheck returning members",
401
+ "description": "Require returning members to complete Access Control again.",
402
+ "group": "Returning members",
403
+ "required": true,
404
+ "supportVisibility": "value",
405
+ "default": false
406
+ },
407
+ {
408
+ "key": "restoreVerifiedMembers",
409
+ "type": "boolean",
410
+ "label": "Restore previous access",
411
+ "description": "Restore the access role for previously successful returning members.",
412
+ "group": "Returning members",
413
+ "required": true,
414
+ "supportVisibility": "value",
415
+ "default": true
416
+ },
417
+ {
418
+ "key": "passwordChannelId",
419
+ "type": "discord-channel",
420
+ "label": "Password Entry channel",
421
+ "description": "Channel for a shared gate phrase; Message Content and Manage Messages are required.",
422
+ "group": "Password Entry",
423
+ "required": true,
424
+ "supportVisibility": "value",
425
+ "visibleWhen": {
426
+ "field": "accessType",
427
+ "equals": "password"
428
+ },
429
+ "channelTypes": ["guild_text"]
430
+ },
431
+ {
432
+ "key": "passwordIgnoreCase",
433
+ "type": "boolean",
434
+ "label": "Ignore letter case",
435
+ "description": "Compare each panel password without letter-case differences.",
436
+ "group": "Password Entry",
437
+ "required": true,
438
+ "supportVisibility": "value",
439
+ "visibleWhen": {
440
+ "field": "accessType",
441
+ "equals": "password"
442
+ },
443
+ "default": true
444
+ },
445
+ {
446
+ "key": "passwordTrimWhitespace",
447
+ "type": "boolean",
448
+ "label": "Ignore surrounding spaces",
449
+ "description": "Ignore leading and trailing spaces in each panel password.",
450
+ "group": "Password Entry",
451
+ "required": true,
452
+ "supportVisibility": "value",
453
+ "visibleWhen": {
454
+ "field": "accessType",
455
+ "equals": "password"
456
+ },
457
+ "default": true
458
+ },
459
+ {
460
+ "key": "emojiChannelId",
461
+ "type": "discord-channel",
462
+ "label": "Emoji Entry channel",
463
+ "description": "Channel containing the exact configured reaction message.",
464
+ "group": "Emoji Entry",
465
+ "required": true,
466
+ "supportVisibility": "value",
467
+ "visibleWhen": {
468
+ "field": "accessType",
469
+ "equals": "emoji"
470
+ },
471
+ "channelTypes": ["guild_text", "guild_announcement"]
472
+ },
473
+ {
474
+ "key": "emojiMessageId",
475
+ "type": "string",
476
+ "label": "Emoji Entry message ID",
477
+ "description": "Exact Discord message ID validated during setup.",
478
+ "group": "Emoji Entry",
479
+ "required": true,
480
+ "supportVisibility": "value",
481
+ "visibleWhen": {
482
+ "field": "accessType",
483
+ "equals": "emoji"
484
+ },
485
+ "minLength": 0,
486
+ "maxLength": 20,
487
+ "default": ""
488
+ },
489
+ {
490
+ "key": "emojiIdentifier",
491
+ "type": "string",
492
+ "label": "Emoji Entry emoji",
493
+ "description": "Exact Unicode or accessible server emoji used on the configured message.",
494
+ "group": "Emoji Entry",
495
+ "required": true,
496
+ "supportVisibility": "value",
497
+ "visibleWhen": {
498
+ "field": "accessType",
499
+ "equals": "emoji"
500
+ },
501
+ "minLength": 0,
502
+ "maxLength": 100,
503
+ "default": "",
504
+ "display": "emoji"
505
+ }
506
+ ],
507
+ "actions": [
508
+ {
509
+ "id": "activate-strict-mode",
510
+ "label": "Temporary strict mode",
511
+ "description": "Add one generated challenge temporarily, without changing attempts or failure actions.",
512
+ "buttonLabel": "Activate strict mode",
513
+ "style": "danger"
514
+ }
515
+ ],
516
+ "resources": [
517
+ {
518
+ "id": "gate-panel",
519
+ "name": "Gate panels",
520
+ "singularName": "Gate panel",
521
+ "description": "Edit, repair, repost or remove each published Access Control panel. Password Entry passwords belong to their individual panel.",
522
+ "columns": [
523
+ {
524
+ "key": "channelId",
525
+ "label": "Channel"
526
+ },
527
+ {
528
+ "key": "messageId",
529
+ "label": "Message"
530
+ }
531
+ ],
532
+ "operations": [
533
+ "list",
534
+ "read",
535
+ "preview",
536
+ "create",
537
+ "update",
538
+ "delete",
539
+ "action"
540
+ ],
541
+ "creationIntents": ["publish"],
542
+ "publicationMode": "validate_on_publish",
543
+ "editableFields": [
544
+ {
545
+ "statuses": ["posted", "missing"],
546
+ "fields": ["messageBody", "replacementPhrase"]
547
+ }
548
+ ],
549
+ "actions": [
550
+ {
551
+ "id": "repair",
552
+ "label": "Repair panel",
553
+ "description": "Restore the saved panel message in place, or publish a replacement when it is missing.",
554
+ "style": "secondary"
555
+ },
556
+ {
557
+ "id": "repost",
558
+ "label": "Repost panel",
559
+ "description": "Publish a replacement panel message and retire the previous message.",
560
+ "style": "secondary",
561
+ "confirmation": "Repost the Access Control panel and replace its current Discord message?"
562
+ }
563
+ ],
564
+ "fields": [
565
+ {
566
+ "key": "accessType",
567
+ "type": "select",
568
+ "label": "Access type",
569
+ "description": "The access type captured when this gate was published.",
570
+ "required": true,
571
+ "options": [
572
+ {
573
+ "value": "challenges",
574
+ "label": "Challenges"
575
+ },
576
+ {
577
+ "value": "password",
578
+ "label": "Password"
579
+ },
580
+ {
581
+ "value": "emoji",
582
+ "label": "Emoji"
583
+ }
584
+ ],
585
+ "default": "challenges"
586
+ },
587
+ {
588
+ "key": "messageBody",
589
+ "type": "string",
590
+ "label": "Message",
591
+ "description": "Instructions shown to members. Challenge and Password panels add a Start check button; Emoji panels remain instruction-only.",
592
+ "required": true,
593
+ "minLength": 1,
594
+ "maxLength": 1000,
595
+ "default": "Complete a short human-interaction check to access the server. Press the button below when you are ready.",
596
+ "multiline": true,
597
+ "group": "Message"
598
+ },
599
+ {
600
+ "key": "replacementPhrase",
601
+ "type": "string",
602
+ "label": "Password",
603
+ "description": "Enter a replacement password only when you want to change it. Helyx stores a one-way hash and cannot display it again.",
604
+ "required": false,
605
+ "minLength": 4,
606
+ "maxLength": 200,
607
+ "group": "Password Entry",
608
+ "visibleWhen": {
609
+ "field": "accessType",
610
+ "equals": "password"
611
+ }
612
+ }
613
+ ]
614
+ },
615
+ {
616
+ "id": "members",
617
+ "name": "Members",
618
+ "singularName": "Member",
619
+ "description": "Members known to Access Control, with live Discord identity and access state.",
620
+ "columns": [
621
+ {
622
+ "key": "memberUserId",
623
+ "label": "User ID"
624
+ },
625
+ {
626
+ "key": "displayName",
627
+ "label": "Display name"
628
+ },
629
+ {
630
+ "key": "avatarUrl",
631
+ "label": "Avatar"
632
+ },
633
+ {
634
+ "key": "memberPresent",
635
+ "label": "Server member"
636
+ },
637
+ {
638
+ "key": "completedAt",
639
+ "label": "Access granted"
640
+ }
641
+ ],
642
+ "operations": ["list", "action"],
643
+ "actions": [
644
+ {
645
+ "id": "revoke",
646
+ "permissionId": "account-gate.manage",
647
+ "label": "Revoke access",
648
+ "description": "Remove the configured access role and mark this Access Control member as revoked.",
649
+ "style": "danger",
650
+ "confirmation": "Revoke this member's Access Control access?",
651
+ "statuses": ["passed"]
652
+ }
653
+ ],
654
+ "query": {
655
+ "search": {
656
+ "label": "Search members",
657
+ "placeholder": "Current Discord display name or user ID"
658
+ }
659
+ },
660
+ "fields": [
661
+ {
662
+ "key": "memberUserId",
663
+ "type": "string",
664
+ "label": "Discord user ID",
665
+ "description": "The Discord user ID held by Access Control.",
666
+ "required": true,
667
+ "minLength": 17,
668
+ "maxLength": 20
669
+ }
670
+ ]
671
+ },
672
+ {
673
+ "id": "server-questions",
674
+ "name": "Server questions",
675
+ "singularName": "Server question",
676
+ "description": "Create simple server-rule questions with one correct answer.",
677
+ "columns": [
678
+ {
679
+ "key": "status",
680
+ "label": "State"
681
+ },
682
+ {
683
+ "key": "updatedAt",
684
+ "label": "Last changed"
685
+ }
686
+ ],
687
+ "operations": ["list", "read", "preview", "create", "update", "delete"],
688
+ "creationIntents": ["draft", "publish"],
689
+ "publicationMode": "preview_confirm",
690
+ "fields": [
691
+ {
692
+ "key": "question",
693
+ "type": "string",
694
+ "label": "Question",
695
+ "description": "Short server-rule or community-expectation question.",
696
+ "required": true,
697
+ "group": "Question",
698
+ "minLength": 1,
699
+ "maxLength": 200
700
+ },
701
+ {
702
+ "key": "correctAnswer",
703
+ "type": "string",
704
+ "label": "Correct answer",
705
+ "description": "The one answer Helyx accepts.",
706
+ "required": true,
707
+ "group": "Answers",
708
+ "minLength": 1,
709
+ "maxLength": 80
710
+ },
711
+ {
712
+ "key": "incorrectAnswers",
713
+ "type": "string",
714
+ "label": "Incorrect answers",
715
+ "description": "Enter two to four incorrect answers, one per line.",
716
+ "required": true,
717
+ "group": "Answers",
718
+ "minLength": 3,
719
+ "maxLength": 323
720
+ },
721
+ {
722
+ "key": "enabled",
723
+ "type": "boolean",
724
+ "label": "Enabled",
725
+ "description": "Allow this question to be selected for new checks.",
726
+ "required": true,
727
+ "group": "Availability",
728
+ "default": true
729
+ }
730
+ ]
731
+ }
732
+ ]
733
+ },
734
+ "contributions": {
735
+ "commands": ["access-control"],
736
+ "events": [
737
+ "discord.guild-member-add",
738
+ "discord.guild-member-remove",
739
+ "discord.message-reaction-add",
740
+ "discord.privileged-message-create"
741
+ ],
742
+ "logs": [
743
+ "account-gate-completed",
744
+ "account-gate-review-created",
745
+ "account-gate-kicked",
746
+ "account-gate-strict-mode-changed",
747
+ "account-gate-resume-notice"
748
+ ]
749
+ }
750
+ }