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}