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