tg_flows/types/callback_query.rs
1use serde::{Deserialize, Serialize};
2
3use crate::types::{Message, User};
4
5/// This object represents an incoming callback query from a callback button in
6/// an [inline keyboard].
7///
8/// If the button that originated the query was attached to a message sent by
9/// the bot, the field message will be present. If the button was attached to a
10/// message sent via the bot (in [inline mode]), the field `inline_message_id`
11/// will be present. Exactly one of the fields data or `game_short_name` will be
12/// present.
13///
14/// [The official docs](https://core.telegram.org/bots/api#callbackquery).
15///
16/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
17/// [inline mode]: https://core.telegram.org/bots/api#inline-mode
18#[serde_with_macros::skip_serializing_none]
19#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
20pub struct CallbackQuery {
21 /// An unique identifier for this query.
22 pub id: String,
23
24 /// A sender.
25 pub from: User,
26
27 /// A message with the callback button that originated the query. Note that
28 /// message content and message date will not be available if the message
29 /// is too old.
30 pub message: Option<Message>,
31
32 /// An identifier of the message sent via the bot in inline mode, that
33 /// originated the query.
34 pub inline_message_id: Option<String>,
35
36 /// A global identifier, uniquely corresponding to the chat to which the
37 /// message with the callback button was sent. Useful for high scores in
38 /// [games].
39 ///
40 /// [games]: https://core.telegram.org/bots/api#games
41 pub chat_instance: String,
42
43 /// A data associated with the callback button. Be aware that a bad client
44 /// can send arbitrary data in this field.
45 pub data: Option<String>,
46
47 /// A short name of a Game to be returned, serves as the unique identifier
48 /// for the game.
49 pub game_short_name: Option<String>,
50}
51
52impl CallbackQuery {
53 /// Returns all users that are "contained" in this `CallbackQuery`
54 /// structure.
55 ///
56 /// This might be useful to track information about users.
57 /// Note that this function can return duplicate users.
58 pub fn mentioned_users(&self) -> impl Iterator<Item = &User> {
59 use crate::util::flatten;
60 use std::iter::once;
61
62 once(&self.from).chain(flatten(self.message.as_ref().map(Message::mentioned_users)))
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use crate::types::UserId;
69
70 use super::*;
71
72 #[test]
73 fn deserialize() {
74 let json = r#"{
75 "id":"id",
76 "from":{
77 "id":12345,
78 "is_bot":false,
79 "first_name":"firstName"
80 },
81 "inline_message_id":"i_m_id",
82 "chat_instance":"123456",
83 "data":"some_data",
84 "game_short_name":"game_name"
85 }"#;
86 let expected = CallbackQuery {
87 id: "id".to_string(),
88 from: User {
89 id: UserId(12345),
90 is_bot: false,
91 first_name: "firstName".to_string(),
92 last_name: None,
93 username: None,
94 language_code: None,
95 is_premium: false,
96 added_to_attachment_menu: false,
97 },
98 chat_instance: "123456".to_string(),
99 message: None,
100 inline_message_id: Some("i_m_id".to_string()),
101 data: Some("some_data".to_string()),
102 game_short_name: Some("game_name".to_string()),
103 };
104 let actual = serde_json::from_str::<CallbackQuery>(json).unwrap();
105 assert_eq!(actual, expected);
106 }
107}