twilight_model/guild/widget/
mod.rs

1mod settings;
2
3pub use self::settings::GuildWidgetSettings;
4
5use crate::{
6    gateway::presence::Status,
7    id::{
8        marker::{ChannelMarker, GuildMarker, UserMarker},
9        AnonymizableId, Id,
10    },
11    user::{discriminator, DiscriminatorDisplay},
12    util::ImageHash,
13};
14use serde::{Deserialize, Serialize};
15
16#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
17pub struct GuildWidget {
18    pub channels: Vec<GuildWidgetChannel>,
19    pub id: Id<GuildMarker>,
20    pub instant_invite: Option<String>,
21    pub members: Vec<GuildWidgetMember>,
22    pub name: String,
23    pub presence_count: u64,
24}
25
26#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
27pub struct GuildWidgetChannel {
28    pub id: Id<ChannelMarker>,
29    pub name: String,
30    pub position: i64,
31}
32
33#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
34pub struct GuildWidgetMember {
35    pub avatar: Option<ImageHash>,
36    pub avatar_url: Option<String>,
37    #[serde(with = "discriminator")]
38    pub discriminator: u16,
39    /// Member's ID.
40    pub id: AnonymizableId<UserMarker>,
41    #[serde(rename = "username")]
42    pub name: String,
43    pub status: Status,
44}
45
46impl GuildWidgetMember {
47    /// Create a [`Display`] formatter for a user discriminator.
48    ///
49    /// [`Display`]: core::fmt::Display
50    pub const fn discriminator(&self) -> DiscriminatorDisplay {
51        DiscriminatorDisplay::new(self.discriminator)
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::{GuildWidget, GuildWidgetChannel, GuildWidgetMember, Id, Status};
58    use crate::id::AnonymizableId;
59    use serde::{Deserialize, Serialize};
60    use serde_test::Token;
61    use static_assertions::{assert_fields, assert_impl_all};
62    use std::{fmt::Debug, hash::Hash};
63
64    assert_fields!(
65        GuildWidget: channels,
66        id,
67        instant_invite,
68        members,
69        name,
70        presence_count
71    );
72    assert_fields!(GuildWidgetChannel: id, name, position);
73    assert_fields!(
74        GuildWidgetMember: avatar,
75        avatar_url,
76        discriminator,
77        id,
78        name,
79        status
80    );
81    assert_impl_all!(
82        GuildWidget: Clone,
83        Debug,
84        Deserialize<'static>,
85        Eq,
86        Hash,
87        PartialEq,
88        Serialize,
89        Send,
90        Sync
91    );
92    assert_impl_all!(
93        GuildWidgetChannel: Clone,
94        Debug,
95        Deserialize<'static>,
96        Eq,
97        Hash,
98        PartialEq,
99        Serialize,
100        Send,
101        Sync
102    );
103    assert_impl_all!(
104        GuildWidgetMember: Clone,
105        Debug,
106        Deserialize<'static>,
107        Eq,
108        Hash,
109        PartialEq,
110        Serialize,
111        Send,
112        Sync
113    );
114
115    #[test]
116    fn guild_widget() {
117        let value = GuildWidget {
118            channels: Vec::from([GuildWidgetChannel {
119                id: Id::new(2),
120                name: "General".to_string(),
121                position: 1,
122            }]),
123            id: Id::new(1),
124            instant_invite: Some("https://discord.com/invite/P8PkgN2".to_string()),
125            members: Vec::from([GuildWidgetMember {
126                avatar: None,
127                avatar_url: Some("widget avatar link".to_string()),
128                discriminator: 1,
129                id: AnonymizableId::Anonymized,
130                name: "Foo".to_string(),
131                status: Status::Online,
132            }]),
133            name: "Twilight".to_string(),
134            presence_count: 15,
135        };
136
137        serde_test::assert_tokens(
138            &value,
139            &[
140                Token::Struct {
141                    name: "GuildWidget",
142                    len: 6,
143                },
144                Token::Str("channels"),
145                Token::Seq { len: Some(1) },
146                Token::Struct {
147                    name: "GuildWidgetChannel",
148                    len: 3,
149                },
150                Token::Str("id"),
151                Token::NewtypeStruct { name: "Id" },
152                Token::Str("2"),
153                Token::Str("name"),
154                Token::Str("General"),
155                Token::Str("position"),
156                Token::I64(1),
157                Token::StructEnd,
158                Token::SeqEnd,
159                Token::Str("id"),
160                Token::NewtypeStruct { name: "Id" },
161                Token::Str("1"),
162                Token::Str("instant_invite"),
163                Token::Some,
164                Token::Str("https://discord.com/invite/P8PkgN2"),
165                Token::Str("members"),
166                Token::Seq { len: Some(1) },
167                Token::Struct {
168                    name: "GuildWidgetMember",
169                    len: 6,
170                },
171                Token::Str("avatar"),
172                Token::None,
173                Token::Str("avatar_url"),
174                Token::Some,
175                Token::Str("widget avatar link"),
176                Token::Str("discriminator"),
177                Token::Str("0001"),
178                Token::Str("id"),
179                Token::NewtypeStruct {
180                    name: "AnonymizableId",
181                },
182                Token::Str("0"),
183                Token::Str("username"),
184                Token::Str("Foo"),
185                Token::Str("status"),
186                Token::UnitVariant {
187                    name: "Status",
188                    variant: "online",
189                },
190                Token::StructEnd,
191                Token::SeqEnd,
192                Token::Str("name"),
193                Token::Str("Twilight"),
194                Token::Str("presence_count"),
195                Token::U64(15),
196                Token::StructEnd,
197            ],
198        );
199    }
200}