twilight_model/voice/
voice_state.rs

1use crate::{
2    guild::Member,
3    id::{
4        marker::{ChannelMarker, GuildMarker, UserMarker},
5        Id,
6    },
7    util::Timestamp,
8};
9use serde::{Deserialize, Serialize};
10
11/// User's voice connection status.
12#[allow(clippy::struct_excessive_bools)]
13#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
14pub struct VoiceState {
15    /// Channel this user is connected to.
16    ///
17    /// [`None`] corresponds to being disconnected.
18    pub channel_id: Option<Id<ChannelMarker>>,
19    /// Whether this user is server deafened.
20    pub deaf: bool,
21    /// Guild this voice state is for.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub guild_id: Option<Id<GuildMarker>>,
24    /// Member this voice state is for.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub member: Option<Member>,
27    /// Whether this user is server muted.
28    pub mute: bool,
29    /// Whether this user is locally deafened.
30    pub self_deaf: bool,
31    /// Whether this user is locally muted.
32    pub self_mute: bool,
33    /// Whether this user is streaming using "Go Live".
34    #[serde(default)]
35    pub self_stream: bool,
36    /// Whether this user's camera is enabled.
37    pub self_video: bool,
38    /// Session ID for this voice state.
39    ///
40    /// Used to establish a voice websocket connection.
41    pub session_id: String,
42    /// Whether the user's permission to speak is denied.
43    ///
44    /// Only applies to stage channels.
45    pub suppress: bool,
46    /// User this voice state is for.
47    pub user_id: Id<UserMarker>,
48    /// When the user requested to speak.
49    ///
50    /// # serde
51    ///
52    /// This is serialized as an ISO 8601 timestamp in the format of
53    /// "2021-01-01T01-01-01.010000+00:00".
54    pub request_to_speak_timestamp: Option<Timestamp>,
55}
56
57#[cfg(test)]
58mod tests {
59    use super::VoiceState;
60    use crate::{
61        guild::{Member, MemberFlags},
62        id::Id,
63        user::User,
64        util::datetime::{Timestamp, TimestampParseError},
65    };
66    use serde_test::Token;
67    use std::str::FromStr;
68
69    #[test]
70    fn voice_state() {
71        let value = VoiceState {
72            channel_id: Some(Id::new(1)),
73            deaf: false,
74            guild_id: Some(Id::new(2)),
75            member: None,
76            mute: true,
77            self_deaf: false,
78            self_mute: true,
79            self_stream: false,
80            self_video: false,
81            session_id: "a".to_owned(),
82            suppress: true,
83            user_id: Id::new(3),
84            request_to_speak_timestamp: None,
85        };
86
87        serde_test::assert_tokens(
88            &value,
89            &[
90                Token::Struct {
91                    name: "VoiceState",
92                    len: 12,
93                },
94                Token::Str("channel_id"),
95                Token::Some,
96                Token::NewtypeStruct { name: "Id" },
97                Token::Str("1"),
98                Token::Str("deaf"),
99                Token::Bool(false),
100                Token::Str("guild_id"),
101                Token::Some,
102                Token::NewtypeStruct { name: "Id" },
103                Token::Str("2"),
104                Token::Str("mute"),
105                Token::Bool(true),
106                Token::Str("self_deaf"),
107                Token::Bool(false),
108                Token::Str("self_mute"),
109                Token::Bool(true),
110                Token::Str("self_stream"),
111                Token::Bool(false),
112                Token::Str("self_video"),
113                Token::Bool(false),
114                Token::Str("session_id"),
115                Token::Str("a"),
116                Token::Str("suppress"),
117                Token::Bool(true),
118                Token::Str("user_id"),
119                Token::NewtypeStruct { name: "Id" },
120                Token::Str("3"),
121                Token::Str("request_to_speak_timestamp"),
122                Token::None,
123                Token::StructEnd,
124            ],
125        );
126    }
127
128    #[allow(clippy::too_many_lines)]
129    #[test]
130    fn voice_state_complete() -> Result<(), TimestampParseError> {
131        let joined_at = Some(Timestamp::from_str("2015-04-26T06:26:56.936000+00:00")?);
132        let premium_since = Timestamp::from_str("2021-03-16T14:29:19.046000+00:00")?;
133        let request_to_speak_timestamp = Timestamp::from_str("2021-04-21T22:16:50.000000+00:00")?;
134        let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
135
136        let value = VoiceState {
137            channel_id: Some(Id::new(1)),
138            deaf: false,
139            guild_id: Some(Id::new(2)),
140            member: Some(Member {
141                avatar: None,
142                communication_disabled_until: None,
143                deaf: false,
144                flags,
145                joined_at,
146                mute: true,
147                nick: Some("twilight".to_owned()),
148                pending: false,
149                premium_since: Some(premium_since),
150                roles: Vec::new(),
151                user: User {
152                    accent_color: None,
153                    avatar: None,
154                    avatar_decoration: None,
155                    avatar_decoration_data: None,
156                    banner: None,
157                    bot: false,
158                    discriminator: 1,
159                    email: None,
160                    flags: None,
161                    global_name: Some("test".to_owned()),
162                    id: Id::new(3),
163                    locale: None,
164                    mfa_enabled: None,
165                    name: "twilight".to_owned(),
166                    premium_type: None,
167                    public_flags: None,
168                    system: None,
169                    verified: None,
170                },
171            }),
172            mute: true,
173            self_deaf: false,
174            self_mute: true,
175            self_stream: false,
176            self_video: false,
177            session_id: "a".to_owned(),
178            suppress: true,
179            user_id: Id::new(3),
180            request_to_speak_timestamp: Some(request_to_speak_timestamp),
181        };
182
183        serde_test::assert_tokens(
184            &value,
185            &[
186                Token::Struct {
187                    name: "VoiceState",
188                    len: 13,
189                },
190                Token::Str("channel_id"),
191                Token::Some,
192                Token::NewtypeStruct { name: "Id" },
193                Token::Str("1"),
194                Token::Str("deaf"),
195                Token::Bool(false),
196                Token::Str("guild_id"),
197                Token::Some,
198                Token::NewtypeStruct { name: "Id" },
199                Token::Str("2"),
200                Token::Str("member"),
201                Token::Some,
202                Token::Struct {
203                    name: "Member",
204                    len: 10,
205                },
206                Token::Str("communication_disabled_until"),
207                Token::None,
208                Token::Str("deaf"),
209                Token::Bool(false),
210                Token::Str("flags"),
211                Token::U64(flags.bits()),
212                Token::Str("joined_at"),
213                Token::Some,
214                Token::Str("2015-04-26T06:26:56.936000+00:00"),
215                Token::Str("mute"),
216                Token::Bool(true),
217                Token::Str("nick"),
218                Token::Some,
219                Token::Str("twilight"),
220                Token::Str("pending"),
221                Token::Bool(false),
222                Token::Str("premium_since"),
223                Token::Some,
224                Token::Str("2021-03-16T14:29:19.046000+00:00"),
225                Token::Str("roles"),
226                Token::Seq { len: Some(0) },
227                Token::SeqEnd,
228                Token::Str("user"),
229                Token::Struct {
230                    name: "User",
231                    len: 10,
232                },
233                Token::Str("accent_color"),
234                Token::None,
235                Token::Str("avatar"),
236                Token::None,
237                Token::Str("avatar_decoration"),
238                Token::None,
239                Token::Str("avatar_decoration_data"),
240                Token::None,
241                Token::Str("banner"),
242                Token::None,
243                Token::Str("bot"),
244                Token::Bool(false),
245                Token::Str("discriminator"),
246                Token::Str("0001"),
247                Token::Str("global_name"),
248                Token::Some,
249                Token::Str("test"),
250                Token::Str("id"),
251                Token::NewtypeStruct { name: "Id" },
252                Token::Str("3"),
253                Token::Str("username"),
254                Token::Str("twilight"),
255                Token::StructEnd,
256                Token::StructEnd,
257                Token::Str("mute"),
258                Token::Bool(true),
259                Token::Str("self_deaf"),
260                Token::Bool(false),
261                Token::Str("self_mute"),
262                Token::Bool(true),
263                Token::Str("self_stream"),
264                Token::Bool(false),
265                Token::Str("self_video"),
266                Token::Bool(false),
267                Token::Str("session_id"),
268                Token::Str("a"),
269                Token::Str("suppress"),
270                Token::Bool(true),
271                Token::Str("user_id"),
272                Token::NewtypeStruct { name: "Id" },
273                Token::Str("3"),
274                Token::Str("request_to_speak_timestamp"),
275                Token::Some,
276                Token::Str("2021-04-21T22:16:50.000000+00:00"),
277                Token::StructEnd,
278            ],
279        );
280
281        Ok(())
282    }
283}