use serde::{Deserialize, Serialize};
use crate::types::UserId;
#[derive(
Clone,
Copy,
Debug,
derive_more::Display,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Serialize,
Deserialize,
)]
#[serde(transparent)]
pub struct ChatId(pub i64);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) enum BareChatId {
User(UserId),
Group(u64),
Channel(u64),
}
impl ChatId {
#[must_use]
pub fn is_user(self) -> bool {
matches!(self.to_bare(), BareChatId::User(_))
}
#[must_use]
pub fn is_group(self) -> bool {
matches!(self.to_bare(), BareChatId::Group(_))
}
#[must_use]
pub fn is_channel_or_supergroup(self) -> bool {
matches!(self.to_bare(), BareChatId::Channel(_))
}
pub(crate) fn to_bare(self) -> BareChatId {
use BareChatId::*;
match self.0 {
id @ MIN_MARKED_CHAT_ID..=MAX_MARKED_CHAT_ID => Group(-id as _),
id @ MIN_MARKED_CHANNEL_ID..=MAX_MARKED_CHANNEL_ID => {
Channel((MAX_MARKED_CHANNEL_ID - id) as _)
}
id @ MIN_USER_ID..=MAX_USER_ID => User(UserId(id as _)),
id => panic!("malformed chat id: {id}"),
}
}
}
impl From<UserId> for ChatId {
fn from(UserId(id): UserId) -> Self {
Self(id as _)
}
}
impl BareChatId {
#[allow(unused)]
pub(crate) fn to_bot_api(self) -> ChatId {
use BareChatId::*;
match self {
User(UserId(id)) => ChatId(id as _),
Group(id) => ChatId(-(id as i64)),
Channel(id) => ChatId(MAX_MARKED_CHANNEL_ID - (id as i64)),
}
}
}
const MIN_MARKED_CHANNEL_ID: i64 = -1997852516352;
const MAX_MARKED_CHANNEL_ID: i64 = -1000000000000;
const MIN_MARKED_CHAT_ID: i64 = MAX_MARKED_CHANNEL_ID + 1;
const MAX_MARKED_CHAT_ID: i64 = MIN_USER_ID - 1;
const MIN_USER_ID: i64 = 0;
const MAX_USER_ID: i64 = (1 << 40) - 1;
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
use crate::types::{BareChatId, ChatId, UserId};
#[test]
fn deser() {
let chat_id = S {
chat_id: ChatId(0xAA),
};
let json = r#"{"chat_id":170}"#;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
struct S {
chat_id: ChatId,
}
assert_eq!(serde_json::to_string(&chat_id).unwrap(), json);
assert_eq!(chat_id, serde_json::from_str(json).unwrap());
}
#[test]
fn chonky_user_id_to_bare() {
assert!(matches!(
ChatId(5298363099).to_bare(),
BareChatId::User(UserId(5298363099))
));
}
#[test]
fn to_bare_to_bot_api_identity() {
fn assert_identity(x: u64) {
use BareChatId::*;
assert_eq!(User(UserId(x)), User(UserId(x)).to_bot_api().to_bare());
assert_eq!(Group(x), Group(x).to_bot_api().to_bare());
assert_eq!(Channel(x), Channel(x).to_bot_api().to_bare());
}
let ids = [
1,
4,
17,
34,
51,
777000,
1000000,
617136926,
1666111087,
1 << 20,
(1 << 35) | 123456,
];
ids.iter().copied().for_each(assert_identity);
}
#[test]
fn display() {
assert_eq!(ChatId(1).to_string(), "1");
}
}