grammers_client/client/
bots.rs1use grammers_mtsender::InvocationError;
10use grammers_session::types::PeerRef;
11use grammers_tl_types as tl;
12
13use super::messages::parse_mention_entities;
14use super::{Client, IterBuffer};
15use crate::message::InputMessage;
16use crate::utils::generate_random_id;
17
18const MAX_LIMIT: usize = 50;
19
20pub struct InlineResult {
22 client: Client,
23 query_id: i64,
24 pub raw: tl::enums::BotInlineResult,
25}
26
27pub type InlineResultIter = IterBuffer<tl::functions::messages::GetInlineBotResults, InlineResult>;
29
30impl InlineResult {
31 pub async fn send<C: Into<PeerRef>>(&self, peer: C) -> Result<(), InvocationError> {
34 self.client
35 .invoke(&tl::functions::messages::SendInlineBotResult {
36 silent: false,
37 background: false,
38 clear_draft: false,
39 hide_via: false,
40 peer: peer.into().into(),
41 reply_to: None,
42 random_id: generate_random_id(),
43 query_id: self.query_id,
44 id: self.id().to_string(),
45 schedule_date: None,
46 send_as: None,
47 quick_reply_shortcut: None,
48 allow_paid_stars: None,
49 })
50 .await
51 .map(drop)
52 }
53
54 pub fn id(&self) -> &str {
56 use tl::enums::BotInlineResult::*;
57
58 match &self.raw {
59 Result(r) => &r.id,
60 BotInlineMediaResult(r) => &r.id,
61 }
62 }
63
64 pub fn title(&self) -> Option<&String> {
66 use tl::enums::BotInlineResult::*;
67
68 match &self.raw {
69 Result(r) => r.title.as_ref(),
70 BotInlineMediaResult(r) => r.title.as_ref(),
71 }
72 }
73}
74
75impl InlineResultIter {
76 fn new(client: &Client, bot: PeerRef, query: &str) -> Self {
77 Self::from_request(
78 client,
79 MAX_LIMIT,
80 tl::functions::messages::GetInlineBotResults {
81 bot: bot.into(),
82 peer: tl::enums::InputPeer::Empty,
83 geo_point: None,
84 query: query.to_string(),
85 offset: String::new(),
86 },
87 )
88 }
89
90 pub fn peer<C: Into<PeerRef>>(mut self, peer: C) -> Self {
95 self.request.peer = peer.into().into();
96 self
97 }
98
99 pub async fn next(&mut self) -> Result<Option<InlineResult>, InvocationError> {
104 if let Some(result) = self.next_raw() {
105 return result;
106 }
107
108 let tl::enums::messages::BotResults::Results(tl::types::messages::BotResults {
109 query_id,
110 next_offset,
111 results,
112 ..
113 }) = self.client.invoke(&self.request).await?;
114
115 if let Some(offset) = next_offset {
116 self.request.offset = offset;
117 } else {
118 self.last_chunk = true;
119 }
120
121 let client = self.client.clone();
122 self.buffer
123 .extend(results.into_iter().map(|r| InlineResult {
124 client: client.clone(),
125 query_id,
126 raw: r,
127 }));
128
129 Ok(self.pop_item())
130 }
131}
132
133impl Client {
135 pub fn inline_query<C: Into<PeerRef>>(&self, bot: C, query: &str) -> InlineResultIter {
156 InlineResultIter::new(self, bot.into(), query)
157 }
158
159 pub(crate) async fn edit_inline_message(
164 &self,
165 message_id: tl::enums::InputBotInlineMessageId,
166 message: InputMessage,
167 ) -> Result<bool, InvocationError> {
168 let entities = parse_mention_entities(self, message.entities).await;
169 if message.media.as_ref().is_some_and(|media| {
170 !matches!(
171 media,
172 tl::enums::InputMedia::PhotoExternal(_)
173 | tl::enums::InputMedia::DocumentExternal(_),
174 )
175 }) {
176 let dc_id = message_id.dc_id();
177 self.invoke_in_dc(
178 dc_id,
179 &tl::functions::messages::EditInlineBotMessage {
180 id: message_id,
181 message: Some(message.text),
182 media: message.media,
183 entities,
184 no_webpage: !message.link_preview,
185 reply_markup: message.reply_markup,
186 invert_media: message.invert_media,
187 },
188 )
189 .await
190 } else {
191 self.invoke(&tl::functions::messages::EditInlineBotMessage {
192 id: message_id,
193 message: Some(message.text),
194 media: message.media,
195 entities,
196 no_webpage: !message.link_preview,
197 reply_markup: message.reply_markup,
198 invert_media: message.invert_media,
199 })
200 .await
201 }
202 }
203}