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