1use layer_tl_types as tl;
6use layer_tl_types::{Cursor, Deserializable};
7
8use crate::{Client, InvocationError};
9
10#[derive(Debug, Clone)]
14pub struct Participant {
15 pub user: tl::types::User,
17 pub status: ParticipantStatus,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum ParticipantStatus {
24 Member,
26 Creator,
28 Admin,
30 Restricted,
32 Left,
34 Banned,
36}
37
38impl Client {
41 pub async fn get_participants(
48 &self,
49 peer: tl::enums::Peer,
50 limit: i32,
51 ) -> Result<Vec<Participant>, InvocationError> {
52 match &peer {
53 tl::enums::Peer::Channel(c) => {
54 let cache = self.inner.peer_cache.lock().await;
55 let access_hash = cache.channels.get(&c.channel_id).copied().unwrap_or(0);
56 drop(cache);
57 self.get_channel_participants(c.channel_id, access_hash, limit).await
58 }
59 tl::enums::Peer::Chat(c) => {
60 self.get_chat_participants(c.chat_id).await
61 }
62 _ => Err(InvocationError::Deserialize("get_participants: peer must be a chat or channel".into())),
63 }
64 }
65
66 async fn get_channel_participants(
67 &self,
68 channel_id: i64,
69 access_hash: i64,
70 limit: i32,
71 ) -> Result<Vec<Participant>, InvocationError> {
72 let limit = if limit <= 0 { 200 } else { limit };
73 let req = tl::functions::channels::GetParticipants {
74 channel: tl::enums::InputChannel::InputChannel(tl::types::InputChannel {
75 channel_id, access_hash,
76 }),
77 filter: tl::enums::ChannelParticipantsFilter::ChannelParticipantsRecent,
78 offset: 0,
79 limit,
80 hash: 0,
81 };
82 let body = self.rpc_call_raw_pub(&req).await?;
83 let mut cur = Cursor::from_slice(&body);
84 let raw = match tl::enums::channels::ChannelParticipants::deserialize(&mut cur)? {
85 tl::enums::channels::ChannelParticipants::ChannelParticipants(p) => p,
86 tl::enums::channels::ChannelParticipants::NotModified => return Ok(vec![]),
87 };
88
89 let user_map: std::collections::HashMap<i64, tl::types::User> = raw.users.into_iter()
91 .filter_map(|u| match u { tl::enums::User::User(u) => Some((u.id, u)), _ => None })
92 .collect();
93
94 {
96 let mut cache = self.inner.peer_cache.lock().await;
97 for u in user_map.values() {
98 if let Some(h) = u.access_hash { cache.users.insert(u.id, h); }
99 }
100 }
101
102 let mut result = Vec::new();
103 for p in raw.participants {
104 let (user_id, status) = match &p {
105 tl::enums::ChannelParticipant::ChannelParticipant(x) => (x.user_id, ParticipantStatus::Member),
106 tl::enums::ChannelParticipant::ParticipantSelf(x) => (x.user_id, ParticipantStatus::Member),
107 tl::enums::ChannelParticipant::Creator(x) => (x.user_id, ParticipantStatus::Creator),
108 tl::enums::ChannelParticipant::Admin(x) => (x.user_id, ParticipantStatus::Admin),
109 tl::enums::ChannelParticipant::Banned(x) => (x.peer.user_id_or(0), ParticipantStatus::Banned),
110 tl::enums::ChannelParticipant::Left(x) => (x.peer.user_id_or(0), ParticipantStatus::Left),
111 };
112 if let Some(user) = user_map.get(&user_id).cloned() {
113 result.push(Participant { user, status });
114 }
115 }
116 Ok(result)
117 }
118
119 async fn get_chat_participants(&self, chat_id: i64) -> Result<Vec<Participant>, InvocationError> {
120 let req = tl::functions::messages::GetFullChat { chat_id };
121 let body = self.rpc_call_raw_pub(&req).await?;
122 let mut cur = Cursor::from_slice(&body);
123 let tl::enums::messages::ChatFull::ChatFull(full) = tl::enums::messages::ChatFull::deserialize(&mut cur)?;
124
125 let user_map: std::collections::HashMap<i64, tl::types::User> = full.users.into_iter()
126 .filter_map(|u| match u { tl::enums::User::User(u) => Some((u.id, u)), _ => None })
127 .collect();
128
129 {
130 let mut cache = self.inner.peer_cache.lock().await;
131 for u in user_map.values() {
132 if let Some(h) = u.access_hash { cache.users.insert(u.id, h); }
133 }
134 }
135
136 let participants = match &full.full_chat {
137 tl::enums::ChatFull::ChatFull(cf) => match &cf.participants {
138 tl::enums::ChatParticipants::ChatParticipants(p) => p.participants.clone(),
139 tl::enums::ChatParticipants::Forbidden(_) => vec![],
140 },
141 tl::enums::ChatFull::ChannelFull(_) => {
142 return Err(InvocationError::Deserialize(
143 "get_chat_participants: peer is a channel, use get_participants with a Channel peer instead".into()
144 ));
145 }
146 };
147
148 let mut result = Vec::new();
149 for p in participants {
150 let (user_id, status) = match p {
151 tl::enums::ChatParticipant::ChatParticipant(x) => (x.user_id, ParticipantStatus::Member),
152 tl::enums::ChatParticipant::Creator(x) => (x.user_id, ParticipantStatus::Creator),
153 tl::enums::ChatParticipant::Admin(x) => (x.user_id, ParticipantStatus::Admin),
154 };
155 if let Some(user) = user_map.get(&user_id).cloned() {
156 result.push(Participant { user, status });
157 }
158 }
159 Ok(result)
160 }
161
162 pub async fn kick_participant(
164 &self,
165 chat_id: i64,
166 user_id: i64,
167 ) -> Result<(), InvocationError> {
168 let cache = self.inner.peer_cache.lock().await;
169 let access_hash = cache.users.get(&user_id).copied().unwrap_or(0);
170 drop(cache);
171 let req = tl::functions::messages::DeleteChatUser {
172 revoke_history: false,
173 chat_id,
174 user_id: tl::enums::InputUser::InputUser(tl::types::InputUser { user_id, access_hash }),
175 };
176 self.rpc_call_raw_pub(&req).await?;
177 Ok(())
178 }
179
180 pub async fn ban_participant(
184 &self,
185 channel: tl::enums::Peer,
186 user_id: i64,
187 until_date: i32,
188 ) -> Result<(), InvocationError> {
189 let (channel_id, ch_hash) = match &channel {
190 tl::enums::Peer::Channel(c) => {
191 let h = self.inner.peer_cache.lock().await.channels.get(&c.channel_id).copied().unwrap_or(0);
192 (c.channel_id, h)
193 }
194 _ => return Err(InvocationError::Deserialize("ban_participant: peer must be a channel".into())),
195 };
196 let user_hash = self.inner.peer_cache.lock().await.users.get(&user_id).copied().unwrap_or(0);
197
198 let req = tl::functions::channels::EditBanned {
199 channel: tl::enums::InputChannel::InputChannel(tl::types::InputChannel {
200 channel_id, access_hash: ch_hash,
201 }),
202 participant: tl::enums::InputPeer::User(tl::types::InputPeerUser {
203 user_id, access_hash: user_hash,
204 }),
205 banned_rights: tl::enums::ChatBannedRights::ChatBannedRights(tl::types::ChatBannedRights {
206 view_messages: true,
207 send_messages: true,
208 send_media: true,
209 send_stickers: true,
210 send_gifs: true,
211 send_games: true,
212 send_inline: true,
213 embed_links: true,
214 send_polls: true,
215 change_info: true,
216 invite_users: true,
217 pin_messages: true,
218 manage_topics: false,
219 send_photos: false,
220 send_videos: false,
221 send_roundvideos: false,
222 send_audios: false,
223 send_voices: false,
224 send_docs: false,
225 send_plain: false,
226 edit_rank: false,
227 until_date,
228 }),
229 };
230 self.rpc_call_raw_pub(&req).await?;
231 Ok(())
232 }
233
234 pub async fn promote_participant(
238 &self,
239 channel: tl::enums::Peer,
240 user_id: i64,
241 promote: bool,
242 ) -> Result<(), InvocationError> {
243 let (channel_id, ch_hash) = match &channel {
244 tl::enums::Peer::Channel(c) => {
245 let h = self.inner.peer_cache.lock().await.channels.get(&c.channel_id).copied().unwrap_or(0);
246 (c.channel_id, h)
247 }
248 _ => return Err(InvocationError::Deserialize("promote_participant: peer must be a channel".into())),
249 };
250 let user_hash = self.inner.peer_cache.lock().await.users.get(&user_id).copied().unwrap_or(0);
251
252 let rights = if promote {
253 tl::types::ChatAdminRights {
254 change_info: true,
255 post_messages: true,
256 edit_messages: true,
257 delete_messages: true,
258 ban_users: true,
259 invite_users: true,
260 pin_messages: true,
261 add_admins: false,
262 anonymous: false,
263 manage_call: true,
264 other: false,
265 manage_topics: false,
266 post_stories: false,
267 edit_stories: false,
268 delete_stories: false,
269 manage_direct_messages: false,
270 manage_ranks: false,
271 }
272 } else {
273 tl::types::ChatAdminRights {
274 change_info: false,
275 post_messages: false,
276 edit_messages: false,
277 delete_messages: false,
278 ban_users: false,
279 invite_users: false,
280 pin_messages: false,
281 add_admins: false,
282 anonymous: false,
283 manage_call: false,
284 other: false,
285 manage_topics: false,
286 post_stories: false,
287 edit_stories: false,
288 delete_stories: false,
289 manage_direct_messages: false,
290 manage_ranks: false,
291 }
292 };
293
294 let req = tl::functions::channels::EditAdmin {
295 channel: tl::enums::InputChannel::InputChannel(tl::types::InputChannel {
296 channel_id, access_hash: ch_hash,
297 }),
298 user_id: tl::enums::InputUser::InputUser(tl::types::InputUser { user_id, access_hash: user_hash }),
299 admin_rights: tl::enums::ChatAdminRights::ChatAdminRights(rights),
300 rank: None,
301 };
302 self.rpc_call_raw_pub(&req).await?;
303 Ok(())
304 }
305
306 pub async fn get_profile_photos(
310 &self,
311 peer: tl::enums::Peer,
312 limit: i32,
313 ) -> Result<Vec<tl::enums::Photo>, InvocationError> {
314 let input_peer = {
315 let cache = self.inner.peer_cache.lock().await;
316 cache.peer_to_input(&peer)
317 };
318
319 let req = tl::functions::photos::GetUserPhotos {
320 user_id: match &input_peer {
321 tl::enums::InputPeer::User(u) => tl::enums::InputUser::InputUser(
322 tl::types::InputUser { user_id: u.user_id, access_hash: u.access_hash }
323 ),
324 tl::enums::InputPeer::PeerSelf => tl::enums::InputUser::UserSelf,
325 _ => return Err(InvocationError::Deserialize("get_profile_photos: peer must be a user".into())),
326 },
327 offset: 0,
328 max_id: 0,
329 limit,
330 };
331 let body = self.rpc_call_raw_pub(&req).await?;
332 let mut cur = Cursor::from_slice(&body);
333 match tl::enums::photos::Photos::deserialize(&mut cur)? {
334 tl::enums::photos::Photos::Photos(p) => Ok(p.photos),
335 tl::enums::photos::Photos::Slice(p) => Ok(p.photos),
336 }
337 }
338
339 pub async fn search_peer(
343 &self,
344 query: &str,
345 ) -> Result<Vec<tl::enums::Peer>, InvocationError> {
346 let req = tl::functions::contacts::Search {
347 q: query.to_string(),
348 limit: 20,
349 };
350 let body = self.rpc_call_raw_pub(&req).await?;
351 let mut cur = Cursor::from_slice(&body);
352 let tl::enums::contacts::Found::Found(found) = tl::enums::contacts::Found::deserialize(&mut cur)?;
353
354 self.cache_users_slice_pub(&found.users).await;
355 self.cache_chats_slice_pub(&found.chats).await;
356
357 let mut peers = Vec::new();
358 for r in found.my_results.iter().chain(found.results.iter()) {
359 peers.push(r.clone());
360 }
361 Ok(peers)
362 }
363
364 pub async fn send_reaction(
368 &self,
369 peer: tl::enums::Peer,
370 message_id: i32,
371 reaction: &str,
372 ) -> Result<(), InvocationError> {
373 let input_peer = {
374 let cache = self.inner.peer_cache.lock().await;
375 cache.peer_to_input(&peer)
376 };
377
378 let reactions = if reaction.is_empty() {
379 vec![]
380 } else {
381 vec![tl::enums::Reaction::Emoji(tl::types::ReactionEmoji {
382 emoticon: reaction.to_string(),
383 })]
384 };
385
386 let req = tl::functions::messages::SendReaction {
387 big: false,
388 add_to_recent: false,
389 peer: input_peer,
390 msg_id: message_id,
391 reaction: Some(reactions),
392 };
393 self.rpc_call_raw_pub(&req).await?;
394 Ok(())
395 }
396}
397
398trait PeerUserIdExt {
401 fn user_id_or(&self, default: i64) -> i64;
402}
403
404impl PeerUserIdExt for tl::enums::Peer {
405 fn user_id_or(&self, default: i64) -> i64 {
406 match self {
407 tl::enums::Peer::User(u) => u.user_id,
408 _ => default,
409 }
410 }
411}
412
413#[derive(Debug, Clone, Default)]
427pub struct BannedRightsBuilder {
428 pub view_messages: bool,
429 pub send_messages: bool,
430 pub send_media: bool,
431 pub send_stickers: bool,
432 pub send_gifs: bool,
433 pub send_games: bool,
434 pub send_inline: bool,
435 pub embed_links: bool,
436 pub send_polls: bool,
437 pub change_info: bool,
438 pub invite_users: bool,
439 pub pin_messages: bool,
440 pub until_date: i32,
441}
442
443impl BannedRightsBuilder {
444 pub fn new() -> Self { Self::default() }
445 pub fn view_messages(mut self, v: bool) -> Self { self.view_messages = v; self }
446 pub fn send_messages(mut self, v: bool) -> Self { self.send_messages = v; self }
447 pub fn send_media(mut self, v: bool) -> Self { self.send_media = v; self }
448 pub fn send_stickers(mut self, v: bool) -> Self { self.send_stickers = v; self }
449 pub fn send_gifs(mut self, v: bool) -> Self { self.send_gifs = v; self }
450 pub fn send_games(mut self, v: bool) -> Self { self.send_games = v; self }
451 pub fn send_inline(mut self, v: bool) -> Self { self.send_inline = v; self }
452 pub fn embed_links(mut self, v: bool) -> Self { self.embed_links = v; self }
453 pub fn send_polls(mut self, v: bool) -> Self { self.send_polls = v; self }
454 pub fn change_info(mut self, v: bool) -> Self { self.change_info = v; self }
455 pub fn invite_users(mut self, v: bool) -> Self { self.invite_users = v; self }
456 pub fn pin_messages(mut self, v: bool) -> Self { self.pin_messages = v; self }
457 pub fn until_date(mut self, ts: i32) -> Self { self.until_date = ts; self }
459
460 pub fn full_ban() -> Self {
462 Self {
463 view_messages: true, send_messages: true, send_media: true,
464 send_stickers: true, send_gifs: true, send_games: true,
465 send_inline: true, embed_links: true, send_polls: true,
466 change_info: true, invite_users: true, pin_messages: true,
467 until_date: 0,
468 }
469 }
470
471 pub(crate) fn into_tl(self) -> tl::enums::ChatBannedRights {
472 tl::enums::ChatBannedRights::ChatBannedRights(tl::types::ChatBannedRights {
473 view_messages: self.view_messages,
474 send_messages: self.send_messages,
475 send_media: self.send_media,
476 send_stickers: self.send_stickers,
477 send_gifs: self.send_gifs,
478 send_games: self.send_games,
479 send_inline: self.send_inline,
480 embed_links: self.embed_links,
481 send_polls: self.send_polls,
482 change_info: self.change_info,
483 invite_users: self.invite_users,
484 pin_messages: self.pin_messages,
485 manage_topics: false,
486 send_photos: false,
487 send_videos: false,
488 send_roundvideos: false,
489 send_audios: false,
490 send_voices: false,
491 send_docs: false,
492 send_plain: false,
493 edit_rank: false,
494 until_date: self.until_date,
495 })
496 }
497}
498
499#[derive(Debug, Clone, Default)]
503pub struct AdminRightsBuilder {
504 pub change_info: bool,
505 pub post_messages: bool,
506 pub edit_messages: bool,
507 pub delete_messages: bool,
508 pub ban_users: bool,
509 pub invite_users: bool,
510 pub pin_messages: bool,
511 pub add_admins: bool,
512 pub anonymous: bool,
513 pub manage_call: bool,
514 pub manage_topics: bool,
515 pub rank: Option<String>,
516}
517
518impl AdminRightsBuilder {
519 pub fn new() -> Self { Self::default() }
520 pub fn change_info(mut self, v: bool) -> Self { self.change_info = v; self }
521 pub fn post_messages(mut self, v: bool) -> Self { self.post_messages = v; self }
522 pub fn edit_messages(mut self, v: bool) -> Self { self.edit_messages = v; self }
523 pub fn delete_messages(mut self, v: bool) -> Self { self.delete_messages = v; self }
524 pub fn ban_users(mut self, v: bool) -> Self { self.ban_users = v; self }
525 pub fn invite_users(mut self, v: bool) -> Self { self.invite_users = v; self }
526 pub fn pin_messages(mut self, v: bool) -> Self { self.pin_messages = v; self }
527 pub fn add_admins(mut self, v: bool) -> Self { self.add_admins = v; self }
528 pub fn anonymous(mut self, v: bool) -> Self { self.anonymous = v; self }
529 pub fn manage_call(mut self, v: bool) -> Self { self.manage_call = v; self }
530 pub fn manage_topics(mut self, v: bool) -> Self { self.manage_topics = v; self }
531 pub fn rank(mut self, r: impl Into<String>) -> Self { self.rank = Some(r.into()); self }
533
534 pub fn full_admin() -> Self {
536 Self {
537 change_info: true, post_messages: true, edit_messages: true,
538 delete_messages: true, ban_users: true, invite_users: true,
539 pin_messages: true, add_admins: false, anonymous: false,
540 manage_call: true, manage_topics: true, rank: None,
541 }
542 }
543
544 pub(crate) fn into_tl_rights(self) -> tl::enums::ChatAdminRights {
545 tl::enums::ChatAdminRights::ChatAdminRights(tl::types::ChatAdminRights {
546 change_info: self.change_info,
547 post_messages: self.post_messages,
548 edit_messages: self.edit_messages,
549 delete_messages: self.delete_messages,
550 ban_users: self.ban_users,
551 invite_users: self.invite_users,
552 pin_messages: self.pin_messages,
553 add_admins: self.add_admins,
554 anonymous: self.anonymous,
555 manage_call: self.manage_call,
556 other: false,
557 manage_topics: self.manage_topics,
558 post_stories: false,
559 edit_stories: false,
560 delete_stories: false,
561 manage_direct_messages: false,
562 manage_ranks: false,
563 })
564 }
565}
566
567#[derive(Debug, Clone)]
571pub struct ParticipantPermissions {
572 pub is_creator: bool,
573 pub is_admin: bool,
574 pub is_banned: bool,
575 pub is_left: bool,
576 pub can_send_messages: bool,
577 pub can_send_media: bool,
578 pub can_pin_messages: bool,
579 pub can_add_admins: bool,
580 pub admin_rank: Option<String>,
581}
582
583impl ParticipantPermissions {
584 pub fn is_creator(&self) -> bool { self.is_creator }
585 pub fn is_admin(&self) -> bool { self.is_admin }
586 pub fn is_banned(&self) -> bool { self.is_banned }
587 pub fn is_member(&self) -> bool { !self.is_banned && !self.is_left }
588}
589
590impl Client {
593 pub async fn set_banned_rights(
599 &self,
600 channel: tl::enums::Peer,
601 user_id: i64,
602 build: impl FnOnce(BannedRightsBuilder) -> BannedRightsBuilder,
603 ) -> Result<(), InvocationError> {
604 let rights = build(BannedRightsBuilder::new()).into_tl();
605 let (channel_id, ch_hash) = match &channel {
606 tl::enums::Peer::Channel(c) => {
607 let h = self.inner.peer_cache.lock().await.channels.get(&c.channel_id).copied().unwrap_or(0);
608 (c.channel_id, h)
609 }
610 _ => return Err(InvocationError::Deserialize("set_banned_rights: must be a channel".into())),
611 };
612 let user_hash = self.inner.peer_cache.lock().await.users.get(&user_id).copied().unwrap_or(0);
613 let req = tl::functions::channels::EditBanned {
614 channel: tl::enums::InputChannel::InputChannel(tl::types::InputChannel {
615 channel_id, access_hash: ch_hash,
616 }),
617 participant: tl::enums::InputPeer::User(tl::types::InputPeerUser {
618 user_id, access_hash: user_hash,
619 }),
620 banned_rights: rights,
621 };
622 self.rpc_call_raw_pub(&req).await?;
623 Ok(())
624 }
625
626 pub async fn set_admin_rights(
632 &self,
633 channel: tl::enums::Peer,
634 user_id: i64,
635 build: impl FnOnce(AdminRightsBuilder) -> AdminRightsBuilder,
636 ) -> Result<(), InvocationError> {
637 let b = build(AdminRightsBuilder::new());
638 let rank = b.rank.clone();
639 let rights = b.into_tl_rights();
640 let (channel_id, ch_hash) = match &channel {
641 tl::enums::Peer::Channel(c) => {
642 let h = self.inner.peer_cache.lock().await.channels.get(&c.channel_id).copied().unwrap_or(0);
643 (c.channel_id, h)
644 }
645 _ => return Err(InvocationError::Deserialize("set_admin_rights: must be a channel".into())),
646 };
647 let user_hash = self.inner.peer_cache.lock().await.users.get(&user_id).copied().unwrap_or(0);
648 let req = tl::functions::channels::EditAdmin {
649 channel: tl::enums::InputChannel::InputChannel(tl::types::InputChannel {
650 channel_id, access_hash: ch_hash,
651 }),
652 user_id: tl::enums::InputUser::InputUser(tl::types::InputUser { user_id, access_hash: user_hash }),
653 admin_rights: rights,
654 rank,
655 };
656 self.rpc_call_raw_pub(&req).await?;
657 Ok(())
658 }
659
660 pub async fn iter_participants(
666 &self,
667 peer: tl::enums::Peer,
668 filter: Option<tl::enums::ChannelParticipantsFilter>,
669 limit: i32,
670 ) -> Result<Vec<Participant>, InvocationError> {
671 match &peer {
672 tl::enums::Peer::Channel(c) => {
673 let access_hash = self.inner.peer_cache.lock().await
674 .channels.get(&c.channel_id).copied().unwrap_or(0);
675 let filter = filter.unwrap_or(tl::enums::ChannelParticipantsFilter::ChannelParticipantsRecent);
676 let limit = if limit <= 0 { 200 } else { limit };
677 let req = tl::functions::channels::GetParticipants {
678 channel: tl::enums::InputChannel::InputChannel(tl::types::InputChannel {
679 channel_id: c.channel_id, access_hash,
680 }),
681 filter,
682 offset: 0,
683 limit,
684 hash: 0,
685 };
686 let body = self.rpc_call_raw_pub(&req).await?;
687 let mut cur = Cursor::from_slice(&body);
688 let raw = match tl::enums::channels::ChannelParticipants::deserialize(&mut cur)? {
689 tl::enums::channels::ChannelParticipants::ChannelParticipants(p) => p,
690 tl::enums::channels::ChannelParticipants::NotModified => return Ok(vec![]),
691 };
692 let user_map: std::collections::HashMap<i64, tl::types::User> = raw.users.into_iter()
693 .filter_map(|u| match u { tl::enums::User::User(u) => Some((u.id, u)), _ => None })
694 .collect();
695 {
696 let mut cache = self.inner.peer_cache.lock().await;
697 for u in user_map.values() {
698 if let Some(h) = u.access_hash { cache.users.insert(u.id, h); }
699 }
700 }
701 Ok(raw.participants.into_iter().filter_map(|p| {
702 let (uid, status) = match &p {
703 tl::enums::ChannelParticipant::ChannelParticipant(x) => (x.user_id, ParticipantStatus::Member),
704 tl::enums::ChannelParticipant::ParticipantSelf(x) => (x.user_id, ParticipantStatus::Member),
705 tl::enums::ChannelParticipant::Creator(x) => (x.user_id, ParticipantStatus::Creator),
706 tl::enums::ChannelParticipant::Admin(x) => (x.user_id, ParticipantStatus::Admin),
707 tl::enums::ChannelParticipant::Banned(x) => {
708 if let tl::enums::Peer::User(u) = &x.peer { (u.user_id, ParticipantStatus::Banned) } else { return None; }
709 }
710 tl::enums::ChannelParticipant::Left(x) => {
711 if let tl::enums::Peer::User(u) = &x.peer { (u.user_id, ParticipantStatus::Left) } else { return None; }
712 }
713 };
714 user_map.get(&uid).map(|u| Participant { user: u.clone(), status })
715 }).collect())
716 }
717 tl::enums::Peer::Chat(c) => self.get_chat_participants(c.chat_id).await,
718 _ => Err(InvocationError::Deserialize("iter_participants: must be chat or channel".into())),
719 }
720 }
721
722 pub async fn get_permissions(
726 &self,
727 channel: tl::enums::Peer,
728 user_id: i64,
729 ) -> Result<ParticipantPermissions, InvocationError> {
730 let (channel_id, ch_hash) = match &channel {
731 tl::enums::Peer::Channel(c) => {
732 let h = self.inner.peer_cache.lock().await.channels.get(&c.channel_id).copied().unwrap_or(0);
733 (c.channel_id, h)
734 }
735 _ => return Err(InvocationError::Deserialize("get_permissions: must be a channel".into())),
736 };
737 let user_hash = self.inner.peer_cache.lock().await.users.get(&user_id).copied().unwrap_or(0);
738 let req = tl::functions::channels::GetParticipant {
739 channel: tl::enums::InputChannel::InputChannel(tl::types::InputChannel {
740 channel_id, access_hash: ch_hash,
741 }),
742 participant: tl::enums::InputPeer::User(tl::types::InputPeerUser {
743 user_id, access_hash: user_hash,
744 }),
745 };
746 let body = self.rpc_call_raw_pub(&req).await?;
747 let mut cur = Cursor::from_slice(&body);
748 let tl::enums::channels::ChannelParticipant::ChannelParticipant(raw) = tl::enums::channels::ChannelParticipant::deserialize(&mut cur)?;
749
750 let perms = match raw.participant {
751 tl::enums::ChannelParticipant::Creator(_) => ParticipantPermissions {
752 is_creator: true, is_admin: true, is_banned: false, is_left: false,
753 can_send_messages: true, can_send_media: true, can_pin_messages: true,
754 can_add_admins: true, admin_rank: None,
755 },
756 tl::enums::ChannelParticipant::Admin(a) => {
757 let tl::enums::ChatAdminRights::ChatAdminRights(rights) = a.admin_rights;
758 ParticipantPermissions {
759 is_creator: false, is_admin: true, is_banned: false, is_left: false,
760 can_send_messages: true, can_send_media: true,
761 can_pin_messages: rights.pin_messages,
762 can_add_admins: rights.add_admins,
763 admin_rank: a.rank,
764 }
765 }
766 tl::enums::ChannelParticipant::Banned(b) => {
767 let tl::enums::ChatBannedRights::ChatBannedRights(rights) = b.banned_rights;
768 ParticipantPermissions {
769 is_creator: false, is_admin: false, is_banned: true, is_left: false,
770 can_send_messages: !rights.send_messages,
771 can_send_media: !rights.send_media,
772 can_pin_messages: !rights.pin_messages,
773 can_add_admins: false, admin_rank: None,
774 }
775 }
776 tl::enums::ChannelParticipant::Left(_) => ParticipantPermissions {
777 is_creator: false, is_admin: false, is_banned: false, is_left: true,
778 can_send_messages: false, can_send_media: false, can_pin_messages: false,
779 can_add_admins: false, admin_rank: None,
780 },
781 _ => ParticipantPermissions {
782 is_creator: false, is_admin: false, is_banned: false, is_left: false,
783 can_send_messages: true, can_send_media: true, can_pin_messages: false,
784 can_add_admins: false, admin_rank: None,
785 },
786 };
787
788 Ok(perms)
789 }
790}