use std::fmt;
use grammers_session::types::{ChannelKind, PeerAuth, PeerId, PeerInfo, PeerRef};
use grammers_tl_types as tl;
use crate::Client;
#[derive(Clone)]
pub struct Channel {
pub raw: tl::types::Channel,
pub(crate) client: Client,
}
impl fmt::Debug for Channel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.raw.fmt(f)
}
}
impl Channel {
pub fn from_raw(client: &Client, chat: tl::enums::Chat) -> Self {
use tl::enums::Chat as C;
match chat {
C::Empty(_) | C::Chat(_) | C::Forbidden(_) => panic!("cannot create from group chat"),
C::Channel(channel) => {
if channel.broadcast {
Self {
raw: channel,
client: client.clone(),
}
} else {
panic!("tried to create broadcast channel from megagroup");
}
}
C::ChannelForbidden(channel) => {
if channel.broadcast {
Self {
raw: tl::types::Channel {
creator: false,
left: false,
broadcast: channel.broadcast,
verified: false,
megagroup: channel.megagroup,
restricted: false,
signatures: false,
min: false,
scam: false,
has_link: false,
has_geo: false,
slowmode_enabled: false,
call_active: false,
call_not_empty: false,
fake: false,
gigagroup: false,
noforwards: false,
join_request: false,
forum: false,
stories_hidden: false,
stories_hidden_min: false,
stories_unavailable: true,
signature_profiles: false,
autotranslation: false,
broadcast_messages_allowed: false,
monoforum: false,
join_to_send: false,
id: channel.id,
access_hash: Some(channel.access_hash),
title: channel.title,
username: None,
photo: tl::enums::ChatPhoto::Empty,
date: 0,
restriction_reason: None,
admin_rights: None,
banned_rights: None,
default_banned_rights: None,
participants_count: None,
usernames: None,
stories_max_id: None,
color: None,
profile_color: None,
emoji_status: None,
level: None,
subscription_until_date: None,
bot_verification_icon: None,
send_paid_messages_stars: None,
forum_tabs: false,
linked_monoforum_id: None,
},
client: client.clone(),
}
} else {
panic!("tried to create broadcast channel from megagroup");
}
}
}
}
pub fn id(&self) -> PeerId {
PeerId::channel_unchecked(self.raw.id)
}
pub(crate) fn auth(&self) -> Option<PeerAuth> {
self.raw
.access_hash
.filter(|_| !self.raw.min)
.map(PeerAuth::from_hash)
}
pub async fn to_ref(&self) -> Option<PeerRef> {
let id = self.id();
match self.auth() {
Some(auth) => Some(PeerRef { id, auth }),
None => self.client.0.session.peer_ref(id).await,
}
}
#[inline]
pub fn kind(&self) -> Option<ChannelKind> {
match <ChannelKind as TryFrom<&Channel>>::try_from(self) {
Ok(channel_kind) => Some(channel_kind),
Err(()) => None,
}
}
pub fn title(&self) -> &str {
self.raw.title.as_str()
}
pub fn username(&self) -> Option<&str> {
self.raw.username.as_deref()
}
pub fn usernames(&self) -> Vec<&str> {
self.raw
.usernames
.as_deref()
.map_or(Vec::new(), |usernames| {
usernames
.iter()
.map(|username| match username {
tl::enums::Username::Username(username) => username.username.as_ref(),
})
.collect()
})
}
pub fn photo(&self) -> Option<&tl::types::ChatPhoto> {
match &self.raw.photo {
tl::enums::ChatPhoto::Empty => None,
tl::enums::ChatPhoto::Photo(photo) => Some(photo),
}
}
pub fn admin_rights(&self) -> Option<&tl::types::ChatAdminRights> {
match &self.raw.admin_rights {
Some(tl::enums::ChatAdminRights::Rights(rights)) => Some(rights),
None if self.raw.creator => Some(&tl::types::ChatAdminRights {
add_admins: true,
other: true,
change_info: true,
post_messages: true,
anonymous: false,
ban_users: true,
delete_messages: true,
edit_messages: true,
invite_users: true,
manage_call: true,
pin_messages: true,
manage_topics: true,
post_stories: true,
edit_stories: true,
delete_stories: true,
manage_direct_messages: true,
}),
None => None,
}
}
pub fn requires_join_request(&self) -> bool {
self.raw.join_request
}
}
impl TryFrom<Channel> for ChannelKind {
type Error = <Self as TryFrom<&'static Channel>>::Error;
#[inline]
fn try_from(channel: Channel) -> Result<Self, Self::Error> {
<Self as TryFrom<&Channel>>::try_from(&channel)
}
}
impl<'a> TryFrom<&'a Channel> for ChannelKind {
type Error = <Self as TryFrom<&'a tl::types::Channel>>::Error;
#[inline]
fn try_from(channel: &'a Channel) -> Result<Self, Self::Error> {
<Self as TryFrom<&'a tl::types::Channel>>::try_from(&channel.raw)
}
}
impl From<Channel> for PeerInfo {
#[inline]
fn from(channel: Channel) -> Self {
<Self as From<&Channel>>::from(&channel)
}
}
impl<'a> From<&'a Channel> for PeerInfo {
fn from(channel: &'a Channel) -> Self {
<Self as From<&'a tl::types::Channel>>::from(&channel.raw)
}
}