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(&self) -> Option<PeerRef> {
57 self.peers.get_ref(self.peer_id()).await
58 }
59
60 pub fn peer(&self) -> Option<&Peer> {
62 self.peers.get(self.peer_id())
63 }
64
65 pub fn sender_id(&self) -> PeerId {
67 PeerId::user_unchecked(match &self.raw {
68 tl::enums::Update::BotCallbackQuery(update) => update.user_id,
69 tl::enums::Update::InlineBotCallbackQuery(update) => update.user_id,
70 _ => unreachable!(),
71 })
72 }
73
74 pub async fn sender_ref(&self) -> Option<PeerRef> {
76 self.peers.get_ref(self.sender_id()).await
77 }
78
79 pub fn sender(&self) -> Option<&Peer> {
81 self.peers.get(self.sender_id())
82 }
83
84 pub fn data(&self) -> &[u8] {
93 match &self.raw {
94 tl::enums::Update::BotCallbackQuery(update) => update.data.as_deref().unwrap_or(&[]),
95 tl::enums::Update::InlineBotCallbackQuery(update) => {
96 update.data.as_deref().unwrap_or(&[])
97 }
98 _ => unreachable!(),
99 }
100 }
101
102 pub fn is_from_inline(&self) -> bool {
104 matches!(self.raw, tl::enums::Update::InlineBotCallbackQuery(_))
105 }
106
107 pub async fn load_message(&self) -> Result<Message, InvocationError> {
109 let msg_id = match &self.raw {
110 tl::enums::Update::BotCallbackQuery(update) => update.msg_id,
111 _ => return Err(InvocationError::Dropped),
112 };
113 Ok(self
114 .client
115 .get_messages_by_id(
116 self.peer_ref().await.ok_or(InvocationError::Dropped)?,
117 &[msg_id],
118 )
119 .await?
120 .pop()
121 .unwrap()
122 .unwrap())
123 }
124
125 pub fn answer(&self) -> Answer<'_> {
127 let query_id = match &self.raw {
128 tl::enums::Update::BotCallbackQuery(update) => update.query_id,
129 tl::enums::Update::InlineBotCallbackQuery(update) => update.query_id,
130 _ => unreachable!(),
131 };
132 Answer {
133 request: tl::functions::messages::SetBotCallbackAnswer {
134 alert: false,
135 query_id,
136 message: None,
137 url: None,
138 cache_time: 0,
139 },
140 query: self,
141 }
142 }
143}
144
145impl<'a> Answer<'a> {
146 pub fn text<T: Into<String>>(mut self, text: T) -> Self {
151 self.request.message = Some(text.into());
152 self.request.alert = false;
153 self
154 }
155
156 pub fn cache_time(mut self, time: Duration) -> Self {
160 self.request.cache_time = time.as_secs().try_into().unwrap_or(i32::MAX);
161 self
162 }
163
164 pub fn alert<T: Into<String>>(mut self, text: T) -> Self {
169 self.request.message = Some(text.into());
170 self.request.alert = true;
171 self
172 }
173
174 pub async fn send(self) -> Result<(), InvocationError> {
177 self.query.client.invoke(&self.request).await?;
178 Ok(())
179 }
180
181 pub async fn edit<M: Into<InputMessage>>(self, new_message: M) -> Result<(), InvocationError> {
183 self.query.client.invoke(&self.request).await?;
184 let peer = self
185 .query
186 .peer_ref()
187 .await
188 .ok_or(InvocationError::Dropped)?;
189 match &self.query.raw {
190 tl::enums::Update::BotCallbackQuery(update) => {
191 self.query
192 .client
193 .edit_message(peer, update.msg_id, new_message)
194 .await
195 }
196 tl::enums::Update::InlineBotCallbackQuery(update) => self
197 .query
198 .client
199 .edit_inline_message(update.msg_id.clone(), new_message.into())
200 .await
201 .map(drop),
202 _ => unreachable!(),
203 }
204 }
205
206 pub async fn respond<M: Into<InputMessage>>(
208 self,
209 message: M,
210 ) -> Result<Message, InvocationError> {
211 self.query.client.invoke(&self.request).await?;
212 let peer = self
213 .query
214 .peer_ref()
215 .await
216 .ok_or(InvocationError::Dropped)?;
217 self.query.client.send_message(peer, message).await
218 }
219
220 pub async fn reply<M: Into<InputMessage>>(
222 self,
223 message: M,
224 ) -> Result<Message, InvocationError> {
225 let msg_id = match &self.query.raw {
226 tl::enums::Update::BotCallbackQuery(update) => update.msg_id,
227 _ => return Err(InvocationError::Dropped),
228 };
229 self.query.client.invoke(&self.request).await?;
230 let peer = self
231 .query
232 .peer_ref()
233 .await
234 .ok_or(InvocationError::Dropped)?;
235 let message = message.into();
236 self.query
237 .client
238 .send_message(peer, message.reply_to(Some(msg_id)))
239 .await
240 }
241}
242
243impl fmt::Debug for CallbackQuery {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 f.debug_struct("CallbackQuery")
246 .field("data", &self.data())
247 .field("sender", &self.sender())
248 .field("peer", &self.peer())
249 .finish()
250 }
251}