tangled
alpha
login
or
join now
folospior.dev
/
grom
0
fork
atom
A Discord API Library for Gleam! 💫
0
fork
atom
overview
issues
pulls
pipelines
auto moderation revamp
folospior.dev
9 months ago
a58558eb
d9f14c39
+549
-701
6 changed files
expand all
collapse all
unified
split
src
grom
guild
auto_moderation
action.gleam
event.gleam
keyword_preset.gleam
rule.gleam
trigger.gleam
auto_moderation.gleam
+549
src/grom/guild/auto_moderation.gleam
···
1
1
+
import gleam/dynamic/decode
2
2
+
import gleam/http
3
3
+
import gleam/http/request
4
4
+
import gleam/json.{type Json}
5
5
+
import gleam/list
6
6
+
import gleam/option.{type Option, None, Some}
7
7
+
import gleam/result
8
8
+
import gleam/time/duration.{type Duration}
9
9
+
import grom/client.{type Client}
10
10
+
import grom/error.{type Error}
11
11
+
import grom/internal/rest
12
12
+
import grom/internal/time_duration
13
13
+
14
14
+
// TYPES -----------------------------------------------------------------------
15
15
+
16
16
+
pub type Rule {
17
17
+
Rule(
18
18
+
id: String,
19
19
+
guild_id: String,
20
20
+
name: String,
21
21
+
creator_id: String,
22
22
+
trigger: Trigger,
23
23
+
actions: List(Action),
24
24
+
is_enabled: Bool,
25
25
+
exempt_role_ids: List(String),
26
26
+
exempt_channel_ids: List(String),
27
27
+
)
28
28
+
}
29
29
+
30
30
+
pub type Trigger {
31
31
+
KeywordTrigger(
32
32
+
keyword_filter: List(String),
33
33
+
regex_patterns: List(String),
34
34
+
allow_list: List(String),
35
35
+
)
36
36
+
MemberProfileTrigger(
37
37
+
keyword_filter: List(String),
38
38
+
regex_patterns: List(String),
39
39
+
allow_list: List(String),
40
40
+
)
41
41
+
KeywordPresetTrigger(presets: List(KeywordPreset), allow_list: List(String))
42
42
+
MentionSpamTrigger(
43
43
+
total_mention_limit: Int,
44
44
+
is_mention_raid_protection_enabled: Bool,
45
45
+
)
46
46
+
SpamTrigger
47
47
+
}
48
48
+
49
49
+
pub type KeywordPreset {
50
50
+
ProfanityPreset
51
51
+
SexualContentPreset
52
52
+
SlursPreset
53
53
+
}
54
54
+
55
55
+
pub type Action {
56
56
+
BlockMessage(custom_message: Option(String))
57
57
+
SendAlertMessage(channel_id: String)
58
58
+
TimeoutMember(duration: Duration)
59
59
+
BlockMemberInteraction
60
60
+
}
61
61
+
62
62
+
pub opaque type CreateRule {
63
63
+
CreateRule(
64
64
+
name: String,
65
65
+
trigger: Trigger,
66
66
+
actions: List(Action),
67
67
+
is_enabled: Bool,
68
68
+
exempt_role_ids: Option(List(String)),
69
69
+
exempt_channel_ids: Option(List(String)),
70
70
+
)
71
71
+
}
72
72
+
73
73
+
pub opaque type ModifyRule {
74
74
+
ModifyRule(
75
75
+
name: Option(String),
76
76
+
/// You can only modify the inner data, you _can't_ change the trigger.
77
77
+
trigger: Option(Trigger),
78
78
+
actions: Option(List(Action)),
79
79
+
is_enabled: Option(Bool),
80
80
+
exempt_role_ids: Option(List(String)),
81
81
+
exempt_channel_ids: Option(List(String)),
82
82
+
)
83
83
+
}
84
84
+
85
85
+
// DECODERS --------------------------------------------------------------------
86
86
+
87
87
+
@internal
88
88
+
pub fn rule_decoder() -> decode.Decoder(Rule) {
89
89
+
use id <- decode.field("id", decode.string)
90
90
+
use guild_id <- decode.field("guild_id", decode.string)
91
91
+
use name <- decode.field("name", decode.string)
92
92
+
use creator_id <- decode.field("creator_id", decode.string)
93
93
+
use trigger_type <- decode.field("trigger_type", decode.int)
94
94
+
use trigger <- decode.field("trigger_metadata", trigger_decoder(trigger_type))
95
95
+
use actions <- decode.field("actions", decode.list(action_decoder()))
96
96
+
use is_enabled <- decode.field("enabled", decode.bool)
97
97
+
use exempt_role_ids <- decode.field(
98
98
+
"exempt_roles",
99
99
+
decode.list(decode.string),
100
100
+
)
101
101
+
use exempt_channel_ids <- decode.field(
102
102
+
"exempt_channels",
103
103
+
decode.list(decode.string),
104
104
+
)
105
105
+
106
106
+
decode.success(Rule(
107
107
+
id:,
108
108
+
guild_id:,
109
109
+
name:,
110
110
+
creator_id:,
111
111
+
trigger:,
112
112
+
actions:,
113
113
+
is_enabled:,
114
114
+
exempt_role_ids:,
115
115
+
exempt_channel_ids:,
116
116
+
))
117
117
+
}
118
118
+
119
119
+
pub fn trigger_decoder(trigger_type: Int) -> decode.Decoder(Trigger) {
120
120
+
case trigger_type {
121
121
+
1 | 6 -> {
122
122
+
use keyword_filter <- decode.field(
123
123
+
"keyword_filter",
124
124
+
decode.list(decode.string),
125
125
+
)
126
126
+
use regex_patterns <- decode.field(
127
127
+
"regex_patterns",
128
128
+
decode.list(decode.string),
129
129
+
)
130
130
+
use allow_list <- decode.field("allow_list", decode.list(decode.string))
131
131
+
132
132
+
case trigger_type {
133
133
+
1 ->
134
134
+
decode.success(KeywordTrigger(
135
135
+
keyword_filter:,
136
136
+
regex_patterns:,
137
137
+
allow_list:,
138
138
+
))
139
139
+
6 ->
140
140
+
decode.success(MemberProfileTrigger(
141
141
+
keyword_filter:,
142
142
+
regex_patterns:,
143
143
+
allow_list:,
144
144
+
))
145
145
+
_ -> decode.failure(KeywordTrigger([], [], []), "Trigger")
146
146
+
}
147
147
+
}
148
148
+
3 -> decode.success(SpamTrigger)
149
149
+
4 -> {
150
150
+
use presets <- decode.field(
151
151
+
"presets",
152
152
+
decode.list(keyword_preset_decoder()),
153
153
+
)
154
154
+
use allow_list <- decode.field("allow_list", decode.list(decode.string))
155
155
+
156
156
+
decode.success(KeywordPresetTrigger(presets:, allow_list:))
157
157
+
}
158
158
+
5 -> {
159
159
+
use total_mention_limit <- decode.field("mention_total_limit", decode.int)
160
160
+
use is_mention_raid_protection_enabled <- decode.field(
161
161
+
"mention_raid_protection_enabled",
162
162
+
decode.bool,
163
163
+
)
164
164
+
165
165
+
decode.success(MentionSpamTrigger(
166
166
+
total_mention_limit:,
167
167
+
is_mention_raid_protection_enabled:,
168
168
+
))
169
169
+
}
170
170
+
_ -> decode.failure(SpamTrigger, "Trigger")
171
171
+
}
172
172
+
}
173
173
+
174
174
+
@internal
175
175
+
pub fn keyword_preset_decoder() -> decode.Decoder(KeywordPreset) {
176
176
+
use variant <- decode.then(decode.int)
177
177
+
case variant {
178
178
+
1 -> decode.success(ProfanityPreset)
179
179
+
2 -> decode.success(SexualContentPreset)
180
180
+
3 -> decode.success(SlursPreset)
181
181
+
_ -> decode.failure(ProfanityPreset, "KeywordPreset")
182
182
+
}
183
183
+
}
184
184
+
185
185
+
@internal
186
186
+
pub fn action_decoder() -> decode.Decoder(Action) {
187
187
+
use type_ <- decode.field("type", decode.int)
188
188
+
use action <- decode.field("metadata", case type_ {
189
189
+
1 -> {
190
190
+
use custom_message <- decode.optional_field(
191
191
+
"custom_message",
192
192
+
None,
193
193
+
decode.optional(decode.string),
194
194
+
)
195
195
+
decode.success(BlockMessage(custom_message:))
196
196
+
}
197
197
+
2 -> {
198
198
+
use channel_id <- decode.field("channel_id", decode.string)
199
199
+
decode.success(SendAlertMessage(channel_id:))
200
200
+
}
201
201
+
3 -> {
202
202
+
use duration <- decode.field(
203
203
+
"duration_seconds",
204
204
+
time_duration.from_int_seconds_decoder(),
205
205
+
)
206
206
+
decode.success(TimeoutMember(duration:))
207
207
+
}
208
208
+
4 -> decode.success(BlockMemberInteraction)
209
209
+
_ -> decode.failure(BlockMessage(None), "Action")
210
210
+
})
211
211
+
212
212
+
decode.success(action)
213
213
+
}
214
214
+
215
215
+
// ENCODERS --------------------------------------------------------------------
216
216
+
217
217
+
@internal
218
218
+
pub fn create_rule_to_json(create_rule: CreateRule) -> Json {
219
219
+
let name = [#("name", json.string(create_rule.name))]
220
220
+
221
221
+
let event_type = [
222
222
+
#("event_type", case create_rule.trigger {
223
223
+
MemberProfileTrigger(..) -> json.int(2)
224
224
+
_ -> json.int(1)
225
225
+
}),
226
226
+
]
227
227
+
228
228
+
let trigger_type = [
229
229
+
#("trigger_type", case create_rule.trigger {
230
230
+
KeywordTrigger(..) -> json.int(1)
231
231
+
SpamTrigger -> json.int(3)
232
232
+
KeywordPresetTrigger(..) -> json.int(4)
233
233
+
MentionSpamTrigger(..) -> json.int(5)
234
234
+
MemberProfileTrigger(..) -> json.int(6)
235
235
+
}),
236
236
+
]
237
237
+
238
238
+
let trigger = case create_rule.trigger {
239
239
+
SpamTrigger -> []
240
240
+
_ -> [#("trigger_metadata", trigger_to_json(create_rule.trigger))]
241
241
+
}
242
242
+
243
243
+
let is_enabled = [#("enabled", json.bool(create_rule.is_enabled))]
244
244
+
245
245
+
let exempt_role_ids = case create_rule.exempt_role_ids {
246
246
+
Some(ids) -> [#("exempt_roles", json.array(ids, json.string))]
247
247
+
None -> []
248
248
+
}
249
249
+
250
250
+
let exempt_channel_ids = case create_rule.exempt_channel_ids {
251
251
+
Some(ids) -> [#("exempt_channels", json.array(ids, json.string))]
252
252
+
None -> []
253
253
+
}
254
254
+
255
255
+
[
256
256
+
name,
257
257
+
event_type,
258
258
+
trigger_type,
259
259
+
trigger,
260
260
+
is_enabled,
261
261
+
exempt_role_ids,
262
262
+
exempt_channel_ids,
263
263
+
]
264
264
+
|> list.flatten
265
265
+
|> json.object
266
266
+
}
267
267
+
268
268
+
@internal
269
269
+
pub fn trigger_to_json(trigger: Trigger) -> Json {
270
270
+
case trigger {
271
271
+
KeywordTrigger(..) -> [
272
272
+
#("keyword_filter", json.array(trigger.keyword_filter, json.string)),
273
273
+
#("regex_patterns", json.array(trigger.regex_patterns, json.string)),
274
274
+
#("allow_list", json.array(trigger.allow_list, json.string)),
275
275
+
]
276
276
+
SpamTrigger -> []
277
277
+
KeywordPresetTrigger(..) -> [
278
278
+
#("presets", json.array(trigger.presets, keyword_preset_to_json)),
279
279
+
#("allow_list", json.array(trigger.allow_list, json.string)),
280
280
+
]
281
281
+
MentionSpamTrigger(..) -> [
282
282
+
#("mention_total_limit", json.int(trigger.total_mention_limit)),
283
283
+
#(
284
284
+
"mention_raid_protection_enabled",
285
285
+
json.bool(trigger.is_mention_raid_protection_enabled),
286
286
+
),
287
287
+
]
288
288
+
MemberProfileTrigger(..) -> [
289
289
+
#("keyword_filter", json.array(trigger.keyword_filter, json.string)),
290
290
+
#("regex_patterns", json.array(trigger.regex_patterns, json.string)),
291
291
+
#("allow_list", json.array(trigger.allow_list, json.string)),
292
292
+
]
293
293
+
}
294
294
+
|> json.object
295
295
+
}
296
296
+
297
297
+
@internal
298
298
+
pub fn keyword_preset_to_json(keyword_preset: KeywordPreset) -> Json {
299
299
+
case keyword_preset {
300
300
+
ProfanityPreset -> 1
301
301
+
SexualContentPreset -> 2
302
302
+
SlursPreset -> 3
303
303
+
}
304
304
+
|> json.int
305
305
+
}
306
306
+
307
307
+
@internal
308
308
+
pub fn action_to_json(action: Action) -> Json {
309
309
+
[
310
310
+
[
311
311
+
#("type", case action {
312
312
+
BlockMessage(..) -> json.int(1)
313
313
+
SendAlertMessage(..) -> json.int(2)
314
314
+
TimeoutMember(..) -> json.int(3)
315
315
+
BlockMemberInteraction -> json.int(4)
316
316
+
}),
317
317
+
],
318
318
+
case action {
319
319
+
BlockMemberInteraction -> []
320
320
+
BlockMessage(..) -> [
321
321
+
#("metadata", {
322
322
+
let custom_message = case action.custom_message {
323
323
+
Some(message) -> [#("custom_message", json.string(message))]
324
324
+
None -> []
325
325
+
}
326
326
+
327
327
+
[custom_message]
328
328
+
|> list.flatten
329
329
+
|> json.object
330
330
+
}),
331
331
+
]
332
332
+
TimeoutMember(..) -> [
333
333
+
#(
334
334
+
"metadata",
335
335
+
json.object([
336
336
+
#(
337
337
+
"duration_seconds",
338
338
+
time_duration.to_int_seconds_encode(action.duration),
339
339
+
),
340
340
+
]),
341
341
+
),
342
342
+
]
343
343
+
SendAlertMessage(..) -> [
344
344
+
#(
345
345
+
"metadata",
346
346
+
json.object([#("channel_id", json.string(action.channel_id))]),
347
347
+
),
348
348
+
]
349
349
+
},
350
350
+
]
351
351
+
|> list.flatten
352
352
+
|> json.object
353
353
+
}
354
354
+
355
355
+
@internal
356
356
+
pub fn modify_rule_to_json(modify_rule: ModifyRule) -> Json {
357
357
+
let name = case modify_rule.name {
358
358
+
Some(name) -> [#("name", json.string(name))]
359
359
+
None -> []
360
360
+
}
361
361
+
362
362
+
let trigger = case modify_rule.trigger {
363
363
+
Some(SpamTrigger) | None -> []
364
364
+
Some(trigger) -> [#("trigger_metadata", trigger_to_json(trigger))]
365
365
+
}
366
366
+
367
367
+
let actions = case modify_rule.actions {
368
368
+
Some(actions) -> [#("actions", json.array(actions, action_to_json))]
369
369
+
None -> []
370
370
+
}
371
371
+
372
372
+
let is_enabled = case modify_rule.is_enabled {
373
373
+
Some(enabled) -> [#("enabled", json.bool(enabled))]
374
374
+
None -> []
375
375
+
}
376
376
+
377
377
+
let exempt_role_ids = case modify_rule.exempt_role_ids {
378
378
+
Some(ids) -> [#("exempt_roles", json.array(ids, json.string))]
379
379
+
None -> []
380
380
+
}
381
381
+
382
382
+
let exempt_channel_ids = case modify_rule.exempt_channel_ids {
383
383
+
Some(ids) -> [#("exempt_channels", json.array(ids, json.string))]
384
384
+
None -> []
385
385
+
}
386
386
+
387
387
+
[name, trigger, actions, is_enabled, exempt_role_ids, exempt_channel_ids]
388
388
+
|> list.flatten
389
389
+
|> json.object
390
390
+
}
391
391
+
392
392
+
// PUBLIC API FUNCTIONS --------------------------------------------------------
393
393
+
394
394
+
pub fn get_rule(
395
395
+
client: Client,
396
396
+
from guild_id: String,
397
397
+
id rule_id: String,
398
398
+
) -> Result(Rule, Error) {
399
399
+
use response <- result.try(
400
400
+
client
401
401
+
|> rest.new_request(
402
402
+
http.Get,
403
403
+
"/guilds/" <> guild_id <> "/auto-moderation/rules/" <> rule_id,
404
404
+
)
405
405
+
|> rest.execute,
406
406
+
)
407
407
+
408
408
+
response.body
409
409
+
|> json.parse(using: rule_decoder())
410
410
+
|> result.map_error(error.CouldNotDecode)
411
411
+
}
412
412
+
413
413
+
pub fn create_rule(
414
414
+
client: Client,
415
415
+
in guild_id: String,
416
416
+
with create_rule: CreateRule,
417
417
+
because reason: Option(String),
418
418
+
) -> Result(Rule, Error) {
419
419
+
let json = create_rule |> create_rule_to_json
420
420
+
421
421
+
use response <- result.try(
422
422
+
client
423
423
+
|> rest.new_request(
424
424
+
http.Post,
425
425
+
"/guilds/" <> guild_id <> "/auto-moderation/rules",
426
426
+
)
427
427
+
|> request.set_body(json |> json.to_string)
428
428
+
|> rest.with_reason(reason)
429
429
+
|> rest.execute,
430
430
+
)
431
431
+
432
432
+
response.body
433
433
+
|> json.parse(using: rule_decoder())
434
434
+
|> result.map_error(error.CouldNotDecode)
435
435
+
}
436
436
+
437
437
+
pub fn new_create_rule(
438
438
+
named name: String,
439
439
+
on trigger: Trigger,
440
440
+
do actions: List(Action),
441
441
+
enable is_enabled: Bool,
442
442
+
) -> CreateRule {
443
443
+
CreateRule(
444
444
+
name:,
445
445
+
trigger:,
446
446
+
actions:,
447
447
+
is_enabled:,
448
448
+
exempt_role_ids: None,
449
449
+
exempt_channel_ids: None,
450
450
+
)
451
451
+
}
452
452
+
453
453
+
pub fn create_rule_with_exempt_roles(
454
454
+
create_rule: CreateRule,
455
455
+
ids exempt_role_ids: List(String),
456
456
+
) -> CreateRule {
457
457
+
CreateRule(..create_rule, exempt_role_ids: Some(exempt_role_ids))
458
458
+
}
459
459
+
460
460
+
pub fn create_rule_with_exempt_channels(
461
461
+
create_rule: CreateRule,
462
462
+
ids exempt_channel_ids: List(String),
463
463
+
) -> CreateRule {
464
464
+
CreateRule(..create_rule, exempt_channel_ids: Some(exempt_channel_ids))
465
465
+
}
466
466
+
467
467
+
pub fn modify_rule(
468
468
+
client: Client,
469
469
+
in guild_id: String,
470
470
+
id rule_id: String,
471
471
+
with modify_rule: ModifyRule,
472
472
+
because reason: Option(String),
473
473
+
) -> Result(Rule, Error) {
474
474
+
let json = modify_rule |> modify_rule_to_json
475
475
+
476
476
+
use response <- result.try(
477
477
+
client
478
478
+
|> rest.new_request(
479
479
+
http.Patch,
480
480
+
"/guilds/" <> guild_id <> "/auto-moderation/rules/" <> rule_id,
481
481
+
)
482
482
+
|> request.set_body(json |> json.to_string)
483
483
+
|> rest.with_reason(reason)
484
484
+
|> rest.execute,
485
485
+
)
486
486
+
487
487
+
response.body
488
488
+
|> json.parse(using: rule_decoder())
489
489
+
|> result.map_error(error.CouldNotDecode)
490
490
+
}
491
491
+
492
492
+
pub fn modify_rule_name(modify_rule: ModifyRule, new name: String) -> ModifyRule {
493
493
+
ModifyRule(..modify_rule, name: Some(name))
494
494
+
}
495
495
+
496
496
+
pub fn modify_rule_trigger(
497
497
+
modify_rule: ModifyRule,
498
498
+
new trigger: Trigger,
499
499
+
) -> ModifyRule {
500
500
+
ModifyRule(..modify_rule, trigger: Some(trigger))
501
501
+
}
502
502
+
503
503
+
pub fn modify_rule_actions(
504
504
+
modify_rule: ModifyRule,
505
505
+
new actions: List(Action),
506
506
+
) -> ModifyRule {
507
507
+
ModifyRule(..modify_rule, actions: Some(actions))
508
508
+
}
509
509
+
510
510
+
pub fn enable_rule(modify_rule: ModifyRule) -> ModifyRule {
511
511
+
ModifyRule(..modify_rule, is_enabled: Some(True))
512
512
+
}
513
513
+
514
514
+
pub fn disable_rule(modify_rule: ModifyRule) -> ModifyRule {
515
515
+
ModifyRule(..modify_rule, is_enabled: Some(False))
516
516
+
}
517
517
+
518
518
+
pub fn exempt_roles_from_rule(
519
519
+
modify_rule: ModifyRule,
520
520
+
ids exempt_role_ids: List(String),
521
521
+
) -> ModifyRule {
522
522
+
ModifyRule(..modify_rule, exempt_role_ids: Some(exempt_role_ids))
523
523
+
}
524
524
+
525
525
+
pub fn exempt_channels_from_rule(
526
526
+
modify_rule: ModifyRule,
527
527
+
ids exempt_channel_ids: List(String),
528
528
+
) -> ModifyRule {
529
529
+
ModifyRule(..modify_rule, exempt_channel_ids: Some(exempt_channel_ids))
530
530
+
}
531
531
+
532
532
+
pub fn delete_rule(
533
533
+
client: Client,
534
534
+
from guild_id: String,
535
535
+
id rule_id: String,
536
536
+
because reason: Option(String),
537
537
+
) -> Result(Nil, Error) {
538
538
+
use _response <- result.try(
539
539
+
client
540
540
+
|> rest.new_request(
541
541
+
http.Delete,
542
542
+
"/guilds/" <> guild_id <> "/auto-moderation/rules/" <> rule_id,
543
543
+
)
544
544
+
|> rest.with_reason(reason)
545
545
+
|> rest.execute,
546
546
+
)
547
547
+
548
548
+
Ok(Nil)
549
549
+
}
-124
src/grom/guild/auto_moderation/action.gleam
···
1
1
-
import gleam/dynamic/decode
2
2
-
import gleam/json.{type Json}
3
3
-
import gleam/list
4
4
-
import gleam/option.{type Option, None, Some}
5
5
-
import gleam/time/duration.{type Duration}
6
6
-
import grom/internal/time_duration
7
7
-
8
8
-
// TYPES -----------------------------------------------------------------------
9
9
-
10
10
-
pub type Action {
11
11
-
Action(type_: Type, metadata: Option(Metadata))
12
12
-
}
13
13
-
14
14
-
pub type Type {
15
15
-
BlockMessage
16
16
-
SendAlertMessage
17
17
-
Timeout
18
18
-
BlockMemberInteraction
19
19
-
}
20
20
-
21
21
-
pub type Metadata {
22
22
-
SendAlertMessageMetadata(channel_id: String)
23
23
-
TimeoutMetadata(duration: Duration)
24
24
-
BlockMessageMetadata(custom_message: Option(String))
25
25
-
}
26
26
-
27
27
-
// TYPES -----------------------------------------------------------------------
28
28
-
29
29
-
@internal
30
30
-
pub fn decoder() -> decode.Decoder(Action) {
31
31
-
use type_ <- decode.field("type", type_decoder())
32
32
-
use metadata <- decode.field(
33
33
-
"metadata",
34
34
-
decode.optional(metadata_decoder(type_)),
35
35
-
)
36
36
-
decode.success(Action(type_:, metadata:))
37
37
-
}
38
38
-
39
39
-
@internal
40
40
-
pub fn type_decoder() -> decode.Decoder(Type) {
41
41
-
use variant <- decode.then(decode.int)
42
42
-
case variant {
43
43
-
1 -> decode.success(BlockMessage)
44
44
-
2 -> decode.success(SendAlertMessage)
45
45
-
3 -> decode.success(Timeout)
46
46
-
4 -> decode.success(BlockMemberInteraction)
47
47
-
_ -> decode.failure(BlockMessage, "Type")
48
48
-
}
49
49
-
}
50
50
-
51
51
-
@internal
52
52
-
pub fn metadata_decoder(type_: Type) -> decode.Decoder(Metadata) {
53
53
-
case type_ {
54
54
-
SendAlertMessage -> send_alert_message_metadata_decoder()
55
55
-
Timeout -> timeout_metadata_decoder()
56
56
-
BlockMessage -> block_message_metadata_decoder()
57
57
-
_ -> decode.failure(SendAlertMessageMetadata(""), "Metadata")
58
58
-
}
59
59
-
}
60
60
-
61
61
-
fn send_alert_message_metadata_decoder() -> decode.Decoder(Metadata) {
62
62
-
use channel_id <- decode.field("channel_id", decode.string)
63
63
-
decode.success(SendAlertMessageMetadata(channel_id:))
64
64
-
}
65
65
-
66
66
-
fn timeout_metadata_decoder() -> decode.Decoder(Metadata) {
67
67
-
use duration <- decode.field(
68
68
-
"duration_seconds",
69
69
-
time_duration.from_int_seconds_decoder(),
70
70
-
)
71
71
-
decode.success(TimeoutMetadata(duration:))
72
72
-
}
73
73
-
74
74
-
fn block_message_metadata_decoder() -> decode.Decoder(Metadata) {
75
75
-
use custom_message <- decode.optional_field(
76
76
-
"custom_message",
77
77
-
None,
78
78
-
decode.optional(decode.string),
79
79
-
)
80
80
-
decode.success(BlockMessageMetadata(custom_message:))
81
81
-
}
82
82
-
83
83
-
// ENCODERS --------------------------------------------------------------------
84
84
-
85
85
-
@internal
86
86
-
pub fn encode(action: Action) -> Json {
87
87
-
let metadata = case action.metadata {
88
88
-
Some(metadata) -> [#("metadata", metadata_encode(metadata))]
89
89
-
None -> []
90
90
-
}
91
91
-
92
92
-
[[#("type", type_encode(action.type_))], metadata]
93
93
-
|> list.flatten
94
94
-
|> json.object
95
95
-
}
96
96
-
97
97
-
@internal
98
98
-
pub fn type_encode(type_: Type) -> Json {
99
99
-
case type_ {
100
100
-
BlockMessage -> 1
101
101
-
SendAlertMessage -> 2
102
102
-
Timeout -> 3
103
103
-
BlockMemberInteraction -> 4
104
104
-
}
105
105
-
|> json.int
106
106
-
}
107
107
-
108
108
-
@internal
109
109
-
pub fn metadata_encode(metadata: Metadata) -> Json {
110
110
-
case metadata {
111
111
-
SendAlertMessageMetadata(channel_id) -> [
112
112
-
#("channel_id", json.string(channel_id)),
113
113
-
]
114
114
-
TimeoutMetadata(duration) -> [
115
115
-
#("duration_seconds", json.int(time_duration.to_int_seconds(duration))),
116
116
-
]
117
117
-
BlockMessageMetadata(custom_message) ->
118
118
-
case custom_message {
119
119
-
Some(msg) -> [#("custom_message", json.string(msg))]
120
120
-
None -> []
121
121
-
}
122
122
-
}
123
123
-
|> json.object
124
124
-
}
-29
src/grom/guild/auto_moderation/event.gleam
···
1
1
-
import gleam/dynamic/decode
2
2
-
import gleam/json.{type Json}
3
3
-
4
4
-
// TYPES -----------------------------------------------------------------------
5
5
-
6
6
-
pub type Type {
7
7
-
MessageSend
8
8
-
MemberUpdate
9
9
-
}
10
10
-
11
11
-
// DECODERS --------------------------------------------------------------------
12
12
-
13
13
-
@internal
14
14
-
pub fn type_decoder() -> decode.Decoder(Type) {
15
15
-
use variant <- decode.then(decode.int)
16
16
-
case variant {
17
17
-
1 -> decode.success(MessageSend)
18
18
-
2 -> decode.success(MemberUpdate)
19
19
-
_ -> decode.failure(MessageSend, "Type")
20
20
-
}
21
21
-
}
22
22
-
23
23
-
@internal
24
24
-
pub fn type_encode(type_: Type) -> Json {
25
25
-
case type_ {
26
26
-
MessageSend -> json.int(1)
27
27
-
MemberUpdate -> json.int(2)
28
28
-
}
29
29
-
}
-35
src/grom/guild/auto_moderation/keyword_preset.gleam
···
1
1
-
import gleam/dynamic/decode
2
2
-
import gleam/json.{type Json}
3
3
-
4
4
-
// TYPES -----------------------------------------------------------------------
5
5
-
6
6
-
pub type Type {
7
7
-
Profanity
8
8
-
SexualContent
9
9
-
Slurs
10
10
-
}
11
11
-
12
12
-
// DECODERS --------------------------------------------------------------------
13
13
-
14
14
-
@internal
15
15
-
pub fn type_decoder() -> decode.Decoder(Type) {
16
16
-
use variant <- decode.then(decode.int)
17
17
-
case variant {
18
18
-
1 -> decode.success(Profanity)
19
19
-
2 -> decode.success(SexualContent)
20
20
-
3 -> decode.success(Slurs)
21
21
-
_ -> decode.failure(Profanity, "Type")
22
22
-
}
23
23
-
}
24
24
-
25
25
-
// ENCODERS --------------------------------------------------------------------
26
26
-
27
27
-
@internal
28
28
-
pub fn type_encode(type_: Type) -> Json {
29
29
-
case type_ {
30
30
-
Profanity -> 1
31
31
-
SexualContent -> 2
32
32
-
Slurs -> 3
33
33
-
}
34
34
-
|> json.int
35
35
-
}
-350
src/grom/guild/auto_moderation/rule.gleam
···
1
1
-
import gleam/dynamic/decode
2
2
-
import gleam/http
3
3
-
import gleam/http/request
4
4
-
import gleam/json.{type Json}
5
5
-
import gleam/list
6
6
-
import gleam/option.{type Option, None, Some}
7
7
-
import gleam/result
8
8
-
import grom/client.{type Client}
9
9
-
import grom/error
10
10
-
import grom/guild/auto_moderation/action.{type Action}
11
11
-
import grom/guild/auto_moderation/event
12
12
-
import grom/guild/auto_moderation/trigger
13
13
-
import grom/internal/rest
14
14
-
15
15
-
// TYPES -----------------------------------------------------------------------
16
16
-
17
17
-
pub type Rule {
18
18
-
Rule(
19
19
-
id: String,
20
20
-
guild_id: String,
21
21
-
name: String,
22
22
-
creator_id: String,
23
23
-
event_type: event.Type,
24
24
-
trigger_type: trigger.Type,
25
25
-
trigger_metadata: trigger.Metadata,
26
26
-
actions: List(Action),
27
27
-
is_enabled: Bool,
28
28
-
exempt_role_ids: List(String),
29
29
-
exempt_channel_ids: List(String),
30
30
-
)
31
31
-
}
32
32
-
33
33
-
/// Disabled by default. Enable with `create_with_is_enabled()`.
34
34
-
pub opaque type Create {
35
35
-
Create(
36
36
-
name: String,
37
37
-
event_type: event.Type,
38
38
-
trigger_type: trigger.Type,
39
39
-
trigger_metadata: Option(trigger.Metadata),
40
40
-
actions: List(Action),
41
41
-
is_enabled: Option(Bool),
42
42
-
exempt_role_ids: Option(List(String)),
43
43
-
exempt_channel_ids: Option(List(String)),
44
44
-
)
45
45
-
}
46
46
-
47
47
-
pub opaque type Modify {
48
48
-
Modify(
49
49
-
name: Option(String),
50
50
-
event_type: Option(event.Type),
51
51
-
trigger_metadata: Option(trigger.Metadata),
52
52
-
actions: Option(List(Action)),
53
53
-
is_enabled: Option(Bool),
54
54
-
exempt_role_ids: Option(List(String)),
55
55
-
exempt_channel_ids: Option(List(String)),
56
56
-
)
57
57
-
}
58
58
-
59
59
-
// DECODERS --------------------------------------------------------------------
60
60
-
61
61
-
@internal
62
62
-
pub fn decoder() -> decode.Decoder(Rule) {
63
63
-
use id <- decode.field("id", decode.string)
64
64
-
use guild_id <- decode.field("guild_id", decode.string)
65
65
-
use name <- decode.field("name", decode.string)
66
66
-
use creator_id <- decode.field("creator_id", decode.string)
67
67
-
use event_type <- decode.field("event_type", event.type_decoder())
68
68
-
use trigger_type <- decode.field("trigger_type", trigger.type_decoder())
69
69
-
use trigger_metadata <- decode.field(
70
70
-
"trigger_metadata",
71
71
-
trigger.metadata_decoder(trigger_type),
72
72
-
)
73
73
-
use actions <- decode.field("actions", decode.list(action.decoder()))
74
74
-
use is_enabled <- decode.field("enabled", decode.bool)
75
75
-
use exempt_role_ids <- decode.field(
76
76
-
"exempt_roles",
77
77
-
decode.list(decode.string),
78
78
-
)
79
79
-
use exempt_channel_ids <- decode.field(
80
80
-
"exempt_channels",
81
81
-
decode.list(decode.string),
82
82
-
)
83
83
-
decode.success(Rule(
84
84
-
id:,
85
85
-
guild_id:,
86
86
-
name:,
87
87
-
creator_id:,
88
88
-
event_type:,
89
89
-
trigger_type:,
90
90
-
trigger_metadata:,
91
91
-
actions:,
92
92
-
is_enabled:,
93
93
-
exempt_role_ids:,
94
94
-
exempt_channel_ids:,
95
95
-
))
96
96
-
}
97
97
-
98
98
-
// ENCODERS --------------------------------------------------------------------
99
99
-
100
100
-
@internal
101
101
-
pub fn create_encode(create: Create) -> Json {
102
102
-
let trigger_metadata = case create.trigger_metadata {
103
103
-
Some(metadata) -> [#("trigger_metadata", trigger.metadata_encode(metadata))]
104
104
-
None -> []
105
105
-
}
106
106
-
let is_enabled = case create.is_enabled {
107
107
-
Some(enabled) -> [#("enabled", json.bool(enabled))]
108
108
-
None -> []
109
109
-
}
110
110
-
let exempt_role_ids = case create.exempt_role_ids {
111
111
-
Some(ids) -> [#("exempt_roles", json.array(ids, json.string))]
112
112
-
None -> []
113
113
-
}
114
114
-
let exempt_channel_ids = case create.exempt_channel_ids {
115
115
-
Some(ids) -> [#("exempt_channels", json.array(ids, json.string))]
116
116
-
None -> []
117
117
-
}
118
118
-
119
119
-
[
120
120
-
[
121
121
-
#("name", json.string(create.name)),
122
122
-
#("event_type", event.type_encode(create.event_type)),
123
123
-
#("trigger_type", trigger.type_encode(create.trigger_type)),
124
124
-
#("actions", json.array(create.actions, action.encode)),
125
125
-
],
126
126
-
trigger_metadata,
127
127
-
is_enabled,
128
128
-
exempt_role_ids,
129
129
-
exempt_channel_ids,
130
130
-
]
131
131
-
|> list.flatten
132
132
-
|> json.object
133
133
-
}
134
134
-
135
135
-
@internal
136
136
-
pub fn modify_encode(modify: Modify) -> Json {
137
137
-
let name = case modify.name {
138
138
-
Some(name) -> [#("name", json.string(name))]
139
139
-
None -> []
140
140
-
}
141
141
-
let event_type = case modify.event_type {
142
142
-
Some(type_) -> [#("event_type", event.type_encode(type_))]
143
143
-
None -> []
144
144
-
}
145
145
-
let trigger_metadata = case modify.trigger_metadata {
146
146
-
Some(metadata) -> [#("trigger_metadata", trigger.metadata_encode(metadata))]
147
147
-
None -> []
148
148
-
}
149
149
-
let actions = case modify.actions {
150
150
-
Some(actions) -> [#("actions", json.array(actions, action.encode))]
151
151
-
None -> []
152
152
-
}
153
153
-
let is_enabled = case modify.is_enabled {
154
154
-
Some(enabled) -> [#("enabled", json.bool(enabled))]
155
155
-
None -> []
156
156
-
}
157
157
-
let exempt_role_ids = case modify.exempt_role_ids {
158
158
-
Some(ids) -> [#("exempt_roles", json.array(ids, json.string))]
159
159
-
None -> []
160
160
-
}
161
161
-
let exempt_channel_ids = case modify.exempt_channel_ids {
162
162
-
Some(ids) -> [#("exempt_channels", json.array(ids, json.string))]
163
163
-
None -> []
164
164
-
}
165
165
-
166
166
-
[
167
167
-
name,
168
168
-
event_type,
169
169
-
trigger_metadata,
170
170
-
actions,
171
171
-
is_enabled,
172
172
-
exempt_role_ids,
173
173
-
exempt_channel_ids,
174
174
-
]
175
175
-
|> list.flatten
176
176
-
|> json.object
177
177
-
}
178
178
-
179
179
-
// PUBLIC API FUNCTIONS -------------------------------------------------------
180
180
-
181
181
-
pub fn get(
182
182
-
client: Client,
183
183
-
in guild_id: String,
184
184
-
id rule_id: String,
185
185
-
) -> Result(Rule, error.Error) {
186
186
-
use response <- result.try(
187
187
-
client
188
188
-
|> rest.new_request(
189
189
-
http.Get,
190
190
-
"/guilds/" <> guild_id <> "/auto-moderation/rules/" <> rule_id,
191
191
-
)
192
192
-
|> rest.execute,
193
193
-
)
194
194
-
195
195
-
response.body
196
196
-
|> json.parse(using: decoder())
197
197
-
|> result.map_error(error.CouldNotDecode)
198
198
-
}
199
199
-
200
200
-
pub fn create(
201
201
-
client: Client,
202
202
-
in guild_id: String,
203
203
-
with create: Create,
204
204
-
reason reason: Option(String),
205
205
-
) -> Result(Rule, error.Error) {
206
206
-
let json = create |> create_encode
207
207
-
208
208
-
use response <- result.try(
209
209
-
client
210
210
-
|> rest.new_request(
211
211
-
http.Post,
212
212
-
"/guilds/" <> guild_id <> "/auto-moderation/rules",
213
213
-
)
214
214
-
|> request.set_body(json |> json.to_string)
215
215
-
|> rest.with_reason(reason)
216
216
-
|> rest.execute,
217
217
-
)
218
218
-
219
219
-
response.body
220
220
-
|> json.parse(using: decoder())
221
221
-
|> result.map_error(error.CouldNotDecode)
222
222
-
}
223
223
-
224
224
-
pub fn new_create(
225
225
-
name: String,
226
226
-
event_type: event.Type,
227
227
-
trigger_type: trigger.Type,
228
228
-
actions: List(Action),
229
229
-
) -> Create {
230
230
-
Create(
231
231
-
name:,
232
232
-
event_type:,
233
233
-
trigger_type:,
234
234
-
actions:,
235
235
-
trigger_metadata: None,
236
236
-
is_enabled: None,
237
237
-
exempt_role_ids: None,
238
238
-
exempt_channel_ids: None,
239
239
-
)
240
240
-
}
241
241
-
242
242
-
pub fn create_with_trigger_metadata(
243
243
-
create: Create,
244
244
-
metadata: trigger.Metadata,
245
245
-
) -> Create {
246
246
-
Create(..create, trigger_metadata: Some(metadata))
247
247
-
}
248
248
-
249
249
-
pub fn create_with_is_enabled(create: Create, is_enabled: Bool) -> Create {
250
250
-
Create(..create, is_enabled: Some(is_enabled))
251
251
-
}
252
252
-
253
253
-
pub fn create_with_exempt_role_ids(
254
254
-
create: Create,
255
255
-
exempt_role_ids: List(String),
256
256
-
) -> Create {
257
257
-
Create(..create, exempt_role_ids: Some(exempt_role_ids))
258
258
-
}
259
259
-
260
260
-
pub fn create_with_exempt_channel_ids(
261
261
-
create: Create,
262
262
-
exempt_channel_ids: List(String),
263
263
-
) -> Create {
264
264
-
Create(..create, exempt_channel_ids: Some(exempt_channel_ids))
265
265
-
}
266
266
-
267
267
-
pub fn modify(
268
268
-
client: Client,
269
269
-
in guild_id: String,
270
270
-
id rule_id: String,
271
271
-
with modify: Modify,
272
272
-
reason reason: Option(String),
273
273
-
) {
274
274
-
let json = modify |> modify_encode
275
275
-
276
276
-
use response <- result.try(
277
277
-
client
278
278
-
|> rest.new_request(
279
279
-
http.Patch,
280
280
-
"/guilds/" <> guild_id <> "/auto-moderation/rules/" <> rule_id,
281
281
-
)
282
282
-
|> rest.with_reason(reason)
283
283
-
|> request.set_body(json |> json.to_string)
284
284
-
|> rest.execute,
285
285
-
)
286
286
-
287
287
-
response.body
288
288
-
|> json.parse(using: decoder())
289
289
-
|> result.map_error(error.CouldNotDecode)
290
290
-
}
291
291
-
292
292
-
pub fn new_modify() -> Modify {
293
293
-
Modify(None, None, None, None, None, None, None)
294
294
-
}
295
295
-
296
296
-
pub fn modify_name(modify: Modify, name: String) -> Modify {
297
297
-
Modify(..modify, name: Some(name))
298
298
-
}
299
299
-
300
300
-
pub fn modify_event_type(modify: Modify, event_type: event.Type) -> Modify {
301
301
-
Modify(..modify, event_type: Some(event_type))
302
302
-
}
303
303
-
304
304
-
pub fn modify_trigger_metadata(
305
305
-
modify: Modify,
306
306
-
trigger_metadata: trigger.Metadata,
307
307
-
) -> Modify {
308
308
-
Modify(..modify, trigger_metadata: Some(trigger_metadata))
309
309
-
}
310
310
-
311
311
-
pub fn modify_actions(modify: Modify, actions: List(Action)) -> Modify {
312
312
-
Modify(..modify, actions: Some(actions))
313
313
-
}
314
314
-
315
315
-
pub fn modify_is_enabled(modify: Modify, is_enabled: Bool) -> Modify {
316
316
-
Modify(..modify, is_enabled: Some(is_enabled))
317
317
-
}
318
318
-
319
319
-
pub fn modify_exempt_role_ids(
320
320
-
modify: Modify,
321
321
-
exempt_role_ids: List(String),
322
322
-
) -> Modify {
323
323
-
Modify(..modify, exempt_role_ids: Some(exempt_role_ids))
324
324
-
}
325
325
-
326
326
-
pub fn modify_exempt_channel_ids(
327
327
-
modify: Modify,
328
328
-
exempt_channel_ids: List(String),
329
329
-
) -> Modify {
330
330
-
Modify(..modify, exempt_channel_ids: Some(exempt_channel_ids))
331
331
-
}
332
332
-
333
333
-
pub fn delete(
334
334
-
client: Client,
335
335
-
in guild_id: String,
336
336
-
id rule_id: String,
337
337
-
reason reason: Option(String),
338
338
-
) -> Result(Nil, error.Error) {
339
339
-
use _response <- result.try(
340
340
-
client
341
341
-
|> rest.new_request(
342
342
-
http.Delete,
343
343
-
"/guilds/" <> guild_id <> "/auto-moderation/rules/" <> rule_id,
344
344
-
)
345
345
-
|> rest.with_reason(reason)
346
346
-
|> rest.execute,
347
347
-
)
348
348
-
349
349
-
Ok(Nil)
350
350
-
}
-163
src/grom/guild/auto_moderation/trigger.gleam
···
1
1
-
import gleam/dynamic/decode
2
2
-
import gleam/int
3
3
-
import gleam/json.{type Json}
4
4
-
import grom/guild/auto_moderation/keyword_preset
5
5
-
6
6
-
// TYPES -----------------------------------------------------------------------
7
7
-
8
8
-
pub type Type {
9
9
-
Keyword
10
10
-
Spam
11
11
-
KeywordPreset
12
12
-
MentionSpam
13
13
-
MemberProfile
14
14
-
}
15
15
-
16
16
-
pub type Metadata {
17
17
-
KeywordMetadata(
18
18
-
keyword_filter: List(String),
19
19
-
regex_patterns: List(String),
20
20
-
allow_list: List(String),
21
21
-
)
22
22
-
MemberProfileMetadata(
23
23
-
keyword_filter: List(String),
24
24
-
regex_patterns: List(String),
25
25
-
allow_list: List(String),
26
26
-
)
27
27
-
KeywordPresetMetadata(
28
28
-
presets: List(keyword_preset.Type),
29
29
-
allow_list: List(String),
30
30
-
)
31
31
-
MentionSpamMetadata(
32
32
-
mention_total_limit: Int,
33
33
-
is_mention_raid_protection_enabled: Bool,
34
34
-
)
35
35
-
}
36
36
-
37
37
-
// DECODERS --------------------------------------------------------------------
38
38
-
39
39
-
@internal
40
40
-
pub fn type_decoder() -> decode.Decoder(Type) {
41
41
-
use variant <- decode.then(decode.int)
42
42
-
case variant {
43
43
-
1 -> decode.success(Keyword)
44
44
-
3 -> decode.success(Spam)
45
45
-
4 -> decode.success(KeywordPreset)
46
46
-
5 -> decode.success(MentionSpam)
47
47
-
6 -> decode.success(MemberProfile)
48
48
-
_ -> decode.failure(Keyword, "Type")
49
49
-
}
50
50
-
}
51
51
-
52
52
-
@internal
53
53
-
pub fn type_string_decoder() -> decode.Decoder(Type) {
54
54
-
use variant <- decode.then(decode.string)
55
55
-
case int.parse(variant) {
56
56
-
Ok(_) -> type_decoder()
57
57
-
Error(_) -> decode.failure(Keyword, "Type")
58
58
-
}
59
59
-
}
60
60
-
61
61
-
@internal
62
62
-
pub fn metadata_decoder(type_: Type) -> decode.Decoder(Metadata) {
63
63
-
case type_ {
64
64
-
Keyword -> keyword_metadata_decoder()
65
65
-
MemberProfile -> member_profile_metadata_decoder()
66
66
-
KeywordPreset -> keyword_preset_metadata_decoder()
67
67
-
MentionSpam -> mention_spam_metadata_decoder()
68
68
-
Spam -> decode.failure(KeywordPresetMetadata([], []), "Metadata")
69
69
-
}
70
70
-
}
71
71
-
72
72
-
fn keyword_metadata_decoder() -> decode.Decoder(Metadata) {
73
73
-
use keyword_filter <- decode.field(
74
74
-
"keyword_filter",
75
75
-
decode.list(decode.string),
76
76
-
)
77
77
-
use regex_patterns <- decode.field(
78
78
-
"regex_patterns",
79
79
-
decode.list(decode.string),
80
80
-
)
81
81
-
use allow_list <- decode.field("allow_list", decode.list(decode.string))
82
82
-
decode.success(KeywordMetadata(keyword_filter:, regex_patterns:, allow_list:))
83
83
-
}
84
84
-
85
85
-
fn member_profile_metadata_decoder() -> decode.Decoder(Metadata) {
86
86
-
use keyword_filter <- decode.field(
87
87
-
"keyword_filter",
88
88
-
decode.list(decode.string),
89
89
-
)
90
90
-
use regex_patterns <- decode.field(
91
91
-
"regex_patterns",
92
92
-
decode.list(decode.string),
93
93
-
)
94
94
-
use allow_list <- decode.field("allow_list", decode.list(decode.string))
95
95
-
decode.success(MemberProfileMetadata(
96
96
-
keyword_filter:,
97
97
-
regex_patterns:,
98
98
-
allow_list:,
99
99
-
))
100
100
-
}
101
101
-
102
102
-
fn keyword_preset_metadata_decoder() -> decode.Decoder(Metadata) {
103
103
-
use presets <- decode.field(
104
104
-
"presets",
105
105
-
decode.list(keyword_preset.type_decoder()),
106
106
-
)
107
107
-
use allow_list <- decode.field("allow_list", decode.list(decode.string))
108
108
-
decode.success(KeywordPresetMetadata(presets:, allow_list:))
109
109
-
}
110
110
-
111
111
-
fn mention_spam_metadata_decoder() -> decode.Decoder(Metadata) {
112
112
-
use mention_total_limit <- decode.field("mention_total_limit", decode.int)
113
113
-
use is_mention_raid_protection_enabled <- decode.field(
114
114
-
"mention_raid_protection_enabled",
115
115
-
decode.bool,
116
116
-
)
117
117
-
decode.success(MentionSpamMetadata(
118
118
-
mention_total_limit:,
119
119
-
is_mention_raid_protection_enabled:,
120
120
-
))
121
121
-
}
122
122
-
123
123
-
// ENCODERS --------------------------------------------------------------------
124
124
-
125
125
-
@internal
126
126
-
pub fn type_encode(type_: Type) -> Json {
127
127
-
case type_ {
128
128
-
Keyword -> 1
129
129
-
Spam -> 3
130
130
-
KeywordPreset -> 4
131
131
-
MentionSpam -> 5
132
132
-
MemberProfile -> 6
133
133
-
}
134
134
-
|> json.int
135
135
-
}
136
136
-
137
137
-
@internal
138
138
-
pub fn metadata_encode(metadata: Metadata) -> Json {
139
139
-
case metadata {
140
140
-
KeywordMetadata(keyword_filter, regex_patterns, allow_list) -> [
141
141
-
#("keyword_filter", json.array(keyword_filter, json.string)),
142
142
-
#("regex_patterns", json.array(regex_patterns, json.string)),
143
143
-
#("allow_list", json.array(allow_list, json.string)),
144
144
-
]
145
145
-
MemberProfileMetadata(keyword_filter, regex_patterns, allow_list) -> [
146
146
-
#("keyword_filter", json.array(keyword_filter, json.string)),
147
147
-
#("regex_patterns", json.array(regex_patterns, json.string)),
148
148
-
#("allow_list", json.array(allow_list, json.string)),
149
149
-
]
150
150
-
KeywordPresetMetadata(presets, allow_list) -> [
151
151
-
#("presets", json.array(presets, keyword_preset.type_encode)),
152
152
-
#("allow_list", json.array(allow_list, json.string)),
153
153
-
]
154
154
-
MentionSpamMetadata(mention_total_limit, is_mention_raid_protection_enabled) -> [
155
155
-
#("mention_total_limit", json.int(mention_total_limit)),
156
156
-
#(
157
157
-
"mention_raid_protection_enabled",
158
158
-
json.bool(is_mention_raid_protection_enabled),
159
159
-
),
160
160
-
]
161
161
-
}
162
162
-
|> json.object
163
163
-
}