vkteams_bot/api/chats/
get_info.rs

1#![allow(unused_parens)]
2//! Get information about a chat method `chats/getInfo`
3//! [More info](https://teams.vk.com/botapi/#/chats/get_chats_getInfo)
4use crate::api::types::*;
5bot_api_method! {
6    method   = "chats/getInfo",
7    request  = RequestChatsGetInfo {
8        required {
9            chat_id: ChatId,
10        },
11        optional {}
12    },
13    response = ResponseChatsGetInfo {
14        #[serde(flatten)]
15        types: EnumChatsGetInfo
16    },
17}
18
19/// # Chats get info response method `chats/getInfo`
20/// Response can be one of the following types:
21/// - `private`: [`ResponseChatsPrivateGetInfo`]
22/// - `group`: [`ResponseChatsGroupGetInfo`]
23/// - `channel`: [`ResponseChatsChannelGetInfo`]
24#[derive(Serialize, Deserialize, Debug, Default, Clone)]
25#[serde(tag = "type", rename_all = "camelCase")]
26pub enum EnumChatsGetInfo {
27    /// Private chat
28    Private(ResponseChatsPrivateGetInfo),
29    /// Group chat
30    Group(ResponseChatsGroupGetInfo),
31    /// Channel chat
32    Channel(ResponseChatsChannelGetInfo),
33    #[default]
34    None,
35}
36/// # Chats get info response method `chats/getInfo` for private chat
37#[derive(Serialize, Deserialize, Clone, Debug, Default)]
38#[serde(rename_all = "camelCase")]
39pub struct ResponseChatsPrivateGetInfo {
40    pub first_name: Option<String>,
41    pub last_name: Option<String>,
42    pub nick: Option<String>,
43    pub about: Option<String>,
44    pub is_bot: Option<bool>,
45    pub language: Option<Languages>,
46}
47/// # Chats get info response method `chats/getInfo` for group chat
48#[derive(Serialize, Deserialize, Clone, Debug, Default)]
49#[serde(rename_all = "camelCase")]
50pub struct ResponseChatsGroupGetInfo {
51    pub title: Option<String>,
52    pub about: Option<String>,
53    pub rules: Option<String>,
54    pub invite_link: Option<String>,
55    pub public: Option<bool>,
56    pub join_moderation: Option<bool>,
57}
58/// # Chats get info response method `chats/getInfo` for channel chat
59#[derive(Serialize, Deserialize, Clone, Debug, Default)]
60#[serde(rename_all = "camelCase")]
61pub struct ResponseChatsChannelGetInfo {
62    pub title: Option<String>,
63    pub about: Option<String>,
64    pub rules: Option<String>,
65    pub invite_link: Option<String>,
66    pub public: Option<bool>,
67    pub join_moderation: Option<bool>,
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use serde_json::json;
74
75    #[test]
76    fn test_enum_chats_get_info_deserialize_private() {
77        let val = json!({
78            "type": "private",
79            "firstName": "Ivan",
80            "lastName": "Ivanov",
81            "nick": "ivan123",
82            "about": "about",
83            "isBot": true,
84            "language": "ru"
85        });
86        let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
87        match info {
88            EnumChatsGetInfo::Private(p) => {
89                assert_eq!(p.first_name.as_deref(), Some("Ivan"));
90                assert_eq!(p.is_bot, Some(true));
91            }
92            _ => panic!("Expected Private variant"),
93        }
94    }
95
96    #[test]
97    fn test_enum_chats_get_info_deserialize_group() {
98        let val = json!({
99            "type": "group",
100            "title": "Group chat",
101            "about": "desc",
102            "rules": "rules",
103            "inviteLink": "link",
104            "public": true,
105            "joinModeration": false
106        });
107        let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
108        match info {
109            EnumChatsGetInfo::Group(g) => {
110                assert_eq!(g.title.as_deref(), Some("Group chat"));
111                assert_eq!(g.public, Some(true));
112            }
113            _ => panic!("Expected Group variant"),
114        }
115    }
116
117    #[test]
118    fn test_enum_chats_get_info_deserialize_channel() {
119        let val = json!({
120            "type": "channel",
121            "title": "Channel chat"
122        });
123        let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
124        match info {
125            EnumChatsGetInfo::Channel(c) => {
126                assert_eq!(c.title.as_deref(), Some("Channel chat"));
127            }
128            _ => panic!("Expected Channel variant"),
129        }
130    }
131
132    #[test]
133    fn test_enum_chats_get_info_deserialize_none() {
134        let val = json!({});
135        let info: Result<EnumChatsGetInfo, _> = serde_json::from_value(val);
136        assert!(info.is_err(), "Ожидалась ошибка при отсутствии поля 'type'");
137    }
138
139    #[test]
140    fn test_private_missing_fields() {
141        let val = json!({"type": "private"});
142        let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
143        match info {
144            EnumChatsGetInfo::Private(p) => {
145                assert!(p.first_name.is_none());
146                assert!(p.is_bot.is_none());
147            }
148            _ => panic!("Expected Private variant"),
149        }
150    }
151
152    #[test]
153    fn test_group_invalid_type() {
154        let val = json!({"type": "group", "public": "not_bool"});
155        let res: Result<EnumChatsGetInfo, _> = serde_json::from_value(val);
156        assert!(res.is_err());
157    }
158
159    #[test]
160    fn test_channel_empty() {
161        let val = json!({"type": "channel"});
162        let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
163        match info {
164            EnumChatsGetInfo::Channel(c) => {
165                assert!(c.title.is_none());
166            }
167            _ => panic!("Expected Channel variant"),
168        }
169    }
170
171    #[test]
172    fn test_serialize_deserialize_roundtrip() {
173        let group = ResponseChatsGroupGetInfo {
174            title: Some("t".to_string()),
175            about: None,
176            rules: None,
177            invite_link: None,
178            public: Some(false),
179            join_moderation: None,
180        };
181        let enum_val = EnumChatsGetInfo::Group(group);
182        let ser = serde_json::to_string(&enum_val).unwrap();
183        let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
184        match de {
185            EnumChatsGetInfo::Group(g) => {
186                assert_eq!(g.title.as_deref(), Some("t"));
187                assert_eq!(g.public, Some(false));
188            }
189            _ => panic!("Expected Group variant"),
190        }
191    }
192}
193
194#[cfg(test)]
195mod prop_tests {
196    use super::*;
197    use proptest::prelude::*;
198
199    proptest! {
200        #[test]
201        fn prop_roundtrip_group(
202            title in proptest::option::of("[a-zA-Z0-9 ]{0,32}"),
203            about in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
204            rules in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
205            invite_link in proptest::option::of("[a-zA-Z0-9:/._-]{0,64}"),
206            public in proptest::option::of(any::<bool>()),
207            join_moderation in proptest::option::of(any::<bool>())
208        ) {
209            let group = ResponseChatsGroupGetInfo {
210                title: title.clone(),
211                about: about.clone(),
212                rules: rules.clone(),
213                invite_link: invite_link.clone(),
214                public,
215                join_moderation,
216            };
217            let enum_val = EnumChatsGetInfo::Group(group);
218            let ser = serde_json::to_string(&enum_val).unwrap();
219            let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
220            match de {
221                EnumChatsGetInfo::Group(g) => {
222                    assert_eq!(g.title, title);
223                    assert_eq!(g.about, about);
224                    assert_eq!(g.rules, rules);
225                    assert_eq!(g.invite_link, invite_link);
226                    assert_eq!(g.public, public);
227                    assert_eq!(g.join_moderation, join_moderation);
228                }
229                _ => panic!("Expected Group variant"),
230            }
231        }
232
233        #[test]
234        fn prop_roundtrip_channel(
235            title in proptest::option::of("[a-zA-Z0-9 ]{0,32}"),
236            about in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
237            rules in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
238            invite_link in proptest::option::of("[a-zA-Z0-9:/._-]{0,64}"),
239            public in proptest::option::of(any::<bool>()),
240            join_moderation in proptest::option::of(any::<bool>())
241        ) {
242            let channel = ResponseChatsChannelGetInfo {
243                title: title.clone(),
244                about: about.clone(),
245                rules: rules.clone(),
246                invite_link: invite_link.clone(),
247                public,
248                join_moderation,
249            };
250            let enum_val = EnumChatsGetInfo::Channel(channel);
251            let ser = serde_json::to_string(&enum_val).unwrap();
252            let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
253            match de {
254                EnumChatsGetInfo::Channel(c) => {
255                    assert_eq!(c.title, title);
256                    assert_eq!(c.about, about);
257                    assert_eq!(c.rules, rules);
258                    assert_eq!(c.invite_link, invite_link);
259                    assert_eq!(c.public, public);
260                    assert_eq!(c.join_moderation, join_moderation);
261                }
262                _ => panic!("Expected Channel variant"),
263            }
264        }
265
266        #[test]
267        fn prop_roundtrip_private(
268            first_name in proptest::option::of("[a-zA-Z]{0,32}"),
269            last_name in proptest::option::of("[a-zA-Z]{0,32}"),
270            nick in proptest::option::of("[a-zA-Z0-9_]{0,32}"),
271            about in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
272            is_bot in proptest::option::of(any::<bool>()),
273            language in proptest::option::of(prop_oneof![Just(Languages::Ru)]).prop_map(|opt| opt)
274        ) {
275            let private = ResponseChatsPrivateGetInfo {
276                first_name: first_name.clone(),
277                last_name: last_name.clone(),
278                nick: nick.clone(),
279                about: about.clone(),
280                is_bot,
281                language: language.clone(),
282            };
283            let enum_val = EnumChatsGetInfo::Private(private);
284            let ser = serde_json::to_string(&enum_val).unwrap();
285            let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
286            match de {
287                EnumChatsGetInfo::Private(p) => {
288                    assert_eq!(p.first_name, first_name);
289                    assert_eq!(p.last_name, last_name);
290                    assert_eq!(p.nick, nick);
291                    assert_eq!(p.about, about);
292                    assert_eq!(p.is_bot, is_bot);
293                    assert_eq!(p.language, language);
294                }
295                _ => panic!("Expected Private variant"),
296            }
297        }
298    }
299}