layer_client/
inline_iter.rs1use std::collections::VecDeque;
12
13use tokio::sync::mpsc;
14use layer_tl_types as tl;
15use layer_tl_types::{Cursor, Deserializable};
16
17use crate::update::{InlineQuery, Update};
18use crate::{Client, InvocationError};
19
20pub struct InlineQueryIter {
25 rx: mpsc::UnboundedReceiver<InlineQuery>,
26}
27
28impl InlineQueryIter {
29 pub async fn next(&mut self) -> Option<InlineQuery> {
31 self.rx.recv().await
32 }
33}
34
35pub struct InlineResult {
40 client: Client,
41 query_id: i64,
42 pub raw: tl::enums::BotInlineResult,
44}
45
46impl InlineResult {
47 pub fn id(&self) -> &str {
49 match &self.raw {
50 tl::enums::BotInlineResult::BotInlineResult(r) => &r.id,
51 tl::enums::BotInlineResult::BotInlineMediaResult(r) => &r.id,
52 }
53 }
54
55 pub fn title(&self) -> Option<&str> {
57 match &self.raw {
58 tl::enums::BotInlineResult::BotInlineResult(r) => r.title.as_deref(),
59 tl::enums::BotInlineResult::BotInlineMediaResult(r) => r.title.as_deref(),
60 }
61 }
62
63 pub fn description(&self) -> Option<&str> {
65 match &self.raw {
66 tl::enums::BotInlineResult::BotInlineResult(r) => r.description.as_deref(),
67 tl::enums::BotInlineResult::BotInlineMediaResult(r) => r.description.as_deref(),
68 }
69 }
70
71 pub async fn send(&self, peer: tl::enums::Peer) -> Result<(), InvocationError> {
73 let input_peer = {
74 let cache = self.client.inner.peer_cache.read().await;
75 cache.peer_to_input(&peer)
76 };
77 let req = tl::functions::messages::SendInlineBotResult {
78 silent: false,
79 background: false,
80 clear_draft: false,
81 hide_via: false,
82 peer: input_peer,
83 reply_to: None,
84 random_id: crate::random_i64_pub(),
85 query_id: self.query_id,
86 id: self.id().to_string(),
87 schedule_date: None,
88 send_as: None,
89 quick_reply_shortcut: None,
90 allow_paid_stars: None,
91 };
92 self.client.rpc_call_raw_pub(&req).await?;
93 Ok(())
94 }
95}
96
97pub struct InlineResultIter {
102 client: Client,
103 request: tl::functions::messages::GetInlineBotResults,
104 buffer: VecDeque<InlineResult>,
105 last_chunk: bool,
106}
107
108impl InlineResultIter {
109 fn new(client: Client, request: tl::functions::messages::GetInlineBotResults) -> Self {
110 Self { client, request, buffer: VecDeque::new(), last_chunk: false }
111 }
112
113 pub fn peer(mut self, peer: tl::enums::InputPeer) -> Self {
115 self.request.peer = peer;
116 self
117 }
118
119 pub async fn next(&mut self) -> Result<Option<InlineResult>, InvocationError> {
121 if let Some(item) = self.buffer.pop_front() {
122 return Ok(Some(item));
123 }
124 if self.last_chunk {
125 return Ok(None);
126 }
127
128 let raw = self.client.rpc_call_raw_pub(&self.request).await?;
129 let mut cur = Cursor::from_slice(&raw);
130 let tl::enums::messages::BotResults::BotResults(r) =
131 tl::enums::messages::BotResults::deserialize(&mut cur)?;
132
133 let query_id = r.query_id;
134 if let Some(offset) = r.next_offset {
135 self.request.offset = offset;
136 } else {
137 self.last_chunk = true;
138 }
139
140 let client = self.client.clone();
141 self.buffer.extend(r.results.into_iter().map(|raw| InlineResult {
142 client: client.clone(),
143 query_id,
144 raw,
145 }));
146
147 Ok(self.buffer.pop_front())
148 }
149}
150
151impl Client {
154 pub fn iter_inline_queries(&self) -> InlineQueryIter {
156 let (tx, rx) = mpsc::unbounded_channel();
157 let client = self.clone();
158 tokio::spawn(async move {
159 let mut stream = client.stream_updates();
160 loop {
161 match stream.next().await {
162 Some(Update::InlineQuery(q)) => { if tx.send(q).is_err() { break; } }
163 Some(_) => {}
164 None => break,
165 }
166 }
167 });
168 InlineQueryIter { rx }
169 }
170
171 pub async fn inline_query(
186 &self,
187 bot: tl::enums::Peer,
188 query: &str,
189 ) -> Result<InlineResultIter, InvocationError> {
190 let input_bot = {
191 let cache = self.inner.peer_cache.read().await;
192 match cache.peer_to_input(&bot) {
193 tl::enums::InputPeer::User(u) =>
194 tl::enums::InputUser::InputUser(tl::types::InputUser {
195 user_id: u.user_id,
196 access_hash: u.access_hash,
197 }),
198 _ => tl::enums::InputUser::Empty,
199 }
200 };
201 let request = tl::functions::messages::GetInlineBotResults {
202 bot: input_bot,
203 peer: tl::enums::InputPeer::Empty,
204 geo_point: None,
205 query: query.to_string(),
206 offset: String::new(),
207 };
208 Ok(InlineResultIter::new(self.clone(), request))
209 }
210}