layer_client/
inline_iter.rs1use std::collections::VecDeque;
11
12use layer_tl_types as tl;
13use layer_tl_types::{Cursor, Deserializable};
14use tokio::sync::mpsc;
15
16use crate::update::{InlineQuery, Update};
17use crate::{Client, InvocationError};
18
19pub struct InlineQueryIter {
24 rx: mpsc::UnboundedReceiver<InlineQuery>,
25}
26
27impl InlineQueryIter {
28 pub async fn next(&mut self) -> Option<InlineQuery> {
30 self.rx.recv().await
31 }
32}
33
34pub struct InlineResult {
37 client: Client,
38 query_id: i64,
39 pub raw: tl::enums::BotInlineResult,
41}
42
43impl InlineResult {
44 pub fn id(&self) -> &str {
46 match &self.raw {
47 tl::enums::BotInlineResult::BotInlineResult(r) => &r.id,
48 tl::enums::BotInlineResult::BotInlineMediaResult(r) => &r.id,
49 }
50 }
51
52 pub fn title(&self) -> Option<&str> {
54 match &self.raw {
55 tl::enums::BotInlineResult::BotInlineResult(r) => r.title.as_deref(),
56 tl::enums::BotInlineResult::BotInlineMediaResult(r) => r.title.as_deref(),
57 }
58 }
59
60 pub fn description(&self) -> Option<&str> {
62 match &self.raw {
63 tl::enums::BotInlineResult::BotInlineResult(r) => r.description.as_deref(),
64 tl::enums::BotInlineResult::BotInlineMediaResult(r) => r.description.as_deref(),
65 }
66 }
67
68 pub async fn send(&self, peer: tl::enums::Peer) -> Result<(), InvocationError> {
70 let input_peer = {
71 let cache = self.client.inner.peer_cache.read().await;
72 cache.peer_to_input(&peer)
73 };
74 let req = tl::functions::messages::SendInlineBotResult {
75 silent: false,
76 background: false,
77 clear_draft: false,
78 hide_via: false,
79 peer: input_peer,
80 reply_to: None,
81 random_id: crate::random_i64_pub(),
82 query_id: self.query_id,
83 id: self.id().to_string(),
84 schedule_date: None,
85 send_as: None,
86 quick_reply_shortcut: None,
87 allow_paid_stars: None,
88 };
89 self.client.rpc_call_raw_pub(&req).await?;
90 Ok(())
91 }
92}
93
94pub struct InlineResultIter {
97 client: Client,
98 request: tl::functions::messages::GetInlineBotResults,
99 buffer: VecDeque<InlineResult>,
100 last_chunk: bool,
101}
102
103impl InlineResultIter {
104 fn new(client: Client, request: tl::functions::messages::GetInlineBotResults) -> Self {
105 Self {
106 client,
107 request,
108 buffer: VecDeque::new(),
109 last_chunk: false,
110 }
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
142 .extend(r.results.into_iter().map(|raw| InlineResult {
143 client: client.clone(),
144 query_id,
145 raw,
146 }));
147
148 Ok(self.buffer.pop_front())
149 }
150}
151
152impl Client {
155 pub fn iter_inline_queries(&self) -> InlineQueryIter {
157 let (tx, rx) = mpsc::unbounded_channel();
158 let client = self.clone();
159 tokio::spawn(async move {
160 let mut stream = client.stream_updates();
161 loop {
162 match stream.next().await {
163 Some(Update::InlineQuery(q)) => {
164 if tx.send(q).is_err() {
165 break;
166 }
167 }
168 Some(_) => {}
169 None => break,
170 }
171 }
172 });
173 InlineQueryIter { rx }
174 }
175
176 pub async fn inline_query(
191 &self,
192 bot: tl::enums::Peer,
193 query: &str,
194 ) -> Result<InlineResultIter, InvocationError> {
195 let input_bot = {
196 let cache = self.inner.peer_cache.read().await;
197 match cache.peer_to_input(&bot) {
198 tl::enums::InputPeer::User(u) => {
199 tl::enums::InputUser::InputUser(tl::types::InputUser {
200 user_id: u.user_id,
201 access_hash: u.access_hash,
202 })
203 }
204 _ => tl::enums::InputUser::Empty,
205 }
206 };
207 let request = tl::functions::messages::GetInlineBotResults {
208 bot: input_bot,
209 peer: tl::enums::InputPeer::Empty,
210 geo_point: None,
211 query: query.to_string(),
212 offset: String::new(),
213 };
214 Ok(InlineResultIter::new(self.clone(), request))
215 }
216}