#![allow(unused_parens)]
use crate::api::types::*;
bot_api_method! {
method = "chats/getInfo",
request = RequestChatsGetInfo {
required {
chat_id: ChatId,
},
optional {}
},
response = ResponseChatsGetInfo {
#[serde(flatten)]
types: EnumChatsGetInfo
},
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum EnumChatsGetInfo {
Private(ResponseChatsPrivateGetInfo),
Group(ResponseChatsGroupGetInfo),
Channel(ResponseChatsChannelGetInfo),
#[default]
None,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct ResponseChatsPrivateGetInfo {
pub first_name: Option<String>,
pub last_name: Option<String>,
pub nick: Option<String>,
pub about: Option<String>,
pub is_bot: Option<bool>,
pub language: Option<Languages>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct ResponseChatsGroupGetInfo {
pub title: Option<String>,
pub about: Option<String>,
pub rules: Option<String>,
pub invite_link: Option<String>,
pub public: Option<bool>,
pub join_moderation: Option<bool>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct ResponseChatsChannelGetInfo {
pub title: Option<String>,
pub about: Option<String>,
pub rules: Option<String>,
pub invite_link: Option<String>,
pub public: Option<bool>,
pub join_moderation: Option<bool>,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_enum_chats_get_info_deserialize_private() {
let val = json!({
"type": "private",
"firstName": "Ivan",
"lastName": "Ivanov",
"nick": "ivan123",
"about": "about",
"isBot": true,
"language": "ru"
});
let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
match info {
EnumChatsGetInfo::Private(p) => {
assert_eq!(p.first_name.as_deref(), Some("Ivan"));
assert_eq!(p.is_bot, Some(true));
}
_ => panic!("Expected Private variant"),
}
}
#[test]
fn test_enum_chats_get_info_deserialize_group() {
let val = json!({
"type": "group",
"title": "Group chat",
"about": "desc",
"rules": "rules",
"inviteLink": "link",
"public": true,
"joinModeration": false
});
let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
match info {
EnumChatsGetInfo::Group(g) => {
assert_eq!(g.title.as_deref(), Some("Group chat"));
assert_eq!(g.public, Some(true));
}
_ => panic!("Expected Group variant"),
}
}
#[test]
fn test_enum_chats_get_info_deserialize_channel() {
let val = json!({
"type": "channel",
"title": "Channel chat"
});
let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
match info {
EnumChatsGetInfo::Channel(c) => {
assert_eq!(c.title.as_deref(), Some("Channel chat"));
}
_ => panic!("Expected Channel variant"),
}
}
#[test]
fn test_enum_chats_get_info_deserialize_none() {
let val = json!({});
let info: Result<EnumChatsGetInfo, _> = serde_json::from_value(val);
assert!(info.is_err(), "Ожидалась ошибка при отсутствии поля 'type'");
}
#[test]
fn test_private_missing_fields() {
let val = json!({"type": "private"});
let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
match info {
EnumChatsGetInfo::Private(p) => {
assert!(p.first_name.is_none());
assert!(p.is_bot.is_none());
}
_ => panic!("Expected Private variant"),
}
}
#[test]
fn test_group_invalid_type() {
let val = json!({"type": "group", "public": "not_bool"});
let res: Result<EnumChatsGetInfo, _> = serde_json::from_value(val);
assert!(res.is_err());
}
#[test]
fn test_channel_empty() {
let val = json!({"type": "channel"});
let info: EnumChatsGetInfo = serde_json::from_value(val).unwrap();
match info {
EnumChatsGetInfo::Channel(c) => {
assert!(c.title.is_none());
}
_ => panic!("Expected Channel variant"),
}
}
#[test]
fn test_serialize_deserialize_roundtrip() {
let group = ResponseChatsGroupGetInfo {
title: Some("t".to_string()),
about: None,
rules: None,
invite_link: None,
public: Some(false),
join_moderation: None,
};
let enum_val = EnumChatsGetInfo::Group(group);
let ser = serde_json::to_string(&enum_val).unwrap();
let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
match de {
EnumChatsGetInfo::Group(g) => {
assert_eq!(g.title.as_deref(), Some("t"));
assert_eq!(g.public, Some(false));
}
_ => panic!("Expected Group variant"),
}
}
}
#[cfg(test)]
mod prop_tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_roundtrip_group(
title in proptest::option::of("[a-zA-Z0-9 ]{0,32}"),
about in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
rules in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
invite_link in proptest::option::of("[a-zA-Z0-9:/._-]{0,64}"),
public in proptest::option::of(any::<bool>()),
join_moderation in proptest::option::of(any::<bool>())
) {
let group = ResponseChatsGroupGetInfo {
title: title.clone(),
about: about.clone(),
rules: rules.clone(),
invite_link: invite_link.clone(),
public,
join_moderation,
};
let enum_val = EnumChatsGetInfo::Group(group);
let ser = serde_json::to_string(&enum_val).unwrap();
let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
match de {
EnumChatsGetInfo::Group(g) => {
assert_eq!(g.title, title);
assert_eq!(g.about, about);
assert_eq!(g.rules, rules);
assert_eq!(g.invite_link, invite_link);
assert_eq!(g.public, public);
assert_eq!(g.join_moderation, join_moderation);
}
_ => panic!("Expected Group variant"),
}
}
#[test]
fn prop_roundtrip_channel(
title in proptest::option::of("[a-zA-Z0-9 ]{0,32}"),
about in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
rules in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
invite_link in proptest::option::of("[a-zA-Z0-9:/._-]{0,64}"),
public in proptest::option::of(any::<bool>()),
join_moderation in proptest::option::of(any::<bool>())
) {
let channel = ResponseChatsChannelGetInfo {
title: title.clone(),
about: about.clone(),
rules: rules.clone(),
invite_link: invite_link.clone(),
public,
join_moderation,
};
let enum_val = EnumChatsGetInfo::Channel(channel);
let ser = serde_json::to_string(&enum_val).unwrap();
let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
match de {
EnumChatsGetInfo::Channel(c) => {
assert_eq!(c.title, title);
assert_eq!(c.about, about);
assert_eq!(c.rules, rules);
assert_eq!(c.invite_link, invite_link);
assert_eq!(c.public, public);
assert_eq!(c.join_moderation, join_moderation);
}
_ => panic!("Expected Channel variant"),
}
}
#[test]
fn prop_roundtrip_private(
first_name in proptest::option::of("[a-zA-Z]{0,32}"),
last_name in proptest::option::of("[a-zA-Z]{0,32}"),
nick in proptest::option::of("[a-zA-Z0-9_]{0,32}"),
about in proptest::option::of("[a-zA-Z0-9 ]{0,64}"),
is_bot in proptest::option::of(any::<bool>()),
language in proptest::option::of(prop_oneof![Just(Languages::Ru)]).prop_map(|opt| opt)
) {
let private = ResponseChatsPrivateGetInfo {
first_name: first_name.clone(),
last_name: last_name.clone(),
nick: nick.clone(),
about: about.clone(),
is_bot,
language: language.clone(),
};
let enum_val = EnumChatsGetInfo::Private(private);
let ser = serde_json::to_string(&enum_val).unwrap();
let de: EnumChatsGetInfo = serde_json::from_str(&ser).unwrap();
match de {
EnumChatsGetInfo::Private(p) => {
assert_eq!(p.first_name, first_name);
assert_eq!(p.last_name, last_name);
assert_eq!(p.nick, nick);
assert_eq!(p.about, about);
assert_eq!(p.is_bot, is_bot);
assert_eq!(p.language, language);
}
_ => panic!("Expected Private variant"),
}
}
}
}