1use std::{
6 error::Error,
7 fmt::{Display, Formatter, Result as FmtResult},
8 time::{SystemTime, UNIX_EPOCH},
9};
10use twilight_model::id::marker::{ChannelMarker, RoleMarker};
11use twilight_model::id::{Id, marker::UserMarker};
12use twilight_model::util::Timestamp;
13
14pub const AUDIT_REASON_MAX: usize = 512;
16
17pub const AUTO_MODERATION_ACTION_BLOCK_CUSTOM_MESSAGE_LENGTH_MAX: usize = 150;
19
20pub const AUTO_MODERATION_METADATA_MENTION_TOTAL_LIMIT: u8 = 50;
22
23pub const AUTO_MODERATION_METADATA_KEYWORD_FILTER_MAX: usize = 1000;
25
26pub const AUTO_MODERATION_METADATA_KEYWORD_FILTER_LENGTH_MAX: usize = 60;
28
29pub const AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_MAX: usize = 100;
31
32pub const AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_MAX: usize = 1000;
34
35pub const AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_LENGTH_MAX: usize = 60;
37
38pub const AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_LENGTH_MAX: usize = 60;
40
41pub const AUTO_MODERATION_METADATA_REGEX_PATTERNS_MAX: usize = 10;
43
44pub const AUTO_MODERATION_METADATA_REGEX_PATTERNS_LENGTH_MAX: usize = 260;
46
47pub const AUTO_MODERATION_ACTION_METADATA_DURATION_SECONDS_MAX: u32 = 2_419_200;
49
50pub const AUTO_MODERATION_EXEMPT_ROLES_MAX: usize = 20;
52
53pub const AUTO_MODERATION_EXEMPT_CHANNELS_MAX: usize = 50;
55
56pub const BIO_LIMIT_MAX: usize = 400;
58
59pub const BIO_LIMIT_MIN: usize = 1;
61
62pub const BULK_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX: u32 = 604_800;
64
65pub const BULK_GUILD_BAN_USER_LIMIT_MAX: usize = 200;
67
68pub const CREATE_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX: u32 = 604_800;
70
71pub const COMMUNICATION_DISABLED_MAX_DURATION: i64 = 28 * 24 * 60 * 60;
73
74pub const GET_CHANNEL_MESSAGES_LIMIT_MAX: u16 = 100;
76
77pub const GET_CHANNEL_MESSAGES_LIMIT_MIN: u16 = 1;
79
80pub const GET_CURRENT_USER_GUILDS_LIMIT_MAX: u16 = 200;
82
83pub const GET_CURRENT_USER_GUILDS_LIMIT_MIN: u16 = 1;
85
86pub const GET_ENTITLEMENTS_LIMIT_MAX: u8 = 100;
88
89pub const GET_ENTITLEMENTS_LIMIT_MIN: u8 = 1;
91
92pub const GET_GUILD_AUDIT_LOG_LIMIT_MAX: u16 = 100;
94
95pub const GET_GUILD_AUDIT_LOG_LIMIT_MIN: u16 = 1;
97
98pub const GET_GUILD_BANS_LIMIT_MAX: u16 = 1000;
100
101pub const GET_GUILD_MEMBERS_LIMIT_MAX: u16 = 1000;
103
104pub const GET_GUILD_MEMBERS_LIMIT_MIN: u16 = 1;
106
107pub const GET_REACTIONS_LIMIT_MIN: u16 = 1;
109
110pub const GET_REACTIONS_LIMIT_MAX: u16 = 100;
112
113pub const GET_SKU_SUBSCRIPTIONS_LIMIT_MIN: u8 = 1;
115
116pub const GET_SKU_SUBSCRIPTIONS_LIMIT_MAX: u8 = 100;
118
119pub const GUILD_NAME_LENGTH_MAX: usize = 100;
121
122pub const GUILD_NAME_LENGTH_MIN: usize = 2;
124
125pub const GUILD_PRUNE_DAYS_MAX: u16 = 30;
127
128pub const GUILD_PRUNE_DAYS_MIN: u16 = 1;
130
131pub const INVITE_AGE_MAX: u32 = 604_800;
133
134pub const INVITE_USES_MAX: u16 = 100;
136
137pub const NICKNAME_LIMIT_MAX: usize = 32;
139
140pub const NICKNAME_LIMIT_MIN: usize = 1;
142
143pub const PIN_LIMIT_MAX: u16 = 50;
145
146pub const PIN_LIMIT_MIN: u16 = 1;
148
149pub const SCHEDULED_EVENT_DESCRIPTION_MAX: usize = 1000;
151
152pub const SCHEDULED_EVENT_DESCRIPTION_MIN: usize = 1;
154
155pub const SCHEDULED_EVENT_GET_USERS_MAX: u16 = 100;
157
158pub const SCHEDULED_EVENT_GET_USERS_MIN: u16 = 1;
160
161pub const SCHEDULED_EVENT_NAME_MAX: usize = 100;
163
164pub const SCHEDULED_EVENT_NAME_MIN: usize = 1;
166
167pub const SEARCH_GUILD_MEMBERS_LIMIT_MAX: u16 = 1000;
169
170pub const SEARCH_GUILD_MEMBERS_LIMIT_MIN: u16 = 1;
172
173pub const STAGE_TOPIC_LENGTH_MAX: usize = 120;
175
176pub const STAGE_TOPIC_LENGTH_MIN: usize = 1;
178
179pub const TEMPLATE_DESCRIPTION_LENGTH_MAX: usize = 120;
181
182pub const TEMPLATE_NAME_LENGTH_MAX: usize = 100;
184
185pub const TEMPLATE_NAME_LENGTH_MIN: usize = 1;
187
188pub const USERNAME_LIMIT_MAX: usize = 32;
190
191pub const USERNAME_LIMIT_MIN: usize = 2;
193
194pub const WEBHOOK_USERNAME_LIMIT_MAX: usize = 80;
196
197pub const WEBHOOK_USERNAME_LIMIT_MIN: usize = 1;
199
200const USERNAME_INVALID_SUBSTRINGS: [&str; 5] = ["@", "#", ":", "```", "discord"];
202
203const USERNAME_INVALID_STRINGS: [&str; 2] = ["everyone", "here"];
205
206const WEBHOOK_INVALID_STRINGS: [&str; 1] = ["clyde"];
208
209#[derive(Debug)]
211pub struct ValidationError {
212 kind: ValidationErrorType,
214}
215
216impl ValidationError {
217 #[must_use = "retrieving the type has no effect if left unused"]
219 pub const fn kind(&self) -> &ValidationErrorType {
220 &self.kind
221 }
222
223 #[allow(clippy::unused_self)]
225 #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
226 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
227 None
228 }
229
230 #[must_use = "consuming the error into its parts has no effect if left unused"]
232 pub fn into_parts(self) -> (ValidationErrorType, Option<Box<dyn Error + Send + Sync>>) {
233 (self.kind, None)
234 }
235}
236
237impl Display for ValidationError {
238 #[allow(clippy::too_many_lines)]
239 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
240 match &self.kind {
241 ValidationErrorType::AuditReason { len } => {
242 f.write_str("provided audit reason length is ")?;
243 Display::fmt(len, f)?;
244 f.write_str(", but it must be at most ")?;
245
246 Display::fmt(&AUDIT_REASON_MAX, f)
247 }
248 ValidationErrorType::AutoModerationBlockActionCustomMessageLimit { len } => {
249 f.write_str("provided auto moderation block action custom message length is ")?;
250 Display::fmt(len, f)?;
251 f.write_str(", but it must be at most ")?;
252
253 Display::fmt(&AUTO_MODERATION_ACTION_BLOCK_CUSTOM_MESSAGE_LENGTH_MAX, f)
254 }
255 ValidationErrorType::AutoModerationMetadataMentionTotalLimit { limit } => {
256 f.write_str("provided auto moderation metadata mention_total_limit is ")?;
257 Display::fmt(limit, f)?;
258 f.write_str(", but it must be at most ")?;
259
260 Display::fmt(&AUTO_MODERATION_METADATA_MENTION_TOTAL_LIMIT, f)
261 }
262 ValidationErrorType::AutoModerationMetadataAllowList { len } => {
263 f.write_str("provided auto moderation metadata allow_list length is ")?;
264 Display::fmt(len, f)?;
265 f.write_str(", but it must be at most ")?;
266
267 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_MAX, f)
268 }
269 ValidationErrorType::AutoModerationMetadataAllowListItem { len, substring } => {
270 f.write_str("provided auto moderation metadata allow_list item ")?;
271 Display::fmt(substring, f)?;
272 f.write_str(" length is ")?;
273 Display::fmt(len, f)?;
274 f.write_str(", but it must be at most ")?;
275
276 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_LENGTH_MAX, f)
277 }
278 ValidationErrorType::AutoModerationMetadataKeywordFilter { len } => {
279 f.write_str("provided auto moderation metadata keyword_filter length is ")?;
280 Display::fmt(len, f)?;
281 f.write_str(", but it must be at most ")?;
282
283 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_FILTER_MAX, f)
284 }
285 ValidationErrorType::AutoModerationMetadataKeywordFilterItem { len, substring } => {
286 f.write_str("provided auto moderation metadata keyword_filter item ")?;
287 Display::fmt(substring, f)?;
288 f.write_str(" length is ")?;
289 Display::fmt(len, f)?;
290 f.write_str(", but it must be at most ")?;
291
292 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_FILTER_LENGTH_MAX, f)
293 }
294 ValidationErrorType::AutoModerationMetadataPresetAllowList { len } => {
295 f.write_str("provided auto moderation metadata allow_list length is ")?;
296 Display::fmt(len, f)?;
297 f.write_str(", but it must be at most ")?;
298
299 Display::fmt(&AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_MAX, f)
300 }
301 ValidationErrorType::AutoModerationMetadataPresetAllowListItem { len, substring } => {
302 f.write_str("provided auto moderation metadata allow_list item ")?;
303 Display::fmt(substring, f)?;
304 f.write_str(" length is ")?;
305 Display::fmt(len, f)?;
306 f.write_str(", but it must be at most ")?;
307
308 Display::fmt(&AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_LENGTH_MAX, f)
309 }
310 ValidationErrorType::AutoModerationActionMetadataDurationSeconds { seconds } => {
311 f.write_str("provided auto moderation action timeout duration is ")?;
312 Display::fmt(seconds, f)?;
313 f.write_str(", but it must be at most ")?;
314
315 Display::fmt(&AUTO_MODERATION_ACTION_METADATA_DURATION_SECONDS_MAX, f)
316 }
317 ValidationErrorType::AutoModerationMetadataRegexPatterns { len } => {
318 f.write_str("provided auto moderation metadata regex_patterns length is ")?;
319 Display::fmt(len, f)?;
320 f.write_str(", but it must be at most ")?;
321
322 Display::fmt(&AUTO_MODERATION_METADATA_REGEX_PATTERNS_MAX, f)
323 }
324 ValidationErrorType::AutoModerationMetadataRegexPatternsItem { len, substring } => {
325 f.write_str("provided auto moderation metadata regex_patterns item ")?;
326 Display::fmt(substring, f)?;
327 f.write_str(" length is ")?;
328 Display::fmt(len, f)?;
329 f.write_str(", but it must be at most ")?;
330
331 Display::fmt(&AUTO_MODERATION_METADATA_REGEX_PATTERNS_LENGTH_MAX, f)
332 }
333 ValidationErrorType::AutoModerationExemptRoles { len } => {
334 f.write_str("provided auto moderation exempt_roles length is ")?;
335 Display::fmt(len, f)?;
336 f.write_str(", but it must be at most ")?;
337
338 Display::fmt(&AUTO_MODERATION_EXEMPT_ROLES_MAX, f)
339 }
340 ValidationErrorType::AutoModerationExemptChannels { len } => {
341 f.write_str("provided auto moderation exempt_channels length is ")?;
342 Display::fmt(len, f)?;
343 f.write_str(", but it must be at most ")?;
344
345 Display::fmt(&AUTO_MODERATION_EXEMPT_CHANNELS_MAX, f)
346 }
347 ValidationErrorType::Bio { len } => {
348 f.write_str("provided bio length is ")?;
349 Display::fmt(len, f)?;
350
351 f.write_str(", but it must be at least")?;
352 Display::fmt(&BIO_LIMIT_MIN, f)?;
353
354 f.write_str(" and at most ")?;
355 Display::fmt(&BIO_LIMIT_MAX, f)
356 }
357 ValidationErrorType::BulkGuildBanDeleteMessageSeconds {
358 seconds: delete_message_seconds,
359 } => {
360 f.write_str("provided bulk guild ban delete_message_seconds is ")?;
361 Display::fmt(delete_message_seconds, f)?;
362 f.write_str(", but it must be at most ")?;
363
364 Display::fmt(&BULK_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX, f)
365 }
366 ValidationErrorType::BulkGuildBanUsers { len } => {
367 f.write_str("provided bulk guild ban users has ")?;
368 Display::fmt(len, f)?;
369 f.write_str("entries, but it must be at most ")?;
370
371 Display::fmt(&BULK_GUILD_BAN_USER_LIMIT_MAX, f)
372 }
373 ValidationErrorType::CreateGuildBanDeleteMessageSeconds {
374 seconds: delete_message_seconds,
375 } => {
376 f.write_str("provided create guild ban delete_message_seconds is ")?;
377 Display::fmt(delete_message_seconds, f)?;
378 f.write_str(", but it must be at most ")?;
379
380 Display::fmt(&CREATE_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX, f)
381 }
382 ValidationErrorType::CommunicationDisabledUntil { .. } => {
383 f.write_str("provided timestamp is too far in the future")
384 }
385 ValidationErrorType::GetChannelMessages { limit } => {
386 f.write_str("provided get guild members limit is ")?;
387 Display::fmt(limit, f)?;
388 f.write_str(", but it must be at least ")?;
389 Display::fmt(&GET_CHANNEL_MESSAGES_LIMIT_MIN, f)?;
390 f.write_str(" and at most ")?;
391
392 Display::fmt(&GET_CHANNEL_MESSAGES_LIMIT_MAX, f)
393 }
394 ValidationErrorType::GetCurrentUserGuilds { limit } => {
395 f.write_str("provided get current user guilds limit is ")?;
396 Display::fmt(limit, f)?;
397 f.write_str(", but it must be at least ")?;
398 Display::fmt(&GET_CURRENT_USER_GUILDS_LIMIT_MIN, f)?;
399 f.write_str(" and at most ")?;
400
401 Display::fmt(&GET_CURRENT_USER_GUILDS_LIMIT_MAX, f)
402 }
403 ValidationErrorType::GetEntitlements { limit } => {
404 f.write_str("provided get entitlements limit is ")?;
405 Display::fmt(limit, f)?;
406 f.write_str(", but it must be at least ")?;
407 Display::fmt(&GET_ENTITLEMENTS_LIMIT_MIN, f)?;
408 f.write_str(" and at most ")?;
409
410 Display::fmt(&GET_ENTITLEMENTS_LIMIT_MAX, f)
411 }
412 ValidationErrorType::GetGuildAuditLog { limit } => {
413 f.write_str("provided get guild audit log limit is ")?;
414 Display::fmt(limit, f)?;
415 f.write_str(", but it must be at least ")?;
416 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MIN, f)?;
417 f.write_str(" and at most ")?;
418
419 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MAX, f)
420 }
421 ValidationErrorType::GetGuildBans { limit } => {
422 f.write_str("provided get guild bans limit is ")?;
423 Display::fmt(limit, f)?;
424 f.write_str(", but it must be at most ")?;
425
426 Display::fmt(&GET_GUILD_BANS_LIMIT_MAX, f)
427 }
428 ValidationErrorType::GetGuildMembers { limit } => {
429 f.write_str("provided get guild members limit is ")?;
430 Display::fmt(limit, f)?;
431 f.write_str(", but it must be at least ")?;
432 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MIN, f)?;
433 f.write_str(" and at most ")?;
434
435 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MAX, f)
436 }
437 ValidationErrorType::GetReactions { limit } => {
438 f.write_str("provided get reactions limit is ")?;
439 Display::fmt(limit, f)?;
440 f.write_str(", but it must be at least ")?;
441 Display::fmt(&GET_REACTIONS_LIMIT_MIN, f)?;
442 f.write_str(" and at most ")?;
443
444 Display::fmt(&GET_REACTIONS_LIMIT_MAX, f)
445 }
446 ValidationErrorType::GetSKUSubscriptions { limit } => {
447 f.write_str("provided get sku subscriptions limit is ")?;
448 Display::fmt(limit, f)?;
449 f.write_str(", but it must be at least ")?;
450 Display::fmt(&GET_SKU_SUBSCRIPTIONS_LIMIT_MIN, f)?;
451 f.write_str(" and at most ")?;
452
453 Display::fmt(&GET_SKU_SUBSCRIPTIONS_LIMIT_MAX, f)
454 }
455 ValidationErrorType::GuildName { len } => {
456 f.write_str("provided guild name length is ")?;
457 Display::fmt(len, f)?;
458 f.write_str(", but it must be at least ")?;
459 Display::fmt(&GUILD_NAME_LENGTH_MIN, f)?;
460 f.write_str(" and at most ")?;
461
462 Display::fmt(&GUILD_NAME_LENGTH_MAX, f)
463 }
464 ValidationErrorType::GuildPruneDays { days } => {
465 f.write_str("provided prune days is ")?;
466 Display::fmt(days, f)?;
467 f.write_str(", but it must be at least ")?;
468 Display::fmt(&GUILD_PRUNE_DAYS_MIN, f)?;
469 f.write_str(" and at most ")?;
470
471 Display::fmt(&GUILD_PRUNE_DAYS_MAX, f)
472 }
473 ValidationErrorType::InviteMaxAge { max_age } => {
474 f.write_str("provided invite max_age is ")?;
475 Display::fmt(max_age, f)?;
476 f.write_str(", but it must be at most ")?;
477
478 Display::fmt(&INVITE_AGE_MAX, f)
479 }
480 ValidationErrorType::InviteMaxUses { max_uses } => {
481 f.write_str("provided invite max_uses is ")?;
482 Display::fmt(max_uses, f)?;
483 f.write_str(", but it must be at most ")?;
484
485 Display::fmt(&INVITE_USES_MAX, f)
486 }
487 ValidationErrorType::Nickname { len } => {
488 f.write_str("provided nickname length is ")?;
489 Display::fmt(len, f)?;
490 f.write_str(", but it must be at least ")?;
491 Display::fmt(&NICKNAME_LIMIT_MIN, f)?;
492 f.write_str(" and at most ")?;
493
494 Display::fmt(&NICKNAME_LIMIT_MAX, f)
495 }
496 ValidationErrorType::Pin { limit } => {
497 f.write_str("provided pin limit is ")?;
498 Display::fmt(limit, f)?;
499 f.write_str(", but it must be at least ")?;
500 Display::fmt(&PIN_LIMIT_MIN, f)?;
501 f.write_str(" and at most ")?;
502 Display::fmt(&PIN_LIMIT_MAX, f)
503 }
504 ValidationErrorType::ScheduledEventDescription { len } => {
505 f.write_str("provided scheduled event description is length is ")?;
506 Display::fmt(len, f)?;
507 f.write_str(", but it must be at least ")?;
508 Display::fmt(&SCHEDULED_EVENT_DESCRIPTION_MIN, f)?;
509 f.write_str(" and at most ")?;
510
511 Display::fmt(&SCHEDULED_EVENT_DESCRIPTION_MAX, f)
512 }
513 ValidationErrorType::ScheduledEventGetUsers { limit } => {
514 f.write_str("provided scheduled event get users limit is ")?;
515 Display::fmt(limit, f)?;
516 f.write_str(", but it must be at least ")?;
517 Display::fmt(&SCHEDULED_EVENT_GET_USERS_MIN, f)?;
518 f.write_str(" and at most ")?;
519
520 Display::fmt(&SCHEDULED_EVENT_GET_USERS_MAX, f)
521 }
522 ValidationErrorType::ScheduledEventName { len } => {
523 f.write_str("provided scheduled event name is length is ")?;
524 Display::fmt(len, f)?;
525 f.write_str(", but it must be at least ")?;
526 Display::fmt(&SCHEDULED_EVENT_NAME_MIN, f)?;
527 f.write_str(" and at most ")?;
528
529 Display::fmt(&SCHEDULED_EVENT_NAME_MAX, f)
530 }
531 ValidationErrorType::SearchGuildMembers { limit } => {
532 f.write_str("provided search guild members limit is ")?;
533 Display::fmt(limit, f)?;
534 f.write_str(", but it must be at least ")?;
535 Display::fmt(&SEARCH_GUILD_MEMBERS_LIMIT_MIN, f)?;
536 f.write_str(" and at most ")?;
537
538 Display::fmt(&SEARCH_GUILD_MEMBERS_LIMIT_MAX, f)
539 }
540 ValidationErrorType::StageTopic { len } => {
541 f.write_str("provided stage instance topic length is ")?;
542 Display::fmt(len, f)?;
543 f.write_str(", but it must be at least ")?;
544 Display::fmt(&STAGE_TOPIC_LENGTH_MIN, f)?;
545 f.write_str(" and at most ")?;
546
547 Display::fmt(&STAGE_TOPIC_LENGTH_MAX, f)
548 }
549 ValidationErrorType::TemplateDescription { len } => {
550 f.write_str("provided guild template description topic length is ")?;
551 Display::fmt(len, f)?;
552 f.write_str(", but it must be at most ")?;
553
554 Display::fmt(&TEMPLATE_DESCRIPTION_LENGTH_MAX, f)
555 }
556 ValidationErrorType::TemplateName { len } => {
557 f.write_str("provided guild template name length is ")?;
558 Display::fmt(len, f)?;
559 f.write_str(", but it must be at least ")?;
560 Display::fmt(&TEMPLATE_NAME_LENGTH_MIN, f)?;
561 f.write_str(" and at most ")?;
562
563 Display::fmt(&TEMPLATE_NAME_LENGTH_MAX, f)
564 }
565 ValidationErrorType::Username { len, substring }
566 | ValidationErrorType::WebhookUsername { len, substring } => {
567 f.write_str("provided username")?;
568
569 if let Some(len) = len {
570 f.write_str(" length is ")?;
571 Display::fmt(len, f)?;
572 f.write_str(", but it must be at least ")?;
573 Display::fmt(&USERNAME_LIMIT_MIN, f)?;
574 f.write_str(" and at most ")?;
575 Display::fmt(&USERNAME_LIMIT_MAX, f)?;
576 }
577
578 if let Some(substring) = substring {
579 if len.is_some() {
580 f.write_str(", and")?;
581 }
582
583 f.write_str(" cannot contain ")?;
584 Display::fmt(substring, f)?;
585 }
586
587 Ok(())
588 }
589 }
590 }
591}
592
593impl Error for ValidationError {}
594
595#[derive(Debug)]
597pub enum ValidationErrorType {
598 AuditReason {
600 len: usize,
602 },
603 AutoModerationBlockActionCustomMessageLimit {
605 len: usize,
607 },
608 AutoModerationMetadataMentionTotalLimit {
610 limit: u8,
612 },
613 AutoModerationMetadataKeywordFilter {
615 len: usize,
617 },
618 AutoModerationMetadataKeywordFilterItem {
620 len: usize,
622 substring: String,
624 },
625 AutoModerationMetadataAllowList {
627 len: usize,
629 },
630 AutoModerationMetadataAllowListItem {
632 len: usize,
634 substring: String,
636 },
637 AutoModerationMetadataPresetAllowList {
639 len: usize,
641 },
642 AutoModerationMetadataPresetAllowListItem {
644 len: usize,
646 substring: String,
648 },
649 AutoModerationActionMetadataDurationSeconds {
651 seconds: u32,
653 },
654 AutoModerationMetadataRegexPatterns {
656 len: usize,
658 },
659 AutoModerationMetadataRegexPatternsItem {
661 len: usize,
663 substring: String,
665 },
666 AutoModerationExemptRoles {
668 len: usize,
670 },
671 AutoModerationExemptChannels {
673 len: usize,
675 },
676 Bio {
678 len: usize,
680 },
681 BulkGuildBanDeleteMessageSeconds {
683 seconds: u32,
685 },
686 BulkGuildBanUsers {
688 len: usize,
690 },
691 CreateGuildBanDeleteMessageSeconds {
693 seconds: u32,
695 },
696 CommunicationDisabledUntil {
698 timestamp: Timestamp,
700 },
701 GetChannelMessages {
703 limit: u16,
705 },
706 GetCurrentUserGuilds {
708 limit: u16,
710 },
711 GetEntitlements {
713 limit: u8,
715 },
716 GetGuildAuditLog {
718 limit: u16,
720 },
721 GetGuildBans {
723 limit: u16,
725 },
726 GetGuildMembers {
728 limit: u16,
730 },
731 GetReactions {
733 limit: u16,
735 },
736 GetSKUSubscriptions {
738 limit: u8,
740 },
741 GuildName {
743 len: usize,
745 },
746 GuildPruneDays {
748 days: u16,
750 },
751 InviteMaxAge {
753 max_age: u32,
755 },
756 InviteMaxUses {
758 max_uses: u16,
760 },
761 Nickname {
763 len: usize,
765 },
766 Pin {
768 limit: u16,
770 },
771 ScheduledEventDescription {
773 len: usize,
775 },
776 ScheduledEventGetUsers {
778 limit: u16,
780 },
781 ScheduledEventName {
783 len: usize,
785 },
786 SearchGuildMembers {
788 limit: u16,
790 },
791 StageTopic {
793 len: usize,
795 },
796 TemplateDescription {
798 len: usize,
800 },
801 TemplateName {
803 len: usize,
805 },
806 Username {
808 len: Option<usize>,
810 substring: Option<&'static str>,
812 },
813 WebhookUsername {
815 len: Option<usize>,
817 substring: Option<&'static str>,
819 },
820}
821
822pub fn audit_reason(audit_reason: impl AsRef<str>) -> Result<(), ValidationError> {
834 let len = audit_reason.as_ref().chars().count();
835
836 if len <= AUDIT_REASON_MAX {
837 Ok(())
838 } else {
839 Err(ValidationError {
840 kind: ValidationErrorType::AuditReason { len },
841 })
842 }
843}
844
845pub fn auto_moderation_block_action_custom_message_limit(
858 custom_message: impl AsRef<str>,
859) -> Result<(), ValidationError> {
860 let len = custom_message.as_ref().chars().count();
861
862 if len <= AUTO_MODERATION_ACTION_BLOCK_CUSTOM_MESSAGE_LENGTH_MAX {
863 Ok(())
864 } else {
865 Err(ValidationError {
866 kind: ValidationErrorType::AutoModerationBlockActionCustomMessageLimit { len },
867 })
868 }
869}
870
871pub const fn auto_moderation_metadata_mention_total_limit(
884 limit: u8,
885) -> Result<(), ValidationError> {
886 if limit <= AUTO_MODERATION_METADATA_MENTION_TOTAL_LIMIT {
887 Ok(())
888 } else {
889 Err(ValidationError {
890 kind: ValidationErrorType::AutoModerationMetadataMentionTotalLimit { limit },
891 })
892 }
893}
894
895pub fn auto_moderation_metadata_keyword_filter(
912 keywords: &[impl AsRef<str>],
913) -> Result<(), ValidationError> {
914 let len = keywords.len();
915
916 if len <= AUTO_MODERATION_METADATA_KEYWORD_FILTER_MAX {
917 for keyword in keywords {
918 auto_moderation_metadata_keyword_filter_item(keyword)?;
919 }
920
921 Ok(())
922 } else {
923 Err(ValidationError {
924 kind: ValidationErrorType::AutoModerationMetadataKeywordFilter { len },
925 })
926 }
927}
928
929pub fn auto_moderation_metadata_keyword_filter_item(
942 keyword: impl AsRef<str>,
943) -> Result<(), ValidationError> {
944 let len = keyword.as_ref().chars().count();
945
946 if len <= AUTO_MODERATION_METADATA_KEYWORD_FILTER_LENGTH_MAX {
947 Ok(())
948 } else {
949 Err(ValidationError {
950 kind: ValidationErrorType::AutoModerationMetadataKeywordFilterItem {
951 len,
952 substring: keyword.as_ref().to_string(),
953 },
954 })
955 }
956}
957
958pub fn auto_moderation_metadata_keyword_allow_list(
975 keywords: &[impl AsRef<str>],
976) -> Result<(), ValidationError> {
977 let len = keywords.len();
978
979 if len <= AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_MAX {
980 for keyword in keywords {
981 auto_moderation_metadata_keyword_allow_list_item(keyword)?;
982 }
983
984 Ok(())
985 } else {
986 Err(ValidationError {
987 kind: ValidationErrorType::AutoModerationMetadataAllowList { len },
988 })
989 }
990}
991
992pub fn auto_moderation_metadata_keyword_allow_list_item(
1005 keyword: impl AsRef<str>,
1006) -> Result<(), ValidationError> {
1007 let len = keyword.as_ref().chars().count();
1008
1009 if len <= AUTO_MODERATION_METADATA_KEYWORD_FILTER_LENGTH_MAX {
1010 Ok(())
1011 } else {
1012 Err(ValidationError {
1013 kind: ValidationErrorType::AutoModerationMetadataAllowListItem {
1014 len,
1015 substring: keyword.as_ref().to_string(),
1016 },
1017 })
1018 }
1019}
1020
1021pub fn auto_moderation_metadata_preset_allow_list(
1038 keywords: &[impl AsRef<str>],
1039) -> Result<(), ValidationError> {
1040 let len = keywords.len();
1041
1042 if len <= AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_MAX {
1043 for keyword in keywords {
1044 auto_moderation_metadata_preset_allow_list_item(keyword)?;
1045 }
1046
1047 Ok(())
1048 } else {
1049 Err(ValidationError {
1050 kind: ValidationErrorType::AutoModerationMetadataPresetAllowList { len },
1051 })
1052 }
1053}
1054
1055pub fn auto_moderation_metadata_preset_allow_list_item(
1068 keyword: impl AsRef<str>,
1069) -> Result<(), ValidationError> {
1070 let len = keyword.as_ref().chars().count();
1071
1072 if len <= AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_LENGTH_MAX {
1073 Ok(())
1074 } else {
1075 Err(ValidationError {
1076 kind: ValidationErrorType::AutoModerationMetadataPresetAllowListItem {
1077 len,
1078 substring: keyword.as_ref().to_string(),
1079 },
1080 })
1081 }
1082}
1083
1084pub fn auto_moderation_metadata_regex_patterns(
1101 patterns: &[impl AsRef<str>],
1102) -> Result<(), ValidationError> {
1103 let len = patterns.len();
1104
1105 if len <= AUTO_MODERATION_METADATA_REGEX_PATTERNS_MAX {
1106 for pattern in patterns {
1107 auto_moderation_metadata_regex_patterns_item(pattern)?;
1108 }
1109
1110 Ok(())
1111 } else {
1112 Err(ValidationError {
1113 kind: ValidationErrorType::AutoModerationMetadataRegexPatterns { len },
1114 })
1115 }
1116}
1117
1118pub fn auto_moderation_metadata_regex_patterns_item(
1131 pattern: impl AsRef<str>,
1132) -> Result<(), ValidationError> {
1133 let len = pattern.as_ref().chars().count();
1134
1135 if len <= AUTO_MODERATION_METADATA_REGEX_PATTERNS_LENGTH_MAX {
1136 Ok(())
1137 } else {
1138 Err(ValidationError {
1139 kind: ValidationErrorType::AutoModerationMetadataRegexPatternsItem {
1140 len,
1141 substring: pattern.as_ref().to_string(),
1142 },
1143 })
1144 }
1145}
1146
1147pub const fn auto_moderation_action_metadata_duration_seconds(
1161 seconds: u32,
1162) -> Result<(), ValidationError> {
1163 if seconds <= AUTO_MODERATION_ACTION_METADATA_DURATION_SECONDS_MAX {
1164 Ok(())
1165 } else {
1166 Err(ValidationError {
1167 kind: ValidationErrorType::AutoModerationActionMetadataDurationSeconds { seconds },
1168 })
1169 }
1170}
1171
1172pub const fn auto_moderation_exempt_roles(roles: &[Id<RoleMarker>]) -> Result<(), ValidationError> {
1185 let len = roles.len();
1186
1187 if len <= AUTO_MODERATION_EXEMPT_ROLES_MAX {
1188 Ok(())
1189 } else {
1190 Err(ValidationError {
1191 kind: ValidationErrorType::AutoModerationExemptRoles { len },
1192 })
1193 }
1194}
1195
1196pub const fn auto_moderation_exempt_channels(
1209 channels: &[Id<ChannelMarker>],
1210) -> Result<(), ValidationError> {
1211 let len = channels.len();
1212
1213 if len <= AUTO_MODERATION_EXEMPT_CHANNELS_MAX {
1214 Ok(())
1215 } else {
1216 Err(ValidationError {
1217 kind: ValidationErrorType::AutoModerationExemptChannels { len },
1218 })
1219 }
1220}
1221
1222pub fn bio(bio: impl AsRef<str>) -> Result<(), ValidationError> {
1235 let len = bio.as_ref().chars().count();
1236
1237 if (BIO_LIMIT_MIN..=BIO_LIMIT_MAX).contains(&len) {
1238 Ok(())
1239 } else {
1240 Err(ValidationError {
1241 kind: ValidationErrorType::Bio { len },
1242 })
1243 }
1244}
1245
1246pub const fn bulk_guild_ban_delete_message_seconds(seconds: u32) -> Result<(), ValidationError> {
1260 if seconds <= BULK_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX {
1261 Ok(())
1262 } else {
1263 Err(ValidationError {
1264 kind: ValidationErrorType::BulkGuildBanDeleteMessageSeconds { seconds },
1265 })
1266 }
1267}
1268
1269pub const fn bulk_guild_ban_users(user_ids: &[Id<UserMarker>]) -> Result<(), ValidationError> {
1281 if user_ids.len() > BULK_GUILD_BAN_USER_LIMIT_MAX {
1282 return Err(ValidationError {
1283 kind: ValidationErrorType::BulkGuildBanUsers {
1284 len: user_ids.len(),
1285 },
1286 });
1287 }
1288
1289 Ok(())
1290}
1291
1292pub const fn create_guild_ban_delete_message_seconds(seconds: u32) -> Result<(), ValidationError> {
1306 if seconds <= CREATE_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX {
1307 Ok(())
1308 } else {
1309 Err(ValidationError {
1310 kind: ValidationErrorType::CreateGuildBanDeleteMessageSeconds { seconds },
1311 })
1312 }
1313}
1314
1315#[allow(clippy::cast_possible_wrap)] pub fn communication_disabled_until(timestamp: Timestamp) -> Result<(), ValidationError> {
1322 let now = SystemTime::now()
1323 .duration_since(UNIX_EPOCH)
1324 .map_err(|_| ValidationError {
1325 kind: ValidationErrorType::CommunicationDisabledUntil { timestamp },
1326 })?;
1327
1328 let end = timestamp.as_secs();
1329
1330 if end - now.as_secs() as i64 <= COMMUNICATION_DISABLED_MAX_DURATION {
1331 Ok(())
1332 } else {
1333 Err(ValidationError {
1334 kind: ValidationErrorType::CommunicationDisabledUntil { timestamp },
1335 })
1336 }
1337}
1338
1339pub const fn get_channel_messages_limit(limit: u16) -> Result<(), ValidationError> {
1352 if limit >= GET_CHANNEL_MESSAGES_LIMIT_MIN && limit <= GET_CHANNEL_MESSAGES_LIMIT_MAX {
1353 Ok(())
1354 } else {
1355 Err(ValidationError {
1356 kind: ValidationErrorType::GetChannelMessages { limit },
1357 })
1358 }
1359}
1360
1361pub const fn get_current_user_guilds_limit(limit: u16) -> Result<(), ValidationError> {
1374 if limit >= GET_CURRENT_USER_GUILDS_LIMIT_MIN && limit <= GET_CURRENT_USER_GUILDS_LIMIT_MAX {
1375 Ok(())
1376 } else {
1377 Err(ValidationError {
1378 kind: ValidationErrorType::GetCurrentUserGuilds { limit },
1379 })
1380 }
1381}
1382
1383pub const fn get_entitlements_limit(limit: u8) -> Result<(), ValidationError> {
1396 if limit >= GET_ENTITLEMENTS_LIMIT_MIN && limit <= GET_ENTITLEMENTS_LIMIT_MAX {
1397 Ok(())
1398 } else {
1399 Err(ValidationError {
1400 kind: ValidationErrorType::GetEntitlements { limit },
1401 })
1402 }
1403}
1404
1405pub const fn get_guild_audit_log_limit(limit: u16) -> Result<(), ValidationError> {
1418 if limit >= GET_GUILD_AUDIT_LOG_LIMIT_MIN && limit <= GET_GUILD_AUDIT_LOG_LIMIT_MAX {
1419 Ok(())
1420 } else {
1421 Err(ValidationError {
1422 kind: ValidationErrorType::GetGuildAuditLog { limit },
1423 })
1424 }
1425}
1426
1427pub const fn get_guild_bans_limit(limit: u16) -> Result<(), ValidationError> {
1439 if limit <= GET_GUILD_BANS_LIMIT_MAX {
1440 Ok(())
1441 } else {
1442 Err(ValidationError {
1443 kind: ValidationErrorType::GetGuildBans { limit },
1444 })
1445 }
1446}
1447
1448pub const fn get_guild_members_limit(limit: u16) -> Result<(), ValidationError> {
1461 if limit >= GET_GUILD_MEMBERS_LIMIT_MIN && limit <= GET_GUILD_MEMBERS_LIMIT_MAX {
1462 Ok(())
1463 } else {
1464 Err(ValidationError {
1465 kind: ValidationErrorType::GetGuildMembers { limit },
1466 })
1467 }
1468}
1469
1470pub const fn get_reactions_limit(limit: u16) -> Result<(), ValidationError> {
1482 if limit >= GET_REACTIONS_LIMIT_MIN && limit <= GET_REACTIONS_LIMIT_MAX {
1483 Ok(())
1484 } else {
1485 Err(ValidationError {
1486 kind: ValidationErrorType::GetReactions { limit },
1487 })
1488 }
1489}
1490
1491pub const fn get_sku_subscriptions_limit(limit: u8) -> Result<(), ValidationError> {
1504 if limit >= GET_SKU_SUBSCRIPTIONS_LIMIT_MIN && limit <= GET_SKU_SUBSCRIPTIONS_LIMIT_MAX {
1505 Ok(())
1506 } else {
1507 Err(ValidationError {
1508 kind: ValidationErrorType::GetSKUSubscriptions { limit },
1509 })
1510 }
1511}
1512
1513pub fn guild_name(name: impl AsRef<str>) -> Result<(), ValidationError> {
1525 let len = name.as_ref().chars().count();
1526
1527 if (GUILD_NAME_LENGTH_MIN..=GUILD_NAME_LENGTH_MAX).contains(&len) {
1528 Ok(())
1529 } else {
1530 Err(ValidationError {
1531 kind: ValidationErrorType::GuildName { len },
1532 })
1533 }
1534}
1535
1536pub const fn guild_prune_days(days: u16) -> Result<(), ValidationError> {
1548 if days >= GUILD_PRUNE_DAYS_MIN && days <= GUILD_PRUNE_DAYS_MAX {
1549 Ok(())
1550 } else {
1551 Err(ValidationError {
1552 kind: ValidationErrorType::GuildPruneDays { days },
1553 })
1554 }
1555}
1556
1557pub const fn invite_max_age(max_age: u32) -> Result<(), ValidationError> {
1569 if max_age <= INVITE_AGE_MAX {
1570 Ok(())
1571 } else {
1572 Err(ValidationError {
1573 kind: ValidationErrorType::InviteMaxAge { max_age },
1574 })
1575 }
1576}
1577
1578pub const fn invite_max_uses(max_uses: u16) -> Result<(), ValidationError> {
1590 if max_uses <= INVITE_USES_MAX {
1591 Ok(())
1592 } else {
1593 Err(ValidationError {
1594 kind: ValidationErrorType::InviteMaxUses { max_uses },
1595 })
1596 }
1597}
1598
1599pub fn nickname(nickname: impl AsRef<str>) -> Result<(), ValidationError> {
1611 let len = nickname.as_ref().chars().count();
1612
1613 if (NICKNAME_LIMIT_MIN..=NICKNAME_LIMIT_MAX).contains(&len) {
1614 Ok(())
1615 } else {
1616 Err(ValidationError {
1617 kind: ValidationErrorType::Nickname { len },
1618 })
1619 }
1620}
1621
1622pub fn pin_limit(limit: u16) -> Result<(), ValidationError> {
1634 if (PIN_LIMIT_MIN..=PIN_LIMIT_MAX).contains(&limit) {
1635 Ok(())
1636 } else {
1637 Err(ValidationError {
1638 kind: ValidationErrorType::Pin { limit },
1639 })
1640 }
1641}
1642
1643pub fn scheduled_event_description(description: impl AsRef<str>) -> Result<(), ValidationError> {
1657 let len = description.as_ref().chars().count();
1658
1659 if (SCHEDULED_EVENT_DESCRIPTION_MIN..=SCHEDULED_EVENT_DESCRIPTION_MAX).contains(&len) {
1660 Ok(())
1661 } else {
1662 Err(ValidationError {
1663 kind: ValidationErrorType::ScheduledEventDescription { len },
1664 })
1665 }
1666}
1667
1668pub const fn scheduled_event_get_users(limit: u16) -> Result<(), ValidationError> {
1681 if limit >= SCHEDULED_EVENT_GET_USERS_MIN && limit <= SCHEDULED_EVENT_GET_USERS_MAX {
1682 Ok(())
1683 } else {
1684 Err(ValidationError {
1685 kind: ValidationErrorType::ScheduledEventGetUsers { limit },
1686 })
1687 }
1688}
1689
1690pub fn scheduled_event_name(name: impl AsRef<str>) -> Result<(), ValidationError> {
1702 let len = name.as_ref().chars().count();
1703
1704 if (SCHEDULED_EVENT_NAME_MIN..=SCHEDULED_EVENT_NAME_MAX).contains(&len) {
1705 Ok(())
1706 } else {
1707 Err(ValidationError {
1708 kind: ValidationErrorType::ScheduledEventName { len },
1709 })
1710 }
1711}
1712
1713pub const fn search_guild_members_limit(limit: u16) -> Result<(), ValidationError> {
1726 if limit >= SEARCH_GUILD_MEMBERS_LIMIT_MIN && limit <= SEARCH_GUILD_MEMBERS_LIMIT_MAX {
1727 Ok(())
1728 } else {
1729 Err(ValidationError {
1730 kind: ValidationErrorType::SearchGuildMembers { limit },
1731 })
1732 }
1733}
1734
1735pub fn stage_topic(topic: impl AsRef<str>) -> Result<(), ValidationError> {
1747 let len = topic.as_ref().chars().count();
1748
1749 if (STAGE_TOPIC_LENGTH_MIN..=STAGE_TOPIC_LENGTH_MAX).contains(&len) {
1750 Ok(())
1751 } else {
1752 Err(ValidationError {
1753 kind: ValidationErrorType::StageTopic { len },
1754 })
1755 }
1756}
1757
1758pub fn template_description(description: impl AsRef<str>) -> Result<(), ValidationError> {
1770 let len = description.as_ref().chars().count();
1771
1772 if len <= TEMPLATE_DESCRIPTION_LENGTH_MAX {
1773 Ok(())
1774 } else {
1775 Err(ValidationError {
1776 kind: ValidationErrorType::TemplateDescription { len },
1777 })
1778 }
1779}
1780
1781pub fn template_name(name: impl AsRef<str>) -> Result<(), ValidationError> {
1793 let len = name.as_ref().chars().count();
1794
1795 if (TEMPLATE_NAME_LENGTH_MIN..=TEMPLATE_NAME_LENGTH_MAX).contains(&len) {
1796 Ok(())
1797 } else {
1798 Err(ValidationError {
1799 kind: ValidationErrorType::TemplateName { len },
1800 })
1801 }
1802}
1803
1804pub fn username(value: impl AsRef<str>) -> Result<(), ValidationError> {
1817 let value = value.as_ref();
1818 let len = value.chars().count();
1819
1820 let range = USERNAME_LIMIT_MIN..=USERNAME_LIMIT_MAX;
1821 let invalid_len = (!range.contains(&len)).then_some(len);
1822
1823 let invalid_substring = USERNAME_INVALID_SUBSTRINGS
1824 .into_iter()
1825 .find(|invalid_substring| value.contains(invalid_substring))
1826 .or_else(|| {
1827 USERNAME_INVALID_STRINGS
1828 .into_iter()
1829 .find(|invalid_string| value == *invalid_string)
1830 });
1831
1832 if invalid_len.is_none() && invalid_substring.is_none() {
1833 Ok(())
1834 } else {
1835 Err(ValidationError {
1836 kind: ValidationErrorType::Username {
1837 len: invalid_len,
1838 substring: invalid_substring,
1839 },
1840 })
1841 }
1842}
1843
1844pub fn webhook_username(value: impl AsRef<str>) -> Result<(), ValidationError> {
1857 let value = value.as_ref();
1858 let len = value.chars().count();
1859
1860 let range = WEBHOOK_USERNAME_LIMIT_MIN..=WEBHOOK_USERNAME_LIMIT_MAX;
1861 let invalid_len = (!range.contains(&len)).then_some(len);
1862
1863 let invalid_substring = WEBHOOK_INVALID_STRINGS
1864 .into_iter()
1865 .find(|invalid_string| value == *invalid_string);
1866
1867 if invalid_len.is_none() && invalid_substring.is_none() {
1868 Ok(())
1869 } else {
1870 Err(ValidationError {
1871 kind: ValidationErrorType::WebhookUsername {
1872 len: invalid_len,
1873 substring: invalid_substring,
1874 },
1875 })
1876 }
1877}
1878
1879#[cfg(test)]
1880mod tests {
1881 use super::*;
1882
1883 #[test]
1884 fn username_variants() {
1885 let expected = format!(
1886 "provided username length is 200, but it must be at least {USERNAME_LIMIT_MIN} and at \
1887 most {USERNAME_LIMIT_MAX}, and cannot contain :"
1888 );
1889 let actual = ValidationError {
1890 kind: ValidationErrorType::Username {
1891 len: Some(200),
1892 substring: Some(":"),
1893 },
1894 };
1895 assert_eq!(expected, actual.to_string());
1896
1897 let expected = format!(
1898 "provided username length is 200, but it must be at least {USERNAME_LIMIT_MIN} and at \
1899 most {USERNAME_LIMIT_MAX}",
1900 );
1901 let actual = ValidationError {
1902 kind: ValidationErrorType::Username {
1903 len: Some(200),
1904 substring: None,
1905 },
1906 };
1907 assert_eq!(expected, actual.to_string());
1908
1909 let expected = "provided username cannot contain :".to_string();
1910 let actual = ValidationError {
1911 kind: ValidationErrorType::Username {
1912 len: None,
1913 substring: Some(":"),
1914 },
1915 };
1916 assert_eq!(expected, actual.to_string());
1917 }
1918
1919 #[test]
1920 fn audit_reason_length() {
1921 assert!(audit_reason("").is_ok());
1922 assert!(audit_reason("a").is_ok());
1923 assert!(audit_reason("a".repeat(500)).is_ok());
1924 assert!(audit_reason("a".repeat(512)).is_ok());
1925
1926 assert!(audit_reason("a".repeat(513)).is_err());
1927 }
1928
1929 #[test]
1930 fn auto_moderation_block_action_custom_message() {
1931 assert!(auto_moderation_block_action_custom_message_limit("").is_ok());
1932 assert!(auto_moderation_block_action_custom_message_limit("a".repeat(150)).is_ok());
1933 assert!(matches!(
1934 auto_moderation_block_action_custom_message_limit("a".repeat(151))
1935 .unwrap_err()
1936 .kind,
1937 ValidationErrorType::AutoModerationBlockActionCustomMessageLimit { len: 151 }
1938 ));
1939 }
1940
1941 #[test]
1942 fn auto_moderation_metadata_mention_total() {
1943 assert!(auto_moderation_metadata_mention_total_limit(0).is_ok());
1944 assert!(auto_moderation_metadata_mention_total_limit(1).is_ok());
1945 assert!(auto_moderation_metadata_mention_total_limit(50).is_ok());
1946
1947 assert!(auto_moderation_metadata_mention_total_limit(51).is_err());
1948 }
1949
1950 #[test]
1951 fn auto_moderation_metadata_keyword_filter_max() {
1952 let mut keywords = (0..1000).map(|_| "a").collect::<Vec<_>>();
1953
1954 assert!(auto_moderation_metadata_keyword_filter(&[] as &[&str]).is_ok());
1955 assert!(auto_moderation_metadata_keyword_filter(&["a".repeat(60)]).is_ok());
1956 assert!(auto_moderation_metadata_keyword_filter(&keywords).is_ok());
1957
1958 keywords.push("a");
1959
1960 assert!(auto_moderation_metadata_keyword_filter(&["a".repeat(61)]).is_err());
1961 assert!(auto_moderation_metadata_keyword_filter(&keywords).is_err());
1962 }
1963
1964 #[test]
1965 fn auto_moderation_metadata_keyword_allow_list_max() {
1966 let mut allow_list = (0..100).map(|_| "a").collect::<Vec<_>>();
1967
1968 assert!(auto_moderation_metadata_keyword_allow_list(&[] as &[&str]).is_ok());
1969 assert!(auto_moderation_metadata_keyword_allow_list(&["a".repeat(60)]).is_ok());
1970
1971 allow_list.push("a");
1972
1973 assert!(auto_moderation_metadata_keyword_allow_list(&["a".repeat(61)]).is_err());
1974 assert!(auto_moderation_metadata_keyword_allow_list(&allow_list).is_err());
1975 }
1976
1977 #[test]
1978 fn auto_moderation_metadata_preset_allow_list_max() {
1979 let mut allow_list = (0..1000).map(|_| "a").collect::<Vec<_>>();
1980
1981 assert!(auto_moderation_metadata_preset_allow_list(&[] as &[&str]).is_ok());
1982 assert!(auto_moderation_metadata_preset_allow_list(&["a".repeat(60)]).is_ok());
1983
1984 allow_list.push("a");
1985
1986 assert!(auto_moderation_metadata_preset_allow_list(&["a".repeat(61)]).is_err());
1987 assert!(auto_moderation_metadata_preset_allow_list(&allow_list).is_err());
1988 }
1989
1990 #[test]
1991 fn auto_moderation_metadata_regex_patterns_max() {
1992 let mut patterns = (0..10).map(|_| "a").collect::<Vec<_>>();
1993
1994 assert!(auto_moderation_metadata_regex_patterns(&[] as &[&str]).is_ok());
1995 assert!(auto_moderation_metadata_regex_patterns(&["a".repeat(260)]).is_ok());
1996
1997 patterns.push("a");
1998
1999 assert!(auto_moderation_metadata_regex_patterns(&["a".repeat(261)]).is_err());
2000 assert!(auto_moderation_metadata_regex_patterns(&patterns).is_err());
2001 }
2002
2003 #[test]
2004 fn auto_moderation_exempt_roles_max() {
2005 let mut roles = (1..=20).map(Id::new).collect::<Vec<_>>();
2006
2007 assert!(auto_moderation_exempt_roles(&[]).is_ok());
2008 assert!(auto_moderation_exempt_roles(&roles).is_ok());
2009
2010 roles.push(Id::new(21));
2011
2012 assert!(auto_moderation_exempt_roles(&roles).is_err());
2013 }
2014
2015 #[test]
2016 fn auto_moderation_exempt_channels_max() {
2017 let mut channels = (1..=50).map(Id::new).collect::<Vec<_>>();
2018
2019 assert!(auto_moderation_exempt_channels(&[]).is_ok());
2020 assert!(auto_moderation_exempt_channels(&channels).is_ok());
2021
2022 channels.push(Id::new(51));
2023
2024 assert!(auto_moderation_exempt_channels(&channels).is_err());
2025 }
2026
2027 #[test]
2028 fn auto_moderation_action_metadata_duration_seconds_max() {
2029 assert!(auto_moderation_action_metadata_duration_seconds(0).is_ok());
2030 assert!(auto_moderation_action_metadata_duration_seconds(1).is_ok());
2031 assert!(auto_moderation_action_metadata_duration_seconds(2_419_200).is_ok());
2032
2033 assert!(auto_moderation_action_metadata_duration_seconds(2_419_201).is_err());
2034 }
2035
2036 #[test]
2037 fn bio_length() {
2038 assert!(bio("a").is_ok());
2039 assert!(bio("a".repeat(400)).is_ok());
2040
2041 assert!(bio("").is_err());
2042 assert!(bio("b".repeat(401)).is_err());
2043 }
2044
2045 #[test]
2046 fn bulk_guild_ban_delete_message_seconds_max() {
2047 assert!(bulk_guild_ban_delete_message_seconds(0).is_ok());
2048 assert!(bulk_guild_ban_delete_message_seconds(1).is_ok());
2049 assert!(bulk_guild_ban_delete_message_seconds(604_800).is_ok());
2050
2051 assert!(bulk_guild_ban_delete_message_seconds(604_801).is_err());
2052 }
2053
2054 #[test]
2055 fn bulk_guild_ban_users_limit() {
2056 fn user_id_iter() -> impl Iterator<Item = Id<UserMarker>> {
2057 std::iter::successors(Some(Id::<UserMarker>::new(1)), |previous| {
2058 Some(Id::new(previous.get() + 1))
2059 })
2060 }
2061
2062 let just_enough = user_id_iter().take(200).collect::<Vec<_>>();
2063 assert!(bulk_guild_ban_users(&just_enough).is_ok());
2064 let too_many = user_id_iter().take(201).collect::<Vec<_>>();
2065 assert!(bulk_guild_ban_users(&too_many).is_err());
2066 }
2067
2068 #[test]
2069 fn create_guild_ban_delete_message_seconds_max() {
2070 assert!(create_guild_ban_delete_message_seconds(0).is_ok());
2071 assert!(create_guild_ban_delete_message_seconds(1).is_ok());
2072 assert!(create_guild_ban_delete_message_seconds(604_800).is_ok());
2073
2074 assert!(create_guild_ban_delete_message_seconds(604_801).is_err());
2075 }
2076
2077 #[test]
2078 fn communication_disabled_until_max() {
2079 #[allow(clippy::cast_possible_wrap)]
2080 let now = SystemTime::now()
2081 .duration_since(UNIX_EPOCH)
2082 .unwrap()
2083 .as_secs() as i64;
2084
2085 let ok_timestamp =
2086 Timestamp::from_secs(now + COMMUNICATION_DISABLED_MAX_DURATION - 1000).unwrap();
2087 assert!(communication_disabled_until(ok_timestamp).is_ok());
2088
2089 let err_timestamp =
2090 Timestamp::from_secs(now + COMMUNICATION_DISABLED_MAX_DURATION + 1000).unwrap();
2091 assert!(communication_disabled_until(err_timestamp).is_err());
2092 }
2093
2094 #[test]
2095 fn get_channel_messages_limit_count() {
2096 assert!(get_channel_messages_limit(1).is_ok());
2097 assert!(get_channel_messages_limit(100).is_ok());
2098
2099 assert!(get_channel_messages_limit(0).is_err());
2100 assert!(get_channel_messages_limit(101).is_err());
2101 }
2102
2103 #[test]
2104 fn get_current_user_guilds_limit_count() {
2105 assert!(get_current_user_guilds_limit(1).is_ok());
2106 assert!(get_current_user_guilds_limit(200).is_ok());
2107
2108 assert!(get_current_user_guilds_limit(0).is_err());
2109 assert!(get_current_user_guilds_limit(201).is_err());
2110 }
2111
2112 #[test]
2113 fn get_guild_log_limit_count() {
2114 assert!(get_guild_audit_log_limit(1).is_ok());
2115 assert!(get_guild_audit_log_limit(100).is_ok());
2116
2117 assert!(get_guild_audit_log_limit(0).is_err());
2118 assert!(get_guild_audit_log_limit(101).is_err());
2119 }
2120
2121 #[test]
2122 fn get_guild_bans_limit_count() {
2123 assert!(get_guild_bans_limit(0).is_ok());
2124 assert!(get_guild_bans_limit(1000).is_ok());
2125
2126 assert!(get_guild_bans_limit(1001).is_err());
2127 }
2128
2129 #[test]
2130 fn get_guild_members_limit_count() {
2131 assert!(get_guild_members_limit(1).is_ok());
2132 assert!(get_guild_members_limit(1000).is_ok());
2133
2134 assert!(get_guild_members_limit(0).is_err());
2135 assert!(get_guild_members_limit(1001).is_err());
2136 }
2137
2138 #[test]
2139 fn get_reactions_limit_count() {
2140 assert!(get_reactions_limit(1).is_ok());
2141 assert!(get_reactions_limit(100).is_ok());
2142
2143 assert!(get_reactions_limit(0).is_err());
2144 assert!(get_reactions_limit(101).is_err());
2145 }
2146
2147 #[test]
2148 fn get_sku_subscriptions_limit_count() {
2149 assert!(get_sku_subscriptions_limit(1).is_ok());
2150 assert!(get_sku_subscriptions_limit(100).is_ok());
2151
2152 assert!(get_sku_subscriptions_limit(0).is_err());
2153 assert!(get_sku_subscriptions_limit(101).is_err());
2154 }
2155
2156 #[test]
2157 fn guild_name_length() {
2158 assert!(guild_name("aa").is_ok());
2159 assert!(guild_name("a".repeat(100)).is_ok());
2160
2161 assert!(guild_name("").is_err());
2162 assert!(guild_name("a").is_err());
2163 assert!(guild_name("a".repeat(101)).is_err());
2164 }
2165
2166 #[test]
2167 fn guild_prune_days_length() {
2168 assert!(guild_prune_days(1).is_ok());
2169 assert!(guild_prune_days(30).is_ok());
2170
2171 assert!(guild_prune_days(0).is_err());
2172 assert!(guild_prune_days(31).is_err());
2173 assert!(guild_prune_days(100).is_err());
2174 }
2175
2176 #[test]
2177 fn invite_max_age_length() {
2178 assert!(invite_max_age(0).is_ok());
2179 assert!(invite_max_age(86_400).is_ok());
2180 assert!(invite_max_age(604_800).is_ok());
2181
2182 assert!(invite_max_age(604_801).is_err());
2183 }
2184
2185 #[test]
2186 fn invite_max_uses_count() {
2187 assert!(invite_max_uses(0).is_ok());
2188 assert!(invite_max_uses(100).is_ok());
2189
2190 assert!(invite_max_uses(101).is_err());
2191 }
2192
2193 #[test]
2194 fn nickname_length() {
2195 assert!(nickname("a").is_ok());
2196 assert!(nickname("a".repeat(32)).is_ok());
2197
2198 assert!(nickname("").is_err());
2199 assert!(nickname("a".repeat(33)).is_err());
2200 }
2201
2202 #[test]
2203 fn pin_limit_test() {
2204 assert!(pin_limit(1).is_ok());
2205 assert!(pin_limit(50).is_ok());
2206
2207 assert!(pin_limit(0).is_err());
2208 assert!(pin_limit(51).is_err());
2209 }
2210
2211 #[test]
2212 fn scheduled_event_description_length() {
2213 assert!(scheduled_event_description("a").is_ok());
2214 assert!(scheduled_event_description("a".repeat(1000)).is_ok());
2215
2216 assert!(scheduled_event_description("").is_err());
2217 assert!(scheduled_event_description("a".repeat(1001)).is_err());
2218 }
2219
2220 #[test]
2221 fn scheduled_event_get_users_length() {
2222 assert!(scheduled_event_get_users(0).is_err());
2223 assert!(scheduled_event_get_users(101).is_err());
2224 assert!(scheduled_event_get_users(100).is_ok());
2225 assert!(scheduled_event_get_users(1).is_ok());
2226 }
2227
2228 #[test]
2229 fn scheduled_event_name_length() {
2230 assert!(scheduled_event_name("a").is_ok());
2231 assert!(scheduled_event_name("a".repeat(100)).is_ok());
2232
2233 assert!(scheduled_event_name("").is_err());
2234 assert!(scheduled_event_name("a".repeat(101)).is_err());
2235 }
2236
2237 #[test]
2238 fn search_guild_members_limit_count() {
2239 assert!(search_guild_members_limit(1).is_ok());
2240 assert!(search_guild_members_limit(1000).is_ok());
2241
2242 assert!(search_guild_members_limit(0).is_err());
2243 assert!(search_guild_members_limit(1001).is_err());
2244 }
2245
2246 #[test]
2247 fn stage_topic_length() {
2248 assert!(stage_topic("a").is_ok());
2249 assert!(stage_topic("a".repeat(120)).is_ok());
2250
2251 assert!(stage_topic("").is_err());
2252 assert!(stage_topic("a".repeat(121)).is_err());
2253 }
2254
2255 #[test]
2256 fn template_description_length() {
2257 assert!(template_description("").is_ok());
2258 assert!(template_description("a").is_ok());
2259 assert!(template_description("a".repeat(120)).is_ok());
2260
2261 assert!(template_description("a".repeat(121)).is_err());
2262 }
2263
2264 #[test]
2265 fn template_name_length() {
2266 assert!(template_name("a").is_ok());
2267 assert!(template_name("a".repeat(100)).is_ok());
2268
2269 assert!(template_name("").is_err());
2270 assert!(template_name("a".repeat(101)).is_err());
2271 }
2272
2273 #[test]
2274 fn username_length() {
2275 assert!(username("aa").is_ok());
2276 assert!(username("a".repeat(32)).is_ok());
2277
2278 assert!(username("a").is_err());
2279 assert!(username("a".repeat(33)).is_err());
2280
2281 assert!(username("no @ in username").is_err());
2282 assert!(username("no # in username").is_err());
2283 assert!(username("no : in username").is_err());
2284 assert!(username(r"no ``` in username").is_err());
2285 assert!(username("no discord in username").is_err());
2286 assert!(username("everyone").is_err());
2287 assert!(username("here").is_err());
2288 }
2289
2290 #[test]
2291 fn webhook_username_length() {
2292 assert!(webhook_username("aa").is_ok());
2293 assert!(webhook_username("a".repeat(80)).is_ok());
2294
2295 assert!(webhook_username("").is_err());
2296 assert!(webhook_username("a".repeat(81)).is_err());
2297
2298 assert!(webhook_username("clyde").is_err());
2299 }
2300}