1use std::{
6 error::Error,
7 fmt::{Display, Formatter, Result as FmtResult},
8 time::{SystemTime, UNIX_EPOCH},
9};
10use twilight_model::id::Id;
11use twilight_model::id::marker::{ChannelMarker, RoleMarker};
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 CREATE_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX: u32 = 604_800;
64
65pub const COMMUNICATION_DISABLED_MAX_DURATION: i64 = 28 * 24 * 60 * 60;
67
68pub const GET_CHANNEL_MESSAGES_LIMIT_MAX: u16 = 100;
70
71pub const GET_CHANNEL_MESSAGES_LIMIT_MIN: u16 = 1;
73
74pub const GET_CURRENT_USER_GUILDS_LIMIT_MAX: u16 = 200;
76
77pub const GET_CURRENT_USER_GUILDS_LIMIT_MIN: u16 = 1;
79
80pub const GET_ENTITLEMENTS_LIMIT_MAX: u8 = 100;
82
83pub const GET_ENTITLEMENTS_LIMIT_MIN: u8 = 1;
85
86pub const GET_GUILD_AUDIT_LOG_LIMIT_MAX: u16 = 100;
88
89pub const GET_GUILD_AUDIT_LOG_LIMIT_MIN: u16 = 1;
91
92pub const GET_GUILD_BANS_LIMIT_MAX: u16 = 1000;
94
95pub const GET_GUILD_MEMBERS_LIMIT_MAX: u16 = 1000;
97
98pub const GET_GUILD_MEMBERS_LIMIT_MIN: u16 = 1;
100
101pub const GET_REACTIONS_LIMIT_MIN: u16 = 1;
103
104pub const GET_REACTIONS_LIMIT_MAX: u16 = 100;
106
107pub const GUILD_NAME_LENGTH_MAX: usize = 100;
109
110pub const GUILD_NAME_LENGTH_MIN: usize = 2;
112
113pub const GUILD_PRUNE_DAYS_MAX: u16 = 30;
115
116pub const GUILD_PRUNE_DAYS_MIN: u16 = 1;
118
119pub const INVITE_AGE_MAX: u32 = 604_800;
121
122pub const INVITE_USES_MAX: u16 = 100;
124
125pub const NICKNAME_LIMIT_MAX: usize = 32;
127
128pub const NICKNAME_LIMIT_MIN: usize = 1;
130
131pub const PIN_LIMIT_MAX: u16 = 50;
133
134pub const PIN_LIMIT_MIN: u16 = 1;
136
137pub const SCHEDULED_EVENT_DESCRIPTION_MAX: usize = 1000;
139
140pub const SCHEDULED_EVENT_DESCRIPTION_MIN: usize = 1;
142
143pub const SCHEDULED_EVENT_GET_USERS_MAX: u16 = 100;
145
146pub const SCHEDULED_EVENT_GET_USERS_MIN: u16 = 1;
148
149pub const SCHEDULED_EVENT_NAME_MAX: usize = 100;
151
152pub const SCHEDULED_EVENT_NAME_MIN: usize = 1;
154
155pub const SEARCH_GUILD_MEMBERS_LIMIT_MAX: u16 = 1000;
157
158pub const SEARCH_GUILD_MEMBERS_LIMIT_MIN: u16 = 1;
160
161pub const STAGE_TOPIC_LENGTH_MAX: usize = 120;
163
164pub const STAGE_TOPIC_LENGTH_MIN: usize = 1;
166
167pub const TEMPLATE_DESCRIPTION_LENGTH_MAX: usize = 120;
169
170pub const TEMPLATE_NAME_LENGTH_MAX: usize = 100;
172
173pub const TEMPLATE_NAME_LENGTH_MIN: usize = 1;
175
176pub const USERNAME_LIMIT_MAX: usize = 32;
178
179pub const USERNAME_LIMIT_MIN: usize = 2;
181
182pub const WEBHOOK_USERNAME_LIMIT_MAX: usize = 80;
184
185pub const WEBHOOK_USERNAME_LIMIT_MIN: usize = 2;
187
188const USERNAME_INVALID_SUBSTRINGS: [&str; 5] = ["@", "#", ":", "```", "discord"];
190
191const USERNAME_INVALID_STRINGS: [&str; 2] = ["everyone", "here"];
193
194const WEBHOOK_INVALID_STRINGS: [&str; 1] = ["clyde"];
196
197#[derive(Debug)]
199pub struct ValidationError {
200 kind: ValidationErrorType,
202}
203
204impl ValidationError {
205 #[must_use = "retrieving the type has no effect if left unused"]
207 pub const fn kind(&self) -> &ValidationErrorType {
208 &self.kind
209 }
210
211 #[allow(clippy::unused_self)]
213 #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
214 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
215 None
216 }
217
218 #[must_use = "consuming the error into its parts has no effect if left unused"]
220 pub fn into_parts(self) -> (ValidationErrorType, Option<Box<dyn Error + Send + Sync>>) {
221 (self.kind, None)
222 }
223}
224
225impl Display for ValidationError {
226 #[allow(clippy::too_many_lines)]
227 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
228 match &self.kind {
229 ValidationErrorType::AuditReason { len } => {
230 f.write_str("provided audit reason length is ")?;
231 Display::fmt(len, f)?;
232 f.write_str(", but it must be at most ")?;
233
234 Display::fmt(&AUDIT_REASON_MAX, f)
235 }
236 ValidationErrorType::AutoModerationBlockActionCustomMessageLimit { len } => {
237 f.write_str("provided auto moderation block action custom message length is ")?;
238 Display::fmt(len, f)?;
239 f.write_str(", but it must be at most ")?;
240
241 Display::fmt(&AUTO_MODERATION_ACTION_BLOCK_CUSTOM_MESSAGE_LENGTH_MAX, f)
242 }
243 ValidationErrorType::AutoModerationMetadataMentionTotalLimit { limit } => {
244 f.write_str("provided auto moderation metadata mention_total_limit is ")?;
245 Display::fmt(limit, f)?;
246 f.write_str(", but it must be at most ")?;
247
248 Display::fmt(&AUTO_MODERATION_METADATA_MENTION_TOTAL_LIMIT, f)
249 }
250 ValidationErrorType::AutoModerationMetadataAllowList { len } => {
251 f.write_str("provided auto moderation metadata allow_list length is ")?;
252 Display::fmt(len, f)?;
253 f.write_str(", but it must be at most ")?;
254
255 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_MAX, f)
256 }
257 ValidationErrorType::AutoModerationMetadataAllowListItem { len, substring } => {
258 f.write_str("provided auto moderation metadata allow_list item ")?;
259 Display::fmt(substring, f)?;
260 f.write_str(" length is ")?;
261 Display::fmt(len, f)?;
262 f.write_str(", but it must be at most ")?;
263
264 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_LENGTH_MAX, f)
265 }
266 ValidationErrorType::AutoModerationMetadataKeywordFilter { len } => {
267 f.write_str("provided auto moderation metadata keyword_filter length is ")?;
268 Display::fmt(len, f)?;
269 f.write_str(", but it must be at most ")?;
270
271 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_FILTER_MAX, f)
272 }
273 ValidationErrorType::AutoModerationMetadataKeywordFilterItem { len, substring } => {
274 f.write_str("provided auto moderation metadata keyword_filter item ")?;
275 Display::fmt(substring, f)?;
276 f.write_str(" length is ")?;
277 Display::fmt(len, f)?;
278 f.write_str(", but it must be at most ")?;
279
280 Display::fmt(&AUTO_MODERATION_METADATA_KEYWORD_FILTER_LENGTH_MAX, f)
281 }
282 ValidationErrorType::AutoModerationMetadataPresetAllowList { len } => {
283 f.write_str("provided auto moderation metadata allow_list length is ")?;
284 Display::fmt(len, f)?;
285 f.write_str(", but it must be at most ")?;
286
287 Display::fmt(&AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_MAX, f)
288 }
289 ValidationErrorType::AutoModerationMetadataPresetAllowListItem { len, substring } => {
290 f.write_str("provided auto moderation metadata allow_list item ")?;
291 Display::fmt(substring, f)?;
292 f.write_str(" length is ")?;
293 Display::fmt(len, f)?;
294 f.write_str(", but it must be at most ")?;
295
296 Display::fmt(&AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_LENGTH_MAX, f)
297 }
298 ValidationErrorType::AutoModerationActionMetadataDurationSeconds { seconds } => {
299 f.write_str("provided auto moderation action timeout duration is ")?;
300 Display::fmt(seconds, f)?;
301 f.write_str(", but it must be at most ")?;
302
303 Display::fmt(&AUTO_MODERATION_ACTION_METADATA_DURATION_SECONDS_MAX, f)
304 }
305 ValidationErrorType::AutoModerationMetadataRegexPatterns { len } => {
306 f.write_str("provided auto moderation metadata regex_patterns length is ")?;
307 Display::fmt(len, f)?;
308 f.write_str(", but it must be at most ")?;
309
310 Display::fmt(&AUTO_MODERATION_METADATA_REGEX_PATTERNS_MAX, f)
311 }
312 ValidationErrorType::AutoModerationMetadataRegexPatternsItem { len, substring } => {
313 f.write_str("provided auto moderation metadata regex_patterns item ")?;
314 Display::fmt(substring, f)?;
315 f.write_str(" length is ")?;
316 Display::fmt(len, f)?;
317 f.write_str(", but it must be at most ")?;
318
319 Display::fmt(&AUTO_MODERATION_METADATA_REGEX_PATTERNS_LENGTH_MAX, f)
320 }
321 ValidationErrorType::AutoModerationExemptRoles { len } => {
322 f.write_str("provided auto moderation exempt_roles length is ")?;
323 Display::fmt(len, f)?;
324 f.write_str(", but it must be at most ")?;
325
326 Display::fmt(&AUTO_MODERATION_EXEMPT_ROLES_MAX, f)
327 }
328 ValidationErrorType::AutoModerationExemptChannels { len } => {
329 f.write_str("provided auto moderation exempt_channels length is ")?;
330 Display::fmt(len, f)?;
331 f.write_str(", but it must be at most ")?;
332
333 Display::fmt(&AUTO_MODERATION_EXEMPT_CHANNELS_MAX, f)
334 }
335 ValidationErrorType::Bio { len } => {
336 f.write_str("provided bio length is ")?;
337 Display::fmt(len, f)?;
338
339 f.write_str(", but it must be at least")?;
340 Display::fmt(&BIO_LIMIT_MIN, f)?;
341
342 f.write_str(" and at most ")?;
343 Display::fmt(&BIO_LIMIT_MAX, f)
344 }
345 ValidationErrorType::CreateGuildBanDeleteMessageSeconds {
346 seconds: delete_message_seconds,
347 } => {
348 f.write_str("provided create guild ban delete_message_seconds is ")?;
349 Display::fmt(delete_message_seconds, f)?;
350 f.write_str(", but it must be at most ")?;
351
352 Display::fmt(&CREATE_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX, f)
353 }
354 ValidationErrorType::CommunicationDisabledUntil { .. } => {
355 f.write_str("provided timestamp is too far in the future")
356 }
357 ValidationErrorType::GetChannelMessages { limit } => {
358 f.write_str("provided get guild members limit is ")?;
359 Display::fmt(limit, f)?;
360 f.write_str(", but it must be at least ")?;
361 Display::fmt(&GET_CHANNEL_MESSAGES_LIMIT_MIN, f)?;
362 f.write_str(" and at most ")?;
363
364 Display::fmt(&GET_CHANNEL_MESSAGES_LIMIT_MAX, f)
365 }
366 ValidationErrorType::GetCurrentUserGuilds { limit } => {
367 f.write_str("provided get current user guilds limit is ")?;
368 Display::fmt(limit, f)?;
369 f.write_str(", but it must be at least ")?;
370 Display::fmt(&GET_CURRENT_USER_GUILDS_LIMIT_MIN, f)?;
371 f.write_str(" and at most ")?;
372
373 Display::fmt(&GET_CURRENT_USER_GUILDS_LIMIT_MAX, f)
374 }
375 ValidationErrorType::GetEntitlements { limit } => {
376 f.write_str("provided get entitlements limit is ")?;
377 Display::fmt(limit, f)?;
378 f.write_str(", but it must be at least ")?;
379 Display::fmt(&GET_ENTITLEMENTS_LIMIT_MIN, f)?;
380 f.write_str(" and at most ")?;
381
382 Display::fmt(&GET_ENTITLEMENTS_LIMIT_MAX, f)
383 }
384 ValidationErrorType::GetGuildAuditLog { limit } => {
385 f.write_str("provided get guild audit log limit is ")?;
386 Display::fmt(limit, f)?;
387 f.write_str(", but it must be at least ")?;
388 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MIN, f)?;
389 f.write_str(" and at most ")?;
390
391 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MAX, f)
392 }
393 ValidationErrorType::GetGuildBans { limit } => {
394 f.write_str("provided get guild bans limit is ")?;
395 Display::fmt(limit, f)?;
396 f.write_str(", but it must be at most ")?;
397
398 Display::fmt(&GET_GUILD_BANS_LIMIT_MAX, f)
399 }
400 ValidationErrorType::GetGuildMembers { limit } => {
401 f.write_str("provided get guild members limit is ")?;
402 Display::fmt(limit, f)?;
403 f.write_str(", but it must be at least ")?;
404 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MIN, f)?;
405 f.write_str(" and at most ")?;
406
407 Display::fmt(&GET_GUILD_MEMBERS_LIMIT_MAX, f)
408 }
409 ValidationErrorType::GetReactions { limit } => {
410 f.write_str("provided get reactions limit is ")?;
411 Display::fmt(limit, f)?;
412 f.write_str(", but it must be at least ")?;
413 Display::fmt(&GET_REACTIONS_LIMIT_MIN, f)?;
414 f.write_str(" and at most ")?;
415
416 Display::fmt(&GET_REACTIONS_LIMIT_MAX, f)
417 }
418 ValidationErrorType::GuildName { len } => {
419 f.write_str("provided guild name length is ")?;
420 Display::fmt(len, f)?;
421 f.write_str(", but it must be at least ")?;
422 Display::fmt(&GUILD_NAME_LENGTH_MIN, f)?;
423 f.write_str(" and at most ")?;
424
425 Display::fmt(&GUILD_NAME_LENGTH_MAX, f)
426 }
427 ValidationErrorType::GuildPruneDays { days } => {
428 f.write_str("provided prune days is ")?;
429 Display::fmt(days, f)?;
430 f.write_str(", but it must be at least ")?;
431 Display::fmt(&GUILD_PRUNE_DAYS_MIN, f)?;
432 f.write_str(" and at most ")?;
433
434 Display::fmt(&GUILD_PRUNE_DAYS_MAX, f)
435 }
436 ValidationErrorType::InviteMaxAge { max_age } => {
437 f.write_str("provided invite max_age is ")?;
438 Display::fmt(max_age, f)?;
439 f.write_str(", but it must be at most ")?;
440
441 Display::fmt(&INVITE_AGE_MAX, f)
442 }
443 ValidationErrorType::InviteMaxUses { max_uses } => {
444 f.write_str("provided invite max_uses is ")?;
445 Display::fmt(max_uses, f)?;
446 f.write_str(", but it must be at most ")?;
447
448 Display::fmt(&INVITE_USES_MAX, f)
449 }
450 ValidationErrorType::Nickname { len } => {
451 f.write_str("provided nickname length is ")?;
452 Display::fmt(len, f)?;
453 f.write_str(", but it must be at least ")?;
454 Display::fmt(&NICKNAME_LIMIT_MIN, f)?;
455 f.write_str(" and at most ")?;
456
457 Display::fmt(&NICKNAME_LIMIT_MAX, f)
458 }
459 ValidationErrorType::Pin { limit } => {
460 f.write_str("provided pin limit is ")?;
461 Display::fmt(limit, f)?;
462 f.write_str(", but it must be at least ")?;
463 Display::fmt(&PIN_LIMIT_MIN, f)?;
464 f.write_str(" and at most ")?;
465 Display::fmt(&PIN_LIMIT_MAX, f)
466 }
467 ValidationErrorType::ScheduledEventDescription { len } => {
468 f.write_str("provided scheduled event description is length is ")?;
469 Display::fmt(len, f)?;
470 f.write_str(", but it must be at least ")?;
471 Display::fmt(&SCHEDULED_EVENT_DESCRIPTION_MIN, f)?;
472 f.write_str(" and at most ")?;
473
474 Display::fmt(&SCHEDULED_EVENT_DESCRIPTION_MAX, f)
475 }
476 ValidationErrorType::ScheduledEventGetUsers { limit } => {
477 f.write_str("provided scheduled event get users limit is ")?;
478 Display::fmt(limit, f)?;
479 f.write_str(", but it must be at least ")?;
480 Display::fmt(&SCHEDULED_EVENT_GET_USERS_MIN, f)?;
481 f.write_str(" and at most ")?;
482
483 Display::fmt(&SCHEDULED_EVENT_GET_USERS_MAX, f)
484 }
485 ValidationErrorType::ScheduledEventName { len } => {
486 f.write_str("provided scheduled event name is length is ")?;
487 Display::fmt(len, f)?;
488 f.write_str(", but it must be at least ")?;
489 Display::fmt(&SCHEDULED_EVENT_NAME_MIN, f)?;
490 f.write_str(" and at most ")?;
491
492 Display::fmt(&SCHEDULED_EVENT_NAME_MAX, f)
493 }
494 ValidationErrorType::SearchGuildMembers { limit } => {
495 f.write_str("provided search guild members limit is ")?;
496 Display::fmt(limit, f)?;
497 f.write_str(", but it must be at least ")?;
498 Display::fmt(&SEARCH_GUILD_MEMBERS_LIMIT_MIN, f)?;
499 f.write_str(" and at most ")?;
500
501 Display::fmt(&SEARCH_GUILD_MEMBERS_LIMIT_MAX, f)
502 }
503 ValidationErrorType::StageTopic { len } => {
504 f.write_str("provided stage instance topic length is ")?;
505 Display::fmt(len, f)?;
506 f.write_str(", but it must be at least ")?;
507 Display::fmt(&STAGE_TOPIC_LENGTH_MIN, f)?;
508 f.write_str(" and at most ")?;
509
510 Display::fmt(&STAGE_TOPIC_LENGTH_MAX, f)
511 }
512 ValidationErrorType::TemplateDescription { len } => {
513 f.write_str("provided guild template description topic length is ")?;
514 Display::fmt(len, f)?;
515 f.write_str(", but it must be at most ")?;
516
517 Display::fmt(&TEMPLATE_DESCRIPTION_LENGTH_MAX, f)
518 }
519 ValidationErrorType::TemplateName { len } => {
520 f.write_str("provided guild template name length is ")?;
521 Display::fmt(len, f)?;
522 f.write_str(", but it must be at least ")?;
523 Display::fmt(&TEMPLATE_NAME_LENGTH_MIN, f)?;
524 f.write_str(" and at most ")?;
525
526 Display::fmt(&TEMPLATE_NAME_LENGTH_MAX, f)
527 }
528 ValidationErrorType::Username { len, substring }
529 | ValidationErrorType::WebhookUsername { len, substring } => {
530 f.write_str("provided username")?;
531
532 if let Some(len) = len {
533 f.write_str(" length is ")?;
534 Display::fmt(len, f)?;
535 f.write_str(", but it must be at least ")?;
536 Display::fmt(&USERNAME_LIMIT_MIN, f)?;
537 f.write_str(" and at most ")?;
538 Display::fmt(&USERNAME_LIMIT_MAX, f)?;
539 }
540
541 if let Some(substring) = substring {
542 if len.is_some() {
543 f.write_str(", and")?;
544 }
545
546 f.write_str(" cannot contain ")?;
547 Display::fmt(substring, f)?;
548 }
549
550 Ok(())
551 }
552 }
553 }
554}
555
556impl Error for ValidationError {}
557
558#[derive(Debug)]
560pub enum ValidationErrorType {
561 AuditReason {
563 len: usize,
565 },
566 AutoModerationBlockActionCustomMessageLimit {
568 len: usize,
570 },
571 AutoModerationMetadataMentionTotalLimit {
573 limit: u8,
575 },
576 AutoModerationMetadataKeywordFilter {
578 len: usize,
580 },
581 AutoModerationMetadataKeywordFilterItem {
583 len: usize,
585 substring: String,
587 },
588 AutoModerationMetadataAllowList {
590 len: usize,
592 },
593 AutoModerationMetadataAllowListItem {
595 len: usize,
597 substring: String,
599 },
600 AutoModerationMetadataPresetAllowList {
602 len: usize,
604 },
605 AutoModerationMetadataPresetAllowListItem {
607 len: usize,
609 substring: String,
611 },
612 AutoModerationActionMetadataDurationSeconds {
614 seconds: u32,
616 },
617 AutoModerationMetadataRegexPatterns {
619 len: usize,
621 },
622 AutoModerationMetadataRegexPatternsItem {
624 len: usize,
626 substring: String,
628 },
629 AutoModerationExemptRoles {
631 len: usize,
633 },
634 AutoModerationExemptChannels {
636 len: usize,
638 },
639 Bio {
641 len: usize,
643 },
644 CreateGuildBanDeleteMessageSeconds {
646 seconds: u32,
648 },
649 CommunicationDisabledUntil {
651 timestamp: Timestamp,
653 },
654 GetChannelMessages {
656 limit: u16,
658 },
659 GetCurrentUserGuilds {
661 limit: u16,
663 },
664 GetEntitlements {
666 limit: u8,
668 },
669 GetGuildAuditLog {
671 limit: u16,
673 },
674 GetGuildBans {
676 limit: u16,
678 },
679 GetGuildMembers {
681 limit: u16,
683 },
684 GetReactions {
686 limit: u16,
688 },
689 GuildName {
691 len: usize,
693 },
694 GuildPruneDays {
696 days: u16,
698 },
699 InviteMaxAge {
701 max_age: u32,
703 },
704 InviteMaxUses {
706 max_uses: u16,
708 },
709 Nickname {
711 len: usize,
713 },
714 Pin {
716 limit: u16,
718 },
719 ScheduledEventDescription {
721 len: usize,
723 },
724 ScheduledEventGetUsers {
726 limit: u16,
728 },
729 ScheduledEventName {
731 len: usize,
733 },
734 SearchGuildMembers {
736 limit: u16,
738 },
739 StageTopic {
741 len: usize,
743 },
744 TemplateDescription {
746 len: usize,
748 },
749 TemplateName {
751 len: usize,
753 },
754 Username {
756 len: Option<usize>,
758 substring: Option<&'static str>,
760 },
761 WebhookUsername {
763 len: Option<usize>,
765 substring: Option<&'static str>,
767 },
768}
769
770pub fn audit_reason(audit_reason: impl AsRef<str>) -> Result<(), ValidationError> {
782 let len = audit_reason.as_ref().chars().count();
783
784 if len <= AUDIT_REASON_MAX {
785 Ok(())
786 } else {
787 Err(ValidationError {
788 kind: ValidationErrorType::AuditReason { len },
789 })
790 }
791}
792
793pub fn auto_moderation_block_action_custom_message_limit(
806 custom_message: impl AsRef<str>,
807) -> Result<(), ValidationError> {
808 let len = custom_message.as_ref().chars().count();
809
810 if len <= AUTO_MODERATION_ACTION_BLOCK_CUSTOM_MESSAGE_LENGTH_MAX {
811 Ok(())
812 } else {
813 Err(ValidationError {
814 kind: ValidationErrorType::AutoModerationBlockActionCustomMessageLimit { len },
815 })
816 }
817}
818
819pub const fn auto_moderation_metadata_mention_total_limit(
832 limit: u8,
833) -> Result<(), ValidationError> {
834 if limit <= AUTO_MODERATION_METADATA_MENTION_TOTAL_LIMIT {
835 Ok(())
836 } else {
837 Err(ValidationError {
838 kind: ValidationErrorType::AutoModerationMetadataMentionTotalLimit { limit },
839 })
840 }
841}
842
843pub fn auto_moderation_metadata_keyword_filter(
860 keywords: &[impl AsRef<str>],
861) -> Result<(), ValidationError> {
862 let len = keywords.len();
863
864 if len <= AUTO_MODERATION_METADATA_KEYWORD_FILTER_MAX {
865 for keyword in keywords {
866 auto_moderation_metadata_keyword_filter_item(keyword)?;
867 }
868
869 Ok(())
870 } else {
871 Err(ValidationError {
872 kind: ValidationErrorType::AutoModerationMetadataKeywordFilter { len },
873 })
874 }
875}
876
877pub fn auto_moderation_metadata_keyword_filter_item(
890 keyword: impl AsRef<str>,
891) -> Result<(), ValidationError> {
892 let len = keyword.as_ref().chars().count();
893
894 if len <= AUTO_MODERATION_METADATA_KEYWORD_FILTER_LENGTH_MAX {
895 Ok(())
896 } else {
897 Err(ValidationError {
898 kind: ValidationErrorType::AutoModerationMetadataKeywordFilterItem {
899 len,
900 substring: keyword.as_ref().to_string(),
901 },
902 })
903 }
904}
905
906pub fn auto_moderation_metadata_keyword_allow_list(
923 keywords: &[impl AsRef<str>],
924) -> Result<(), ValidationError> {
925 let len = keywords.len();
926
927 if len <= AUTO_MODERATION_METADATA_KEYWORD_ALLOW_LIST_MAX {
928 for keyword in keywords {
929 auto_moderation_metadata_keyword_allow_list_item(keyword)?;
930 }
931
932 Ok(())
933 } else {
934 Err(ValidationError {
935 kind: ValidationErrorType::AutoModerationMetadataAllowList { len },
936 })
937 }
938}
939
940pub fn auto_moderation_metadata_keyword_allow_list_item(
953 keyword: impl AsRef<str>,
954) -> Result<(), ValidationError> {
955 let len = keyword.as_ref().chars().count();
956
957 if len <= AUTO_MODERATION_METADATA_KEYWORD_FILTER_LENGTH_MAX {
958 Ok(())
959 } else {
960 Err(ValidationError {
961 kind: ValidationErrorType::AutoModerationMetadataAllowListItem {
962 len,
963 substring: keyword.as_ref().to_string(),
964 },
965 })
966 }
967}
968
969pub fn auto_moderation_metadata_preset_allow_list(
986 keywords: &[impl AsRef<str>],
987) -> Result<(), ValidationError> {
988 let len = keywords.len();
989
990 if len <= AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_MAX {
991 for keyword in keywords {
992 auto_moderation_metadata_preset_allow_list_item(keyword)?;
993 }
994
995 Ok(())
996 } else {
997 Err(ValidationError {
998 kind: ValidationErrorType::AutoModerationMetadataPresetAllowList { len },
999 })
1000 }
1001}
1002
1003pub fn auto_moderation_metadata_preset_allow_list_item(
1016 keyword: impl AsRef<str>,
1017) -> Result<(), ValidationError> {
1018 let len = keyword.as_ref().chars().count();
1019
1020 if len <= AUTO_MODERATION_METADATA_PRESET_ALLOW_LIST_LENGTH_MAX {
1021 Ok(())
1022 } else {
1023 Err(ValidationError {
1024 kind: ValidationErrorType::AutoModerationMetadataPresetAllowListItem {
1025 len,
1026 substring: keyword.as_ref().to_string(),
1027 },
1028 })
1029 }
1030}
1031
1032pub fn auto_moderation_metadata_regex_patterns(
1049 patterns: &[impl AsRef<str>],
1050) -> Result<(), ValidationError> {
1051 let len = patterns.len();
1052
1053 if len <= AUTO_MODERATION_METADATA_REGEX_PATTERNS_MAX {
1054 for pattern in patterns {
1055 auto_moderation_metadata_regex_patterns_item(pattern)?;
1056 }
1057
1058 Ok(())
1059 } else {
1060 Err(ValidationError {
1061 kind: ValidationErrorType::AutoModerationMetadataRegexPatterns { len },
1062 })
1063 }
1064}
1065
1066pub fn auto_moderation_metadata_regex_patterns_item(
1079 pattern: impl AsRef<str>,
1080) -> Result<(), ValidationError> {
1081 let len = pattern.as_ref().chars().count();
1082
1083 if len <= AUTO_MODERATION_METADATA_REGEX_PATTERNS_LENGTH_MAX {
1084 Ok(())
1085 } else {
1086 Err(ValidationError {
1087 kind: ValidationErrorType::AutoModerationMetadataRegexPatternsItem {
1088 len,
1089 substring: pattern.as_ref().to_string(),
1090 },
1091 })
1092 }
1093}
1094
1095pub const fn auto_moderation_action_metadata_duration_seconds(
1109 seconds: u32,
1110) -> Result<(), ValidationError> {
1111 if seconds <= AUTO_MODERATION_ACTION_METADATA_DURATION_SECONDS_MAX {
1112 Ok(())
1113 } else {
1114 Err(ValidationError {
1115 kind: ValidationErrorType::AutoModerationActionMetadataDurationSeconds { seconds },
1116 })
1117 }
1118}
1119
1120pub const fn auto_moderation_exempt_roles(roles: &[Id<RoleMarker>]) -> Result<(), ValidationError> {
1133 let len = roles.len();
1134
1135 if len <= AUTO_MODERATION_EXEMPT_ROLES_MAX {
1136 Ok(())
1137 } else {
1138 Err(ValidationError {
1139 kind: ValidationErrorType::AutoModerationExemptRoles { len },
1140 })
1141 }
1142}
1143
1144pub const fn auto_moderation_exempt_channels(
1157 channels: &[Id<ChannelMarker>],
1158) -> Result<(), ValidationError> {
1159 let len = channels.len();
1160
1161 if len <= AUTO_MODERATION_EXEMPT_CHANNELS_MAX {
1162 Ok(())
1163 } else {
1164 Err(ValidationError {
1165 kind: ValidationErrorType::AutoModerationExemptChannels { len },
1166 })
1167 }
1168}
1169
1170pub fn bio(bio: impl AsRef<str>) -> Result<(), ValidationError> {
1183 let len = bio.as_ref().chars().count();
1184
1185 if (BIO_LIMIT_MIN..=BIO_LIMIT_MAX).contains(&len) {
1186 Ok(())
1187 } else {
1188 Err(ValidationError {
1189 kind: ValidationErrorType::Bio { len },
1190 })
1191 }
1192}
1193
1194pub const fn create_guild_ban_delete_message_seconds(seconds: u32) -> Result<(), ValidationError> {
1208 if seconds <= CREATE_GUILD_BAN_DELETE_MESSAGE_SECONDS_MAX {
1209 Ok(())
1210 } else {
1211 Err(ValidationError {
1212 kind: ValidationErrorType::CreateGuildBanDeleteMessageSeconds { seconds },
1213 })
1214 }
1215}
1216
1217#[allow(clippy::cast_possible_wrap)] pub fn communication_disabled_until(timestamp: Timestamp) -> Result<(), ValidationError> {
1224 let now = SystemTime::now()
1225 .duration_since(UNIX_EPOCH)
1226 .map_err(|_| ValidationError {
1227 kind: ValidationErrorType::CommunicationDisabledUntil { timestamp },
1228 })?;
1229
1230 let end = timestamp.as_secs();
1231
1232 if end - now.as_secs() as i64 <= COMMUNICATION_DISABLED_MAX_DURATION {
1233 Ok(())
1234 } else {
1235 Err(ValidationError {
1236 kind: ValidationErrorType::CommunicationDisabledUntil { timestamp },
1237 })
1238 }
1239}
1240
1241pub const fn get_channel_messages_limit(limit: u16) -> Result<(), ValidationError> {
1254 if limit >= GET_CHANNEL_MESSAGES_LIMIT_MIN && limit <= GET_CHANNEL_MESSAGES_LIMIT_MAX {
1255 Ok(())
1256 } else {
1257 Err(ValidationError {
1258 kind: ValidationErrorType::GetChannelMessages { limit },
1259 })
1260 }
1261}
1262
1263pub const fn get_current_user_guilds_limit(limit: u16) -> Result<(), ValidationError> {
1276 if limit >= GET_CURRENT_USER_GUILDS_LIMIT_MIN && limit <= GET_CURRENT_USER_GUILDS_LIMIT_MAX {
1277 Ok(())
1278 } else {
1279 Err(ValidationError {
1280 kind: ValidationErrorType::GetCurrentUserGuilds { limit },
1281 })
1282 }
1283}
1284
1285pub const fn get_entitlements_limit(limit: u8) -> Result<(), ValidationError> {
1298 if limit >= GET_ENTITLEMENTS_LIMIT_MIN && limit <= GET_ENTITLEMENTS_LIMIT_MAX {
1299 Ok(())
1300 } else {
1301 Err(ValidationError {
1302 kind: ValidationErrorType::GetEntitlements { limit },
1303 })
1304 }
1305}
1306
1307pub const fn get_guild_audit_log_limit(limit: u16) -> Result<(), ValidationError> {
1320 if limit >= GET_GUILD_AUDIT_LOG_LIMIT_MIN && limit <= GET_GUILD_AUDIT_LOG_LIMIT_MAX {
1321 Ok(())
1322 } else {
1323 Err(ValidationError {
1324 kind: ValidationErrorType::GetGuildAuditLog { limit },
1325 })
1326 }
1327}
1328
1329pub const fn get_guild_bans_limit(limit: u16) -> Result<(), ValidationError> {
1341 if limit <= GET_GUILD_BANS_LIMIT_MAX {
1342 Ok(())
1343 } else {
1344 Err(ValidationError {
1345 kind: ValidationErrorType::GetGuildBans { limit },
1346 })
1347 }
1348}
1349
1350pub const fn get_guild_members_limit(limit: u16) -> Result<(), ValidationError> {
1363 if limit >= GET_GUILD_MEMBERS_LIMIT_MIN && limit <= GET_GUILD_MEMBERS_LIMIT_MAX {
1364 Ok(())
1365 } else {
1366 Err(ValidationError {
1367 kind: ValidationErrorType::GetGuildMembers { limit },
1368 })
1369 }
1370}
1371
1372pub const fn get_reactions_limit(limit: u16) -> Result<(), ValidationError> {
1384 if limit >= GET_REACTIONS_LIMIT_MIN && limit <= GET_REACTIONS_LIMIT_MAX {
1385 Ok(())
1386 } else {
1387 Err(ValidationError {
1388 kind: ValidationErrorType::GetReactions { limit },
1389 })
1390 }
1391}
1392
1393pub fn guild_name(name: impl AsRef<str>) -> Result<(), ValidationError> {
1405 let len = name.as_ref().chars().count();
1406
1407 if (GUILD_NAME_LENGTH_MIN..=GUILD_NAME_LENGTH_MAX).contains(&len) {
1408 Ok(())
1409 } else {
1410 Err(ValidationError {
1411 kind: ValidationErrorType::GuildName { len },
1412 })
1413 }
1414}
1415
1416pub const fn guild_prune_days(days: u16) -> Result<(), ValidationError> {
1428 if days >= GUILD_PRUNE_DAYS_MIN && days <= GUILD_PRUNE_DAYS_MAX {
1429 Ok(())
1430 } else {
1431 Err(ValidationError {
1432 kind: ValidationErrorType::GuildPruneDays { days },
1433 })
1434 }
1435}
1436
1437pub const fn invite_max_age(max_age: u32) -> Result<(), ValidationError> {
1449 if max_age <= INVITE_AGE_MAX {
1450 Ok(())
1451 } else {
1452 Err(ValidationError {
1453 kind: ValidationErrorType::InviteMaxAge { max_age },
1454 })
1455 }
1456}
1457
1458pub const fn invite_max_uses(max_uses: u16) -> Result<(), ValidationError> {
1470 if max_uses <= INVITE_USES_MAX {
1471 Ok(())
1472 } else {
1473 Err(ValidationError {
1474 kind: ValidationErrorType::InviteMaxUses { max_uses },
1475 })
1476 }
1477}
1478
1479pub fn nickname(nickname: impl AsRef<str>) -> Result<(), ValidationError> {
1491 let len = nickname.as_ref().chars().count();
1492
1493 if (NICKNAME_LIMIT_MIN..=NICKNAME_LIMIT_MAX).contains(&len) {
1494 Ok(())
1495 } else {
1496 Err(ValidationError {
1497 kind: ValidationErrorType::Nickname { len },
1498 })
1499 }
1500}
1501
1502pub fn pin_limit(limit: u16) -> Result<(), ValidationError> {
1514 if (PIN_LIMIT_MIN..=PIN_LIMIT_MAX).contains(&limit) {
1515 Ok(())
1516 } else {
1517 Err(ValidationError {
1518 kind: ValidationErrorType::Pin { limit },
1519 })
1520 }
1521}
1522
1523pub fn scheduled_event_description(description: impl AsRef<str>) -> Result<(), ValidationError> {
1537 let len = description.as_ref().chars().count();
1538
1539 if (SCHEDULED_EVENT_DESCRIPTION_MIN..=SCHEDULED_EVENT_DESCRIPTION_MAX).contains(&len) {
1540 Ok(())
1541 } else {
1542 Err(ValidationError {
1543 kind: ValidationErrorType::ScheduledEventDescription { len },
1544 })
1545 }
1546}
1547
1548pub const fn scheduled_event_get_users(limit: u16) -> Result<(), ValidationError> {
1561 if limit >= SCHEDULED_EVENT_GET_USERS_MIN && limit <= SCHEDULED_EVENT_GET_USERS_MAX {
1562 Ok(())
1563 } else {
1564 Err(ValidationError {
1565 kind: ValidationErrorType::ScheduledEventGetUsers { limit },
1566 })
1567 }
1568}
1569
1570pub fn scheduled_event_name(name: impl AsRef<str>) -> Result<(), ValidationError> {
1582 let len = name.as_ref().chars().count();
1583
1584 if (SCHEDULED_EVENT_NAME_MIN..=SCHEDULED_EVENT_NAME_MAX).contains(&len) {
1585 Ok(())
1586 } else {
1587 Err(ValidationError {
1588 kind: ValidationErrorType::ScheduledEventName { len },
1589 })
1590 }
1591}
1592
1593pub const fn search_guild_members_limit(limit: u16) -> Result<(), ValidationError> {
1606 if limit >= SEARCH_GUILD_MEMBERS_LIMIT_MIN && limit <= SEARCH_GUILD_MEMBERS_LIMIT_MAX {
1607 Ok(())
1608 } else {
1609 Err(ValidationError {
1610 kind: ValidationErrorType::SearchGuildMembers { limit },
1611 })
1612 }
1613}
1614
1615pub fn stage_topic(topic: impl AsRef<str>) -> Result<(), ValidationError> {
1627 let len = topic.as_ref().chars().count();
1628
1629 if (STAGE_TOPIC_LENGTH_MIN..=STAGE_TOPIC_LENGTH_MAX).contains(&len) {
1630 Ok(())
1631 } else {
1632 Err(ValidationError {
1633 kind: ValidationErrorType::StageTopic { len },
1634 })
1635 }
1636}
1637
1638pub fn template_description(description: impl AsRef<str>) -> Result<(), ValidationError> {
1650 let len = description.as_ref().chars().count();
1651
1652 if len <= TEMPLATE_DESCRIPTION_LENGTH_MAX {
1653 Ok(())
1654 } else {
1655 Err(ValidationError {
1656 kind: ValidationErrorType::TemplateDescription { len },
1657 })
1658 }
1659}
1660
1661pub fn template_name(name: impl AsRef<str>) -> Result<(), ValidationError> {
1673 let len = name.as_ref().chars().count();
1674
1675 if (TEMPLATE_NAME_LENGTH_MIN..=TEMPLATE_NAME_LENGTH_MAX).contains(&len) {
1676 Ok(())
1677 } else {
1678 Err(ValidationError {
1679 kind: ValidationErrorType::TemplateName { len },
1680 })
1681 }
1682}
1683
1684pub fn username(value: impl AsRef<str>) -> Result<(), ValidationError> {
1697 let value = value.as_ref();
1698 let len = value.chars().count();
1699
1700 let range = USERNAME_LIMIT_MIN..=USERNAME_LIMIT_MAX;
1701 let invalid_len = (!range.contains(&len)).then_some(len);
1702
1703 let invalid_substring = USERNAME_INVALID_SUBSTRINGS
1704 .into_iter()
1705 .find(|invalid_substring| value.contains(invalid_substring))
1706 .or_else(|| {
1707 USERNAME_INVALID_STRINGS
1708 .into_iter()
1709 .find(|invalid_string| value == *invalid_string)
1710 });
1711
1712 if invalid_len.is_none() && invalid_substring.is_none() {
1713 Ok(())
1714 } else {
1715 Err(ValidationError {
1716 kind: ValidationErrorType::Username {
1717 len: invalid_len,
1718 substring: invalid_substring,
1719 },
1720 })
1721 }
1722}
1723
1724pub fn webhook_username(value: impl AsRef<str>) -> Result<(), ValidationError> {
1737 let value = value.as_ref();
1738 let len = value.chars().count();
1739
1740 let range = WEBHOOK_USERNAME_LIMIT_MIN..=WEBHOOK_USERNAME_LIMIT_MAX;
1741 let invalid_len = (!range.contains(&len)).then_some(len);
1742
1743 let invalid_substring = WEBHOOK_INVALID_STRINGS
1744 .into_iter()
1745 .find(|invalid_string| value == *invalid_string);
1746
1747 if invalid_len.is_none() && invalid_substring.is_none() {
1748 Ok(())
1749 } else {
1750 Err(ValidationError {
1751 kind: ValidationErrorType::WebhookUsername {
1752 len: invalid_len,
1753 substring: invalid_substring,
1754 },
1755 })
1756 }
1757}
1758
1759#[cfg(test)]
1760mod tests {
1761 use super::*;
1762
1763 #[test]
1764 fn username_variants() {
1765 let expected = format!(
1766 "provided username length is 200, but it must be at least {USERNAME_LIMIT_MIN} and at \
1767 most {USERNAME_LIMIT_MAX}, and cannot contain :"
1768 );
1769 let actual = ValidationError {
1770 kind: ValidationErrorType::Username {
1771 len: Some(200),
1772 substring: Some(":"),
1773 },
1774 };
1775 assert_eq!(expected, actual.to_string());
1776
1777 let expected = format!(
1778 "provided username length is 200, but it must be at least {USERNAME_LIMIT_MIN} and at \
1779 most {USERNAME_LIMIT_MAX}",
1780 );
1781 let actual = ValidationError {
1782 kind: ValidationErrorType::Username {
1783 len: Some(200),
1784 substring: None,
1785 },
1786 };
1787 assert_eq!(expected, actual.to_string());
1788
1789 let expected = "provided username cannot contain :".to_string();
1790 let actual = ValidationError {
1791 kind: ValidationErrorType::Username {
1792 len: None,
1793 substring: Some(":"),
1794 },
1795 };
1796 assert_eq!(expected, actual.to_string());
1797 }
1798
1799 #[test]
1800 fn audit_reason_length() {
1801 assert!(audit_reason("").is_ok());
1802 assert!(audit_reason("a").is_ok());
1803 assert!(audit_reason("a".repeat(500)).is_ok());
1804 assert!(audit_reason("a".repeat(512)).is_ok());
1805
1806 assert!(audit_reason("a".repeat(513)).is_err());
1807 }
1808
1809 #[test]
1810 fn auto_moderation_block_action_custom_message() {
1811 assert!(auto_moderation_block_action_custom_message_limit("").is_ok());
1812 assert!(auto_moderation_block_action_custom_message_limit("a".repeat(150)).is_ok());
1813 assert!(matches!(
1814 auto_moderation_block_action_custom_message_limit("a".repeat(151))
1815 .unwrap_err()
1816 .kind,
1817 ValidationErrorType::AutoModerationBlockActionCustomMessageLimit { len: 151 }
1818 ));
1819 }
1820
1821 #[test]
1822 fn auto_moderation_metadata_mention_total() {
1823 assert!(auto_moderation_metadata_mention_total_limit(0).is_ok());
1824 assert!(auto_moderation_metadata_mention_total_limit(1).is_ok());
1825 assert!(auto_moderation_metadata_mention_total_limit(50).is_ok());
1826
1827 assert!(auto_moderation_metadata_mention_total_limit(51).is_err());
1828 }
1829
1830 #[test]
1831 fn auto_moderation_metadata_keyword_filter_max() {
1832 let mut keywords = (0..1000).map(|_| "a").collect::<Vec<_>>();
1833
1834 assert!(auto_moderation_metadata_keyword_filter(&[] as &[&str]).is_ok());
1835 assert!(auto_moderation_metadata_keyword_filter(&["a".repeat(60)]).is_ok());
1836 assert!(auto_moderation_metadata_keyword_filter(&keywords).is_ok());
1837
1838 keywords.push("a");
1839
1840 assert!(auto_moderation_metadata_keyword_filter(&["a".repeat(61)]).is_err());
1841 assert!(auto_moderation_metadata_keyword_filter(&keywords).is_err());
1842 }
1843
1844 #[test]
1845 fn auto_moderation_metadata_keyword_allow_list_max() {
1846 let mut allow_list = (0..100).map(|_| "a").collect::<Vec<_>>();
1847
1848 assert!(auto_moderation_metadata_keyword_allow_list(&[] as &[&str]).is_ok());
1849 assert!(auto_moderation_metadata_keyword_allow_list(&["a".repeat(60)]).is_ok());
1850
1851 allow_list.push("a");
1852
1853 assert!(auto_moderation_metadata_keyword_allow_list(&["a".repeat(61)]).is_err());
1854 assert!(auto_moderation_metadata_keyword_allow_list(&allow_list).is_err());
1855 }
1856
1857 #[test]
1858 fn auto_moderation_metadata_preset_allow_list_max() {
1859 let mut allow_list = (0..1000).map(|_| "a").collect::<Vec<_>>();
1860
1861 assert!(auto_moderation_metadata_preset_allow_list(&[] as &[&str]).is_ok());
1862 assert!(auto_moderation_metadata_preset_allow_list(&["a".repeat(60)]).is_ok());
1863
1864 allow_list.push("a");
1865
1866 assert!(auto_moderation_metadata_preset_allow_list(&["a".repeat(61)]).is_err());
1867 assert!(auto_moderation_metadata_preset_allow_list(&allow_list).is_err());
1868 }
1869
1870 #[test]
1871 fn auto_moderation_metadata_regex_patterns_max() {
1872 let mut patterns = (0..10).map(|_| "a").collect::<Vec<_>>();
1873
1874 assert!(auto_moderation_metadata_regex_patterns(&[] as &[&str]).is_ok());
1875 assert!(auto_moderation_metadata_regex_patterns(&["a".repeat(260)]).is_ok());
1876
1877 patterns.push("a");
1878
1879 assert!(auto_moderation_metadata_regex_patterns(&["a".repeat(261)]).is_err());
1880 assert!(auto_moderation_metadata_regex_patterns(&patterns).is_err());
1881 }
1882
1883 #[test]
1884 fn auto_moderation_exempt_roles_max() {
1885 let mut roles = (1..=20).map(Id::new).collect::<Vec<_>>();
1886
1887 assert!(auto_moderation_exempt_roles(&[]).is_ok());
1888 assert!(auto_moderation_exempt_roles(&roles).is_ok());
1889
1890 roles.push(Id::new(21));
1891
1892 assert!(auto_moderation_exempt_roles(&roles).is_err());
1893 }
1894
1895 #[test]
1896 fn auto_moderation_exempt_channels_max() {
1897 let mut channels = (1..=50).map(Id::new).collect::<Vec<_>>();
1898
1899 assert!(auto_moderation_exempt_channels(&[]).is_ok());
1900 assert!(auto_moderation_exempt_channels(&channels).is_ok());
1901
1902 channels.push(Id::new(51));
1903
1904 assert!(auto_moderation_exempt_channels(&channels).is_err());
1905 }
1906
1907 #[test]
1908 fn auto_moderation_action_metadata_duration_seconds_max() {
1909 assert!(auto_moderation_action_metadata_duration_seconds(0).is_ok());
1910 assert!(auto_moderation_action_metadata_duration_seconds(1).is_ok());
1911 assert!(auto_moderation_action_metadata_duration_seconds(2_419_200).is_ok());
1912
1913 assert!(auto_moderation_action_metadata_duration_seconds(2_419_201).is_err());
1914 }
1915
1916 #[test]
1917 fn bio_length() {
1918 assert!(bio("a").is_ok());
1919 assert!(bio("a".repeat(400)).is_ok());
1920
1921 assert!(bio("").is_err());
1922 assert!(bio("b".repeat(401)).is_err());
1923 }
1924
1925 #[test]
1926 fn create_guild_ban_delete_message_seconds_max() {
1927 assert!(create_guild_ban_delete_message_seconds(0).is_ok());
1928 assert!(create_guild_ban_delete_message_seconds(1).is_ok());
1929 assert!(create_guild_ban_delete_message_seconds(604_800).is_ok());
1930
1931 assert!(create_guild_ban_delete_message_seconds(604_801).is_err());
1932 }
1933
1934 #[test]
1935 fn communication_disabled_until_max() {
1936 #[allow(clippy::cast_possible_wrap)]
1937 let now = SystemTime::now()
1938 .duration_since(UNIX_EPOCH)
1939 .unwrap()
1940 .as_secs() as i64;
1941
1942 let ok_timestamp =
1943 Timestamp::from_secs(now + COMMUNICATION_DISABLED_MAX_DURATION - 1000).unwrap();
1944 assert!(communication_disabled_until(ok_timestamp).is_ok());
1945
1946 let err_timestamp =
1947 Timestamp::from_secs(now + COMMUNICATION_DISABLED_MAX_DURATION + 1000).unwrap();
1948 assert!(communication_disabled_until(err_timestamp).is_err());
1949 }
1950
1951 #[test]
1952 fn get_channel_messages_limit_count() {
1953 assert!(get_channel_messages_limit(1).is_ok());
1954 assert!(get_channel_messages_limit(100).is_ok());
1955
1956 assert!(get_channel_messages_limit(0).is_err());
1957 assert!(get_channel_messages_limit(101).is_err());
1958 }
1959
1960 #[test]
1961 fn get_current_user_guilds_limit_count() {
1962 assert!(get_current_user_guilds_limit(1).is_ok());
1963 assert!(get_current_user_guilds_limit(200).is_ok());
1964
1965 assert!(get_current_user_guilds_limit(0).is_err());
1966 assert!(get_current_user_guilds_limit(201).is_err());
1967 }
1968
1969 #[test]
1970 fn get_guild_log_limit_count() {
1971 assert!(get_guild_audit_log_limit(1).is_ok());
1972 assert!(get_guild_audit_log_limit(100).is_ok());
1973
1974 assert!(get_guild_audit_log_limit(0).is_err());
1975 assert!(get_guild_audit_log_limit(101).is_err());
1976 }
1977
1978 #[test]
1979 fn get_guild_bans_limit_count() {
1980 assert!(get_guild_bans_limit(0).is_ok());
1981 assert!(get_guild_bans_limit(1000).is_ok());
1982
1983 assert!(get_guild_bans_limit(1001).is_err());
1984 }
1985
1986 #[test]
1987 fn get_guild_members_limit_count() {
1988 assert!(get_guild_members_limit(1).is_ok());
1989 assert!(get_guild_members_limit(1000).is_ok());
1990
1991 assert!(get_guild_members_limit(0).is_err());
1992 assert!(get_guild_members_limit(1001).is_err());
1993 }
1994
1995 #[test]
1996 fn get_reactions_limit_count() {
1997 assert!(get_reactions_limit(1).is_ok());
1998 assert!(get_reactions_limit(100).is_ok());
1999
2000 assert!(get_reactions_limit(0).is_err());
2001 assert!(get_reactions_limit(101).is_err());
2002 }
2003
2004 #[test]
2005 fn guild_name_length() {
2006 assert!(guild_name("aa").is_ok());
2007 assert!(guild_name("a".repeat(100)).is_ok());
2008
2009 assert!(guild_name("").is_err());
2010 assert!(guild_name("a").is_err());
2011 assert!(guild_name("a".repeat(101)).is_err());
2012 }
2013
2014 #[test]
2015 fn guild_prune_days_length() {
2016 assert!(guild_prune_days(1).is_ok());
2017 assert!(guild_prune_days(30).is_ok());
2018
2019 assert!(guild_prune_days(0).is_err());
2020 assert!(guild_prune_days(31).is_err());
2021 assert!(guild_prune_days(100).is_err());
2022 }
2023
2024 #[test]
2025 fn invite_max_age_length() {
2026 assert!(invite_max_age(0).is_ok());
2027 assert!(invite_max_age(86_400).is_ok());
2028 assert!(invite_max_age(604_800).is_ok());
2029
2030 assert!(invite_max_age(604_801).is_err());
2031 }
2032
2033 #[test]
2034 fn invite_max_uses_count() {
2035 assert!(invite_max_uses(0).is_ok());
2036 assert!(invite_max_uses(100).is_ok());
2037
2038 assert!(invite_max_uses(101).is_err());
2039 }
2040
2041 #[test]
2042 fn nickname_length() {
2043 assert!(nickname("a").is_ok());
2044 assert!(nickname("a".repeat(32)).is_ok());
2045
2046 assert!(nickname("").is_err());
2047 assert!(nickname("a".repeat(33)).is_err());
2048 }
2049
2050 #[test]
2051 fn pin_limit_test() {
2052 assert!(pin_limit(1).is_ok());
2053 assert!(pin_limit(50).is_ok());
2054
2055 assert!(pin_limit(0).is_err());
2056 assert!(pin_limit(51).is_err());
2057 }
2058
2059 #[test]
2060 fn scheduled_event_description_length() {
2061 assert!(scheduled_event_description("a").is_ok());
2062 assert!(scheduled_event_description("a".repeat(1000)).is_ok());
2063
2064 assert!(scheduled_event_description("").is_err());
2065 assert!(scheduled_event_description("a".repeat(1001)).is_err());
2066 }
2067
2068 #[test]
2069 fn scheduled_event_get_users_length() {
2070 assert!(scheduled_event_get_users(0).is_err());
2071 assert!(scheduled_event_get_users(101).is_err());
2072 assert!(scheduled_event_get_users(100).is_ok());
2073 assert!(scheduled_event_get_users(1).is_ok());
2074 }
2075
2076 #[test]
2077 fn scheduled_event_name_length() {
2078 assert!(scheduled_event_name("a").is_ok());
2079 assert!(scheduled_event_name("a".repeat(100)).is_ok());
2080
2081 assert!(scheduled_event_name("").is_err());
2082 assert!(scheduled_event_name("a".repeat(101)).is_err());
2083 }
2084
2085 #[test]
2086 fn search_guild_members_limit_count() {
2087 assert!(search_guild_members_limit(1).is_ok());
2088 assert!(search_guild_members_limit(1000).is_ok());
2089
2090 assert!(search_guild_members_limit(0).is_err());
2091 assert!(search_guild_members_limit(1001).is_err());
2092 }
2093
2094 #[test]
2095 fn stage_topic_length() {
2096 assert!(stage_topic("a").is_ok());
2097 assert!(stage_topic("a".repeat(120)).is_ok());
2098
2099 assert!(stage_topic("").is_err());
2100 assert!(stage_topic("a".repeat(121)).is_err());
2101 }
2102
2103 #[test]
2104 fn template_description_length() {
2105 assert!(template_description("").is_ok());
2106 assert!(template_description("a").is_ok());
2107 assert!(template_description("a".repeat(120)).is_ok());
2108
2109 assert!(template_description("a".repeat(121)).is_err());
2110 }
2111
2112 #[test]
2113 fn template_name_length() {
2114 assert!(template_name("a").is_ok());
2115 assert!(template_name("a".repeat(100)).is_ok());
2116
2117 assert!(template_name("").is_err());
2118 assert!(template_name("a".repeat(101)).is_err());
2119 }
2120
2121 #[test]
2122 fn username_length() {
2123 assert!(username("aa").is_ok());
2124 assert!(username("a".repeat(32)).is_ok());
2125
2126 assert!(username("a").is_err());
2127 assert!(username("a".repeat(33)).is_err());
2128
2129 assert!(username("no @ in username").is_err());
2130 assert!(username("no # in username").is_err());
2131 assert!(username("no : in username").is_err());
2132 assert!(username(r"no ``` in username").is_err());
2133 assert!(username("no discord in username").is_err());
2134 assert!(username("everyone").is_err());
2135 assert!(username("here").is_err());
2136 }
2137
2138 #[test]
2139 fn webhook_username_length() {
2140 assert!(webhook_username("aa").is_ok());
2141 assert!(webhook_username("a".repeat(80)).is_ok());
2142
2143 assert!(webhook_username("a").is_err());
2144 assert!(webhook_username("a".repeat(81)).is_err());
2145
2146 assert!(webhook_username("clyde").is_err());
2147 }
2148}