1#![allow(unused_parens)]
2use 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#[derive(Serialize, Deserialize, Debug, Default, Clone)]
25#[serde(tag = "type", rename_all = "camelCase")]
26pub enum EnumChatsGetInfo {
27 Private(ResponseChatsPrivateGetInfo),
29 Group(ResponseChatsGroupGetInfo),
31 Channel(ResponseChatsChannelGetInfo),
33 #[default]
34 None,
35}
36#[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#[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#[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}