1use super::{CategoryFields, GuildChannelFields, RoleFields, TextFields, VoiceFields};
2use std::{
3 error::Error,
4 fmt::{Display, Formatter, Result as FmtResult},
5};
6use twilight_model::{
7 channel::ChannelType,
8 guild::Permissions,
9 http::permission_overwrite::PermissionOverwrite,
10 id::{
11 marker::{ChannelMarker, RoleMarker},
12 Id,
13 },
14};
15
16#[derive(Debug)]
18pub struct RoleFieldsError {
19 kind: RoleFieldsErrorType,
20}
21
22impl RoleFieldsError {
23 #[must_use = "retrieving the type has no effect if left unused"]
25 pub const fn kind(&self) -> &RoleFieldsErrorType {
26 &self.kind
27 }
28
29 #[allow(clippy::unused_self)]
31 #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
32 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
33 None
34 }
35
36 #[must_use = "consuming the error into its parts has no effect if left unused"]
38 pub fn into_parts(self) -> (RoleFieldsErrorType, Option<Box<dyn Error + Send + Sync>>) {
39 (self.kind, None)
40 }
41}
42
43impl Display for RoleFieldsError {
44 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
45 match &self.kind {
46 RoleFieldsErrorType::ColorNotRgb { color } => {
47 f.write_str("the color ")?;
48 Display::fmt(color, f)?;
49
50 f.write_str(" is invalid")
51 }
52 RoleFieldsErrorType::IdInvalid => {
53 f.write_str("the given id value is 1, which is not acceptable")
54 }
55 }
56 }
57}
58
59impl Error for RoleFieldsError {}
60
61#[derive(Debug)]
63#[non_exhaustive]
64pub enum RoleFieldsErrorType {
65 ColorNotRgb {
67 color: u32,
69 },
70 IdInvalid,
72}
73
74#[derive(Debug)]
76#[must_use = "must be built into a role"]
77pub struct RoleFieldsBuilder(Result<RoleFields, RoleFieldsError>);
78
79impl RoleFieldsBuilder {
80 pub const COLOR_MAXIMUM: u32 = 0xff_ff_ff;
86
87 const ROLE_ID: Id<RoleMarker> = Id::new(1);
88
89 pub const fn new(name: String) -> Self {
91 Self(Ok(RoleFields {
92 color: None,
93 hoist: None,
94 id: Self::ROLE_ID,
95 mentionable: None,
96 name,
97 permissions: None,
98 position: None,
99 }))
100 }
101
102 #[allow(clippy::missing_const_for_fn)]
109 pub fn build(self) -> Result<RoleFields, RoleFieldsError> {
110 self.0
111 }
112
113 pub fn color(mut self, color: u32) -> Self {
120 self.0 = self.0.and_then(|mut fields| {
121 if color > Self::COLOR_MAXIMUM {
122 return Err(RoleFieldsError {
123 kind: RoleFieldsErrorType::ColorNotRgb { color },
124 });
125 }
126
127 fields.color.replace(color);
128
129 Ok(fields)
130 });
131
132 self
133 }
134
135 pub fn hoist(mut self) -> Self {
137 if let Ok(fields) = self.0.as_mut() {
138 fields.hoist = Some(true);
139 }
140
141 self
142 }
143
144 pub fn id(mut self, id: Id<RoleMarker>) -> Self {
151 self.0 = self.0.and_then(|mut fields| {
152 if id == Self::ROLE_ID {
153 return Err(RoleFieldsError {
154 kind: RoleFieldsErrorType::IdInvalid,
155 });
156 }
157
158 fields.id = id;
159
160 Ok(fields)
161 });
162
163 self
164 }
165
166 pub fn mentionable(mut self) -> Self {
168 if let Ok(fields) = self.0.as_mut() {
169 fields.mentionable = Some(true);
170 }
171
172 self
173 }
174
175 pub fn permissions(mut self, permissions: Permissions) -> Self {
177 if let Ok(fields) = self.0.as_mut() {
178 fields.permissions = Some(permissions);
179 }
180
181 self
182 }
183
184 pub fn position(mut self, position: i64) -> Self {
186 if let Ok(fields) = self.0.as_mut() {
187 fields.position = Some(position);
188 }
189
190 self
191 }
192}
193
194#[derive(Debug)]
196pub struct TextFieldsError {
197 kind: TextFieldsErrorType,
198}
199
200impl TextFieldsError {
201 #[must_use = "retrieving the type has no effect if left unused"]
203 pub const fn kind(&self) -> &TextFieldsErrorType {
204 &self.kind
205 }
206
207 #[allow(clippy::unused_self)]
209 #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
210 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
211 None
212 }
213
214 #[must_use = "consuming the error into its parts has no effect if left unused"]
216 pub fn into_parts(self) -> (TextFieldsErrorType, Option<Box<dyn Error + Send + Sync>>) {
217 (self.kind, None)
218 }
219}
220
221impl Display for TextFieldsError {
222 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
223 match &self.kind {
224 TextFieldsErrorType::NameTooShort { name } => {
225 f.write_str("the name is too short: ")?;
226
227 Display::fmt(&name.len(), f)
228 }
229 TextFieldsErrorType::NameTooLong { name } => {
230 f.write_str("the name is too long: ")?;
231
232 Display::fmt(&name.len(), f)
233 }
234 TextFieldsErrorType::RateLimitInvalid { limit } => {
235 f.write_str("the rate limit ")?;
236 Display::fmt(limit, f)?;
237
238 f.write_str(" is invalid")
239 }
240 TextFieldsErrorType::TopicTooLong { topic } => {
241 f.write_str("the topic is too long: ")?;
242
243 Display::fmt(&topic.len(), f)
244 }
245 }
246 }
247}
248
249impl Error for TextFieldsError {}
250
251#[derive(Debug)]
253#[non_exhaustive]
254pub enum TextFieldsErrorType {
255 NameTooShort {
257 name: String,
259 },
260 NameTooLong {
262 name: String,
264 },
265 RateLimitInvalid {
267 limit: u16,
269 },
270 TopicTooLong {
272 topic: String,
274 },
275}
276
277#[derive(Debug)]
279#[must_use = "must be built into a text channel"]
280pub struct TextFieldsBuilder(Result<TextFields, TextFieldsError>);
281
282impl TextFieldsBuilder {
283 pub const MIN_NAME_LENGTH: usize = 1;
289
290 pub const MAX_NAME_LENGTH: usize = 100;
296
297 pub const MAX_RATE_LIMIT: u16 = 21600;
303
304 pub const MAX_TOPIC_LENGTH: usize = 1024;
310
311 pub fn new(name: String) -> Self {
313 let fields = Ok(TextFields {
314 id: Id::new(1),
315 kind: ChannelType::GuildText,
316 name: String::new(),
317 nsfw: None,
318 permission_overwrites: None,
319 parent_id: None,
320 rate_limit_per_user: None,
321 topic: None,
322 })
323 .and_then(|mut fields| {
324 if name.len() < Self::MIN_NAME_LENGTH {
325 return Err(TextFieldsError {
326 kind: TextFieldsErrorType::NameTooShort { name },
327 });
328 }
329
330 if name.len() > Self::MAX_NAME_LENGTH {
331 return Err(TextFieldsError {
332 kind: TextFieldsErrorType::NameTooLong { name },
333 });
334 }
335
336 fields.name = name;
337
338 Ok(fields)
339 });
340
341 Self(fields)
342 }
343
344 #[allow(clippy::missing_const_for_fn)]
354 pub fn build(self) -> Result<TextFields, TextFieldsError> {
355 self.0
356 }
357
358 pub fn nsfw(mut self) -> Self {
360 if let Ok(fields) = self.0.as_mut() {
361 fields.nsfw = Some(true);
362 }
363
364 self
365 }
366
367 pub fn permission_overwrites(mut self, overwrites: Vec<PermissionOverwrite>) -> Self {
369 if let Ok(fields) = self.0.as_mut() {
370 fields.permission_overwrites.replace(overwrites);
371 }
372
373 self
374 }
375
376 pub fn rate_limit_per_user(mut self, limit: u16) -> Self {
383 self.0 = self.0.and_then(|mut fields| {
384 if limit > Self::MAX_RATE_LIMIT {
385 return Err(TextFieldsError {
386 kind: TextFieldsErrorType::RateLimitInvalid { limit },
387 });
388 }
389
390 fields.rate_limit_per_user.replace(limit);
391
392 Ok(fields)
393 });
394
395 self
396 }
397
398 pub fn topic(mut self, topic: String) -> Self {
405 self.0 = self.0.and_then(|mut fields| {
406 if topic.len() > Self::MAX_TOPIC_LENGTH {
407 return Err(TextFieldsError {
408 kind: TextFieldsErrorType::TopicTooLong { topic },
409 });
410 }
411
412 fields.topic.replace(topic);
413
414 Ok(fields)
415 });
416
417 self
418 }
419}
420
421#[derive(Debug)]
423pub struct VoiceFieldsError {
424 kind: VoiceFieldsErrorType,
425}
426
427impl VoiceFieldsError {
428 #[must_use = "retrieving the type has no effect if left unused"]
430 pub const fn kind(&self) -> &VoiceFieldsErrorType {
431 &self.kind
432 }
433
434 #[allow(clippy::unused_self)]
436 #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
437 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
438 None
439 }
440
441 #[must_use = "consuming the error into its parts has no effect if left unused"]
443 pub fn into_parts(self) -> (VoiceFieldsErrorType, Option<Box<dyn Error + Send + Sync>>) {
444 (self.kind, None)
445 }
446}
447
448impl Display for VoiceFieldsError {
449 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
450 match &self.kind {
451 VoiceFieldsErrorType::NameTooShort { name } => {
452 f.write_str("the name is too short: ")?;
453
454 Display::fmt(&name.len(), f)
455 }
456 VoiceFieldsErrorType::NameTooLong { name } => {
457 f.write_str("the name is too long: ")?;
458
459 Display::fmt(&name.len(), f)
460 }
461 }
462 }
463}
464
465impl Error for VoiceFieldsError {}
466
467#[derive(Debug)]
469#[non_exhaustive]
470pub enum VoiceFieldsErrorType {
471 NameTooShort {
473 name: String,
475 },
476 NameTooLong {
478 name: String,
480 },
481}
482
483#[derive(Debug)]
485#[must_use = "must be built into a voice channel"]
486pub struct VoiceFieldsBuilder(Result<VoiceFields, VoiceFieldsError>);
487
488impl VoiceFieldsBuilder {
489 pub const MIN_NAME_LENGTH: usize = 1;
495
496 pub const MAX_NAME_LENGTH: usize = 100;
502
503 pub fn new(name: String) -> Self {
505 let fields = Ok(VoiceFields {
506 bitrate: None,
507 id: Id::new(1),
508 kind: ChannelType::GuildVoice,
509 name: String::new(),
510 permission_overwrites: None,
511 parent_id: None,
512 user_limit: None,
513 })
514 .and_then(|mut fields| {
515 if name.len() < Self::MIN_NAME_LENGTH {
516 return Err(VoiceFieldsError {
517 kind: VoiceFieldsErrorType::NameTooShort { name },
518 });
519 }
520
521 if name.len() > Self::MAX_NAME_LENGTH {
522 return Err(VoiceFieldsError {
523 kind: VoiceFieldsErrorType::NameTooLong { name },
524 });
525 }
526
527 fields.name = name;
528
529 Ok(fields)
530 });
531
532 Self(fields)
533 }
534
535 #[allow(clippy::missing_const_for_fn)]
545 pub fn build(self) -> Result<VoiceFields, VoiceFieldsError> {
546 self.0
547 }
548
549 pub fn bitrate(mut self, bitrate: u32) -> Self {
551 if let Ok(fields) = self.0.as_mut() {
552 fields.bitrate = Some(bitrate);
553 }
554
555 self
556 }
557
558 pub fn permission_overwrites(mut self, overwrites: Vec<PermissionOverwrite>) -> Self {
560 if let Ok(fields) = self.0.as_mut() {
561 fields.permission_overwrites.replace(overwrites);
562 }
563
564 self
565 }
566
567 pub fn user_limit(mut self, limit: u16) -> Self {
569 if let Ok(fields) = self.0.as_mut() {
570 fields.user_limit = Some(limit);
571 }
572
573 self
574 }
575}
576
577#[derive(Debug)]
579pub struct CategoryFieldsError {
580 kind: CategoryFieldsErrorType,
581}
582
583impl CategoryFieldsError {
584 #[must_use = "retrieving the type has no effect if left unused"]
586 pub const fn kind(&self) -> &CategoryFieldsErrorType {
587 &self.kind
588 }
589
590 #[allow(clippy::unused_self)]
592 #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
593 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
594 None
595 }
596
597 #[must_use = "consuming the error into its parts has no effect if left unused"]
599 pub fn into_parts(
600 self,
601 ) -> (
602 CategoryFieldsErrorType,
603 Option<Box<dyn Error + Send + Sync>>,
604 ) {
605 (self.kind, None)
606 }
607}
608
609impl Display for CategoryFieldsError {
610 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
611 match &self.kind {
612 CategoryFieldsErrorType::NameTooShort { name } => {
613 f.write_str("the name is too short: ")?;
614
615 Display::fmt(&name.len(), f)
616 }
617 CategoryFieldsErrorType::NameTooLong { name } => {
618 f.write_str("the name is too long: ")?;
619
620 Display::fmt(&name.len(), f)
621 }
622 }
623 }
624}
625
626impl Error for CategoryFieldsError {}
627
628#[derive(Debug)]
630#[non_exhaustive]
631pub enum CategoryFieldsErrorType {
632 NameTooShort {
634 name: String,
636 },
637 NameTooLong {
639 name: String,
641 },
642}
643
644#[derive(Debug)]
646#[must_use = "must be built into a category channel"]
647pub struct CategoryFieldsBuilder {
648 fields: Result<CategoryFields, CategoryFieldsError>,
649 channels: Vec<GuildChannelFields>,
650}
651
652impl CategoryFieldsBuilder {
653 pub const MIN_NAME_LENGTH: usize = 1;
659
660 pub const MAX_NAME_LENGTH: usize = 100;
666
667 pub fn new(name: String) -> Self {
669 let fields = Ok(CategoryFields {
670 id: Id::new(1),
671 name: String::new(),
672 kind: ChannelType::GuildCategory,
673 permission_overwrites: None,
674 })
675 .and_then(|mut fields| {
676 if name.len() < Self::MIN_NAME_LENGTH {
677 return Err(CategoryFieldsError {
678 kind: CategoryFieldsErrorType::NameTooShort { name },
679 });
680 }
681
682 if name.len() > Self::MAX_NAME_LENGTH {
683 return Err(CategoryFieldsError {
684 kind: CategoryFieldsErrorType::NameTooLong { name },
685 });
686 }
687
688 fields.name = name;
689
690 Ok(fields)
691 });
692
693 Self {
694 fields,
695 channels: Vec::new(),
696 }
697 }
698
699 pub(super) fn build(
709 mut self,
710 id: Id<ChannelMarker>,
711 ) -> Result<Vec<GuildChannelFields>, CategoryFieldsError> {
712 let fields = self.fields?;
713
714 for channel in &mut self.channels {
715 match channel {
716 GuildChannelFields::Text(t) => t.parent_id.replace(id),
717 GuildChannelFields::Voice(v) => v.parent_id.replace(id),
718 GuildChannelFields::Category(_) => None,
719 };
720 }
721
722 self.channels.insert(
723 0,
724 GuildChannelFields::Category(CategoryFields { id, ..fields }),
725 );
726
727 Ok(self.channels)
728 }
729
730 pub fn add_text(mut self, channel: TextFields) -> Self {
732 self.channels.push(GuildChannelFields::Text(channel));
733
734 self
735 }
736
737 pub fn add_voice(mut self, channel: VoiceFields) -> Self {
739 self.channels.push(GuildChannelFields::Voice(channel));
740
741 self
742 }
743}
744
745#[derive(Debug)]
747#[must_use = "must be built into a list of channels"]
748pub struct GuildChannelFieldsBuilder(Result<Vec<GuildChannelFields>, CategoryFieldsError>);
749
750impl GuildChannelFieldsBuilder {
751 pub const fn new() -> Self {
753 Self(Ok(Vec::new()))
754 }
755
756 #[allow(clippy::missing_const_for_fn)]
766 pub fn build(self) -> Result<Vec<GuildChannelFields>, CategoryFieldsError> {
767 self.0
768 }
769
770 pub fn add_text(mut self, channel: TextFields) -> Self {
772 if let Ok(list) = self.0.as_mut() {
773 list.push(GuildChannelFields::Text(channel));
774 }
775
776 self
777 }
778
779 pub fn add_voice(mut self, channel: VoiceFields) -> Self {
781 if let Ok(list) = self.0.as_mut() {
782 list.push(GuildChannelFields::Voice(channel));
783 }
784
785 self
786 }
787
788 pub fn add_category_builder(mut self, channel: CategoryFieldsBuilder) -> Self {
790 self.0 = self.0.and_then(|mut list| {
791 let last_id = list
792 .iter()
793 .rev()
794 .find(|c| matches!(c, GuildChannelFields::Category(_)))
795 .map_or(Id::new(1), GuildChannelFields::id);
796
797 let mut channels = channel.build(Id::new(last_id.get() + 1))?;
798
799 list.append(&mut channels);
800
801 Ok(list)
802 });
803
804 self
805 }
806}
807
808impl Default for GuildChannelFieldsBuilder {
809 fn default() -> Self {
810 Self::new()
811 }
812}
813
814#[cfg(test)]
815mod tests {
816 use super::{
817 super::{CategoryFields, GuildChannelFields, RoleFields, TextFields, VoiceFields},
818 CategoryFieldsBuilder, CategoryFieldsErrorType, GuildChannelFieldsBuilder,
819 RoleFieldsBuilder, RoleFieldsErrorType, TextFieldsBuilder, TextFieldsErrorType,
820 VoiceFieldsBuilder, VoiceFieldsErrorType,
821 };
822 use static_assertions::assert_impl_all;
823 use std::fmt::Debug;
824 use twilight_model::{
825 channel::ChannelType,
826 guild::Permissions,
827 http::permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
828 id::Id,
829 };
830
831 assert_impl_all!(RoleFieldsBuilder: Debug, Send, Sync);
832 assert_impl_all!(TextFieldsBuilder: Debug, Send, Sync);
833 assert_impl_all!(VoiceFieldsBuilder: Debug, Send, Sync);
834 assert_impl_all!(CategoryFieldsBuilder: Debug, Send, Sync);
835 assert_impl_all!(GuildChannelFieldsBuilder: Debug, Send, Sync);
836
837 fn perms() -> Permissions {
838 Permissions::CONNECT | Permissions::SPEAK | Permissions::SEND_TTS_MESSAGES
839 }
840
841 fn overwrite() -> PermissionOverwrite {
842 PermissionOverwrite {
843 allow: Some(perms()),
844 deny: Some(Permissions::empty()),
845 id: Id::new(2),
846 kind: PermissionOverwriteType::Role,
847 }
848 }
849
850 fn voice() -> VoiceFields {
851 VoiceFieldsBuilder::new("voicename".to_owned())
852 .bitrate(96_000)
853 .permission_overwrites(vec![overwrite()])
854 .user_limit(40)
855 .build()
856 .unwrap()
857 }
858
859 #[test]
860 fn role_fields() {
861 assert!(matches!(
862 RoleFieldsBuilder::new("role".to_owned())
863 .color(123_123_123)
864 .build()
865 .unwrap_err()
866 .kind(),
867 RoleFieldsErrorType::ColorNotRgb { color: 123_123_123 },
868 ));
869
870 let fields = RoleFieldsBuilder::new("rolename".to_owned())
871 .color(0x12_34_56)
872 .hoist()
873 .id(Id::new(2))
874 .mentionable()
875 .permissions(Permissions::empty())
876 .position(1)
877 .build()
878 .unwrap();
879
880 assert_eq!(
881 fields,
882 RoleFields {
883 color: Some(0x12_34_56),
884 hoist: Some(true),
885 id: Id::new(2),
886 mentionable: Some(true),
887 name: String::from("rolename"),
888 permissions: Some(Permissions::empty()),
889 position: Some(1),
890 }
891 );
892 }
893
894 #[test]
895 fn voice_fields() {
896 assert!(matches!(
897 VoiceFieldsBuilder::new(String::new()).build().unwrap_err().kind(),
898 VoiceFieldsErrorType::NameTooShort { name }
899 if name.is_empty()
900 ));
901
902 assert_eq!(
903 voice(),
904 VoiceFields {
905 bitrate: Some(96_000),
906 id: Id::new(1),
907 kind: ChannelType::GuildVoice,
908 name: String::from("voicename"),
909 permission_overwrites: Some(vec![PermissionOverwrite {
910 allow: Some(perms()),
911 deny: Some(Permissions::empty()),
912 id: Id::new(2),
913 kind: PermissionOverwriteType::Role,
914 }]),
915 parent_id: None,
916 user_limit: Some(40),
917 }
918 );
919 }
920
921 fn text() -> TextFields {
922 TextFieldsBuilder::new("textname".to_owned())
923 .nsfw()
924 .permission_overwrites(vec![overwrite()])
925 .rate_limit_per_user(4_000)
926 .topic("a topic".to_owned())
927 .build()
928 .unwrap()
929 }
930
931 #[test]
932 fn text_fields() {
933 assert!(matches!(
934 TextFieldsBuilder::new(String::new()).build().unwrap_err().kind(),
935 TextFieldsErrorType::NameTooShort { name }
936 if name.is_empty()
937 ));
938
939 assert_eq!(
940 text(),
941 TextFields {
942 id: Id::new(1),
943 kind: ChannelType::GuildText,
944 name: String::from("textname"),
945 nsfw: Some(true),
946 permission_overwrites: Some(vec![PermissionOverwrite {
947 allow: Some(perms()),
948 deny: Some(Permissions::empty()),
949 id: Id::new(2),
950 kind: PermissionOverwriteType::Role
951 }]),
952 parent_id: None,
953 rate_limit_per_user: Some(4_000),
954 topic: Some(String::from("a topic")),
955 }
956 );
957 }
958
959 fn category() -> CategoryFieldsBuilder {
960 CategoryFieldsBuilder::new("category".to_owned())
961 .add_text(text())
962 .add_voice(voice())
963 }
964
965 #[test]
966 fn category_fields() {
967 assert!(matches!(
968 CategoryFieldsBuilder::new(String::new()).build(Id::new(4)).unwrap_err().kind(),
969 CategoryFieldsErrorType::NameTooShort { name }
970 if name.is_empty()
971 ));
972
973 let fields = category();
974 let channels = GuildChannelFieldsBuilder::new().add_category_builder(fields);
975
976 assert_eq!(
977 channels.build().unwrap(),
978 vec![
979 GuildChannelFields::Category(CategoryFields {
980 id: Id::new(2),
981 kind: ChannelType::GuildCategory,
982 name: String::from("category"),
983 permission_overwrites: None,
984 }),
985 GuildChannelFields::Text(TextFields {
986 id: Id::new(1),
987 kind: ChannelType::GuildText,
988 name: String::from("textname"),
989 nsfw: Some(true),
990 permission_overwrites: Some(vec![PermissionOverwrite {
991 allow: Some(
992 Permissions::CONNECT
993 | Permissions::SPEAK
994 | Permissions::SEND_TTS_MESSAGES
995 ),
996 deny: Some(Permissions::empty()),
997 id: Id::new(2),
998 kind: PermissionOverwriteType::Role,
999 }]),
1000 parent_id: Some(Id::new(2)),
1001 rate_limit_per_user: Some(4_000),
1002 topic: Some(String::from("a topic")),
1003 }),
1004 GuildChannelFields::Voice(VoiceFields {
1005 bitrate: Some(96_000),
1006 id: Id::new(1),
1007 kind: ChannelType::GuildVoice,
1008 name: String::from("voicename"),
1009 permission_overwrites: Some(vec![PermissionOverwrite {
1010 allow: Some(
1011 Permissions::CONNECT
1012 | Permissions::SPEAK
1013 | Permissions::SEND_TTS_MESSAGES
1014 ),
1015 deny: Some(Permissions::empty()),
1016 id: Id::new(2),
1017 kind: PermissionOverwriteType::Role,
1018 }]),
1019 parent_id: Some(Id::new(2)),
1020 user_limit: Some(40),
1021 }),
1022 ]
1023 );
1024 }
1025
1026 #[test]
1027 fn channels() {
1028 let channels = GuildChannelFieldsBuilder::new()
1029 .add_text(text())
1030 .add_voice(voice());
1031
1032 assert_eq!(
1033 channels.build().unwrap(),
1034 vec![
1035 GuildChannelFields::Text(TextFields {
1036 id: Id::new(1),
1037 kind: ChannelType::GuildText,
1038 name: String::from("textname"),
1039 nsfw: Some(true),
1040 permission_overwrites: Some(vec![PermissionOverwrite {
1041 allow: Some(
1042 Permissions::CONNECT
1043 | Permissions::SPEAK
1044 | Permissions::SEND_TTS_MESSAGES
1045 ),
1046 deny: Some(Permissions::empty()),
1047 id: Id::new(2),
1048 kind: PermissionOverwriteType::Role,
1049 }]),
1050 parent_id: None,
1051 rate_limit_per_user: Some(4_000),
1052 topic: Some(String::from("a topic")),
1053 }),
1054 GuildChannelFields::Voice(VoiceFields {
1055 bitrate: Some(96_000),
1056 id: Id::new(1),
1057 kind: ChannelType::GuildVoice,
1058 name: String::from("voicename"),
1059 permission_overwrites: Some(vec![PermissionOverwrite {
1060 allow: Some(
1061 Permissions::CONNECT
1062 | Permissions::SPEAK
1063 | Permissions::SEND_TTS_MESSAGES
1064 ),
1065 deny: Some(Permissions::empty()),
1066 id: Id::new(2),
1067 kind: PermissionOverwriteType::Role,
1068 }]),
1069 parent_id: None,
1070 user_limit: Some(40),
1071 }),
1072 ]
1073 );
1074 }
1075}