layer_client/
inline_iter.rs1use std::collections::VecDeque;
29
30use layer_tl_types as tl;
31use layer_tl_types::{Cursor, Deserializable};
32use tokio::sync::mpsc;
33
34use crate::update::{InlineQuery, Update};
35use crate::{Client, InvocationError};
36
37pub struct InlineQueryIter {
42 rx: mpsc::UnboundedReceiver<InlineQuery>,
43}
44
45impl InlineQueryIter {
46 pub async fn next(&mut self) -> Option<InlineQuery> {
48 self.rx.recv().await
49 }
50}
51
52pub struct InlineResult {
55 client: Client,
56 query_id: i64,
57 pub raw: tl::enums::BotInlineResult,
59}
60
61impl InlineResult {
62 pub fn id(&self) -> &str {
64 match &self.raw {
65 tl::enums::BotInlineResult::BotInlineResult(r) => &r.id,
66 tl::enums::BotInlineResult::BotInlineMediaResult(r) => &r.id,
67 }
68 }
69
70 pub fn title(&self) -> Option<&str> {
72 match &self.raw {
73 tl::enums::BotInlineResult::BotInlineResult(r) => r.title.as_deref(),
74 tl::enums::BotInlineResult::BotInlineMediaResult(r) => r.title.as_deref(),
75 }
76 }
77
78 pub fn description(&self) -> Option<&str> {
80 match &self.raw {
81 tl::enums::BotInlineResult::BotInlineResult(r) => r.description.as_deref(),
82 tl::enums::BotInlineResult::BotInlineMediaResult(r) => r.description.as_deref(),
83 }
84 }
85
86 pub async fn send(&self, peer: tl::enums::Peer) -> Result<(), InvocationError> {
88 let input_peer = {
89 let cache = self.client.inner.peer_cache.read().await;
90 cache.peer_to_input(&peer)
91 };
92 let req = tl::functions::messages::SendInlineBotResult {
93 silent: false,
94 background: false,
95 clear_draft: false,
96 hide_via: false,
97 peer: input_peer,
98 reply_to: None,
99 random_id: crate::random_i64_pub(),
100 query_id: self.query_id,
101 id: self.id().to_string(),
102 schedule_date: None,
103 send_as: None,
104 quick_reply_shortcut: None,
105 allow_paid_stars: None,
106 };
107 self.client.rpc_call_raw_pub(&req).await?;
108 Ok(())
109 }
110}
111
112pub struct InlineResultIter {
115 client: Client,
116 request: tl::functions::messages::GetInlineBotResults,
117 buffer: VecDeque<InlineResult>,
118 last_chunk: bool,
119}
120
121impl InlineResultIter {
122 fn new(client: Client, request: tl::functions::messages::GetInlineBotResults) -> Self {
123 Self {
124 client,
125 request,
126 buffer: VecDeque::new(),
127 last_chunk: false,
128 }
129 }
130
131 pub fn peer(mut self, peer: tl::enums::InputPeer) -> Self {
133 self.request.peer = peer;
134 self
135 }
136
137 pub async fn next(&mut self) -> Result<Option<InlineResult>, InvocationError> {
139 if let Some(item) = self.buffer.pop_front() {
140 return Ok(Some(item));
141 }
142 if self.last_chunk {
143 return Ok(None);
144 }
145
146 let raw = self.client.rpc_call_raw_pub(&self.request).await?;
147 let mut cur = Cursor::from_slice(&raw);
148 let tl::enums::messages::BotResults::BotResults(r) =
149 tl::enums::messages::BotResults::deserialize(&mut cur)?;
150
151 let query_id = r.query_id;
152 if let Some(offset) = r.next_offset {
153 self.request.offset = offset;
154 } else {
155 self.last_chunk = true;
156 }
157
158 let client = self.client.clone();
159 self.buffer
160 .extend(r.results.into_iter().map(|raw| InlineResult {
161 client: client.clone(),
162 query_id,
163 raw,
164 }));
165
166 Ok(self.buffer.pop_front())
167 }
168}
169
170impl Client {
173 pub fn iter_inline_queries(&self) -> InlineQueryIter {
175 let (tx, rx) = mpsc::unbounded_channel();
176 let client = self.clone();
177 tokio::spawn(async move {
178 let mut stream = client.stream_updates();
179 loop {
180 match stream.next().await {
181 Some(Update::InlineQuery(q)) => {
182 if tx.send(q).is_err() {
183 break;
184 }
185 }
186 Some(_) => {}
187 None => break,
188 }
189 }
190 });
191 InlineQueryIter { rx }
192 }
193
194 pub async fn inline_query(
209 &self,
210 bot: tl::enums::Peer,
211 query: &str,
212 ) -> Result<InlineResultIter, InvocationError> {
213 let input_bot = {
214 let cache = self.inner.peer_cache.read().await;
215 match cache.peer_to_input(&bot) {
216 tl::enums::InputPeer::User(u) => {
217 tl::enums::InputUser::InputUser(tl::types::InputUser {
218 user_id: u.user_id,
219 access_hash: u.access_hash,
220 })
221 }
222 _ => tl::enums::InputUser::Empty,
223 }
224 };
225 let request = tl::functions::messages::GetInlineBotResults {
226 bot: input_bot,
227 peer: tl::enums::InputPeer::Empty,
228 geo_point: None,
229 query: query.to_string(),
230 offset: String::new(),
231 };
232 Ok(InlineResultIter::new(self.clone(), request))
233 }
234}