use grammers_mtsender::InvocationError;
use grammers_session::types::{PeerKind, PeerRef, UpdateState};
use grammers_tl_types as tl;
use super::{Client, IterBuffer};
use crate::peer::Dialog;
const MAX_LIMIT: usize = 100;
pub type DialogIter = IterBuffer<tl::functions::messages::GetDialogs, Dialog>;
impl DialogIter {
fn new(client: &Client) -> Self {
Self::from_request(
client,
MAX_LIMIT,
tl::functions::messages::GetDialogs {
exclude_pinned: false,
folder_id: None,
offset_date: 0,
offset_id: 0,
offset_peer: tl::enums::InputPeer::Empty,
limit: 0,
hash: 0,
},
)
}
pub async fn total(&mut self) -> Result<usize, InvocationError> {
if let Some(total) = self.total {
return Ok(total);
}
use tl::enums::messages::Dialogs;
self.request.limit = 1;
let total = match self.client.invoke(&self.request).await? {
Dialogs::Dialogs(dialogs) => dialogs.dialogs.len(),
Dialogs::Slice(dialogs) => dialogs.count as usize,
Dialogs::NotModified(dialogs) => dialogs.count as usize,
};
self.total = Some(total);
Ok(total)
}
pub async fn next(&mut self) -> Result<Option<Dialog>, InvocationError> {
if let Some(result) = self.next_raw() {
return result;
}
use tl::enums::messages::Dialogs;
self.request.limit = self.determine_limit(MAX_LIMIT);
let (dialogs, mut messages, users, chats) = match self.client.invoke(&self.request).await? {
Dialogs::Dialogs(d) => {
self.last_chunk = true;
self.total = Some(d.dialogs.len());
(d.dialogs, d.messages, d.users, d.chats)
}
Dialogs::Slice(d) => {
self.last_chunk = d.dialogs.len() < self.request.limit as usize;
self.total = Some(d.count as usize);
(d.dialogs, d.messages, d.users, d.chats)
}
Dialogs::NotModified(_) => {
panic!("API returned Dialogs::NotModified even though hash = 0")
}
};
let peers = self.client.build_peer_map(users, chats).await;
for dialog in dialogs.iter() {
if let tl::enums::Dialog::Dialog(tl::types::Dialog {
peer: tl::enums::Peer::Channel(channel),
pts: Some(pts),
..
}) = &dialog
{
self.client
.0
.session
.set_update_state(UpdateState::Channel {
id: channel.channel_id,
pts: *pts,
})
.await;
}
}
self.buffer.extend(
dialogs
.into_iter()
.map(|dialog| Dialog::new(&self.client, dialog, &mut messages, peers.handle())),
);
if !self.last_chunk && !self.buffer.is_empty() {
self.request.exclude_pinned = true;
if let Some(last_message) = self
.buffer
.iter()
.rev()
.find_map(|dialog| dialog.last_message.as_ref())
{
self.request.offset_date = last_message.date_timestamp();
self.request.offset_id = last_message.id();
}
self.request.offset_peer = self.buffer[self.buffer.len() - 1].peer_ref().into();
}
Ok(self.pop_item())
}
}
impl Client {
pub fn iter_dialogs(&self) -> DialogIter {
DialogIter::new(self)
}
pub async fn delete_dialog<C: Into<PeerRef>>(&self, peer: C) -> Result<(), InvocationError> {
let peer = peer.into();
if peer.id.kind() == PeerKind::Channel {
self.invoke(&tl::functions::channels::LeaveChannel {
channel: peer.into(),
})
.await
.map(drop)
} else if peer.id.kind() == PeerKind::Chat {
self.invoke(&tl::functions::messages::DeleteChatUser {
chat_id: peer.into(),
user_id: tl::enums::InputUser::UserSelf,
revoke_history: false,
})
.await
.map(drop)
} else {
self.invoke(&tl::functions::messages::DeleteHistory {
just_clear: false,
revoke: false,
peer: peer.into(),
max_id: 0,
min_date: None,
max_date: None,
})
.await
.map(drop)
}
}
pub async fn mark_as_read<C: Into<PeerRef>>(&self, peer: C) -> Result<(), InvocationError> {
let peer = peer.into();
if peer.id.kind() == PeerKind::Channel {
self.invoke(&tl::functions::channels::ReadHistory {
channel: peer.into(),
max_id: 0,
})
.await
.map(drop)
} else {
self.invoke(&tl::functions::messages::ReadHistory {
peer: peer.into(),
max_id: 0,
})
.await
.map(drop)
}
}
pub async fn clear_mentions<C: Into<PeerRef>>(&self, peer: C) -> Result<(), InvocationError> {
self.invoke(&tl::functions::messages::ReadMentions {
peer: peer.into().into(),
top_msg_id: None,
})
.await
.map(drop)
}
}