grammers_client/update/
callback_query.rs1use std::convert::TryInto;
10use std::fmt;
11use std::time::Duration;
12
13use grammers_mtsender::InvocationError;
14use grammers_session::types::{PeerId, PeerRef};
15use grammers_session::updates::State;
16use grammers_tl_types as tl;
17
18use crate::Client;
19use crate::message::{InputMessage, Message};
20use crate::peer::{Peer, PeerMap};
21
22#[derive(Clone)]
28pub struct CallbackQuery {
29 pub raw: tl::enums::Update,
30 pub state: State,
31 pub(crate) client: Client,
32 pub(crate) peers: PeerMap,
33}
34
35pub struct Answer<'a> {
39 query: &'a CallbackQuery,
40 request: tl::functions::messages::SetBotCallbackAnswer,
41}
42
43impl CallbackQuery {
44 pub fn peer_id(&self) -> PeerId {
46 match &self.raw {
47 tl::enums::Update::BotCallbackQuery(update) => update.peer.clone().into(),
48 tl::enums::Update::InlineBotCallbackQuery(update) => {
49 PeerId::user_unchecked(update.user_id)
50 }
51 _ => unreachable!(),
52 }
53 }
54
55 pub async fn peer_ref(
57 &self,
58 ) -> Result<Option<PeerRef>, Box<dyn std::error::Error + Send + Sync>> {
59 self.peers.get_ref(self.peer_id()).await
60 }
61
62 pub fn peer(&self) -> Option<&Peer> {
64 self.peers.get(self.peer_id())
65 }
66
67 pub fn sender_id(&self) -> PeerId {
69 PeerId::user_unchecked(match &self.raw {
70 tl::enums::Update::BotCallbackQuery(update) => update.user_id,
71 tl::enums::Update::InlineBotCallbackQuery(update) => update.user_id,
72 _ => unreachable!(),
73 })
74 }
75
76 pub async fn sender_ref(
78 &self,
79 ) -> Result<Option<PeerRef>, Box<dyn std::error::Error + Send + Sync>> {
80 self.peers.get_ref(self.sender_id()).await
81 }
82
83 pub fn sender(&self) -> Option<&Peer> {
85 self.peers.get(self.sender_id())
86 }
87
88 pub fn data(&self) -> &[u8] {
97 match &self.raw {
98 tl::enums::Update::BotCallbackQuery(update) => update.data.as_deref().unwrap_or(&[]),
99 tl::enums::Update::InlineBotCallbackQuery(update) => {
100 update.data.as_deref().unwrap_or(&[])
101 }
102 _ => unreachable!(),
103 }
104 }
105
106 pub fn is_from_inline(&self) -> bool {
108 matches!(self.raw, tl::enums::Update::InlineBotCallbackQuery(_))
109 }
110
111 pub async fn load_message(&self) -> Result<Message, InvocationError> {
113 let msg_id = match &self.raw {
114 tl::enums::Update::BotCallbackQuery(update) => update.msg_id,
115 _ => return Err(InvocationError::Dropped),
116 };
117 Ok(self
118 .client
119 .get_messages_by_id(
120 self.peer_ref().await?.ok_or(InvocationError::Dropped)?,
121 &[msg_id],
122 )
123 .await?
124 .pop()
125 .unwrap()
126 .unwrap())
127 }
128
129 pub fn answer(&self) -> Answer<'_> {
131 let query_id = match &self.raw {
132 tl::enums::Update::BotCallbackQuery(update) => update.query_id,
133 tl::enums::Update::InlineBotCallbackQuery(update) => update.query_id,
134 _ => unreachable!(),
135 };
136 Answer {
137 request: tl::functions::messages::SetBotCallbackAnswer {
138 alert: false,
139 query_id,
140 message: None,
141 url: None,
142 cache_time: 0,
143 },
144 query: self,
145 }
146 }
147}
148
149impl<'a> Answer<'a> {
150 pub fn text<T: Into<String>>(mut self, text: T) -> Self {
155 self.request.message = Some(text.into());
156 self.request.alert = false;
157 self
158 }
159
160 pub fn cache_time(mut self, time: Duration) -> Self {
164 self.request.cache_time = time.as_secs().try_into().unwrap_or(i32::MAX);
165 self
166 }
167
168 pub fn alert<T: Into<String>>(mut self, text: T) -> Self {
173 self.request.message = Some(text.into());
174 self.request.alert = true;
175 self
176 }
177
178 pub async fn send(self) -> Result<(), InvocationError> {
181 self.query.client.invoke(&self.request).await?;
182 Ok(())
183 }
184
185 pub async fn edit<M: Into<InputMessage>>(self, new_message: M) -> Result<(), InvocationError> {
187 self.query.client.invoke(&self.request).await?;
188 let peer = self
189 .query
190 .peer_ref()
191 .await?
192 .ok_or(InvocationError::Dropped)?;
193 match &self.query.raw {
194 tl::enums::Update::BotCallbackQuery(update) => {
195 self.query
196 .client
197 .edit_message(peer, update.msg_id, new_message)
198 .await
199 }
200 tl::enums::Update::InlineBotCallbackQuery(update) => self
201 .query
202 .client
203 .edit_inline_message(update.msg_id.clone(), new_message.into())
204 .await
205 .map(drop),
206 _ => unreachable!(),
207 }
208 }
209
210 pub async fn respond<M: Into<InputMessage>>(
212 self,
213 message: M,
214 ) -> Result<Message, InvocationError> {
215 self.query.client.invoke(&self.request).await?;
216 let peer = self
217 .query
218 .peer_ref()
219 .await?
220 .ok_or(InvocationError::Dropped)?;
221 self.query.client.send_message(peer, message).await
222 }
223
224 pub async fn reply<M: Into<InputMessage>>(
226 self,
227 message: M,
228 ) -> Result<Message, InvocationError> {
229 let msg_id = match &self.query.raw {
230 tl::enums::Update::BotCallbackQuery(update) => update.msg_id,
231 _ => return Err(InvocationError::Dropped),
232 };
233 self.query.client.invoke(&self.request).await?;
234 let peer = self
235 .query
236 .peer_ref()
237 .await?
238 .ok_or(InvocationError::Dropped)?;
239 let message = message.into();
240 self.query
241 .client
242 .send_message(peer, message.reply_to(Some(msg_id)))
243 .await
244 }
245}
246
247impl fmt::Debug for CallbackQuery {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 f.debug_struct("CallbackQuery")
250 .field("data", &self.data())
251 .field("sender", &self.sender())
252 .field("peer", &self.peer())
253 .finish()
254 }
255}