Skip to main content

rustigram_types/
poll.rs

1use serde::{Deserialize, Serialize};
2
3use crate::chat::Chat;
4use crate::message::MessageEntity;
5use crate::user::User;
6
7/// A native Telegram poll or quiz.
8///
9/// Polls are either `regular` (users vote freely) or `quiz` (one or more correct
10/// answers). Returned inside [`Message`](crate::message::Message) when a poll is
11/// sent or forwarded.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Poll {
14    /// Unique poll identifier.
15    pub id: String,
16    /// Poll question (1–300 characters).
17    pub question: String,
18    /// Special entities in the question.
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub question_entities: Option<Vec<MessageEntity>>,
21    /// List of answer options.
22    pub options: Vec<PollOption>,
23    /// Total number of users who voted.
24    pub total_voter_count: u32,
25    /// `true` if the poll is closed.
26    pub is_closed: bool,
27    /// `true` if the poll is anonymous.
28    pub is_anonymous: bool,
29    /// Poll type.
30    #[serde(rename = "type")]
31    pub kind: PollType,
32    /// `true` if the poll allows multiple answers.
33    pub allows_multiple_answers: bool,
34    /// `true` if voters can change their chosen answer options.
35    pub allows_revoting: bool,
36    /// Zero-based indices of the correct answers (quiz polls only).
37    ///
38    /// Bot API 9.6 changed this from a single `u8` to an array to support
39    /// quizzes with multiple correct answers.
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub correct_option_ids: Option<Vec<u8>>,
42    /// Explanation shown after a quiz is answered.
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub explanation: Option<String>,
45    /// Special entities in the explanation.
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub explanation_entities: Option<Vec<MessageEntity>>,
48    /// Duration in seconds the poll stays active after creation.
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub open_period: Option<u32>,
51    /// Unix timestamp when the poll closes automatically.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub close_date: Option<i64>,
54    /// Description of the poll; present only inside `Message` objects.
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub description: Option<String>,
57    /// Special entities in the description.
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub description_entities: Option<Vec<MessageEntity>>,
60}
61
62/// One option in a [`Poll`].
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct PollOption {
65    /// Persistent identifier of this option, stable across poll edits.
66    pub persistent_id: String,
67    /// Option text (1–100 characters).
68    pub text: String,
69    /// Special entities in the option text.
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub text_entities: Option<Vec<MessageEntity>>,
72    /// Number of users who voted for this option.
73    pub voter_count: u32,
74    /// The user who added this option, if applicable.
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub added_by_user: Option<User>,
77    /// The chat that added this option, if applicable.
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub added_by_chat: Option<Chat>,
80    /// Unix timestamp when this option was added; absent if it existed at poll creation.
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub addition_date: Option<i64>,
83}
84
85/// An option to include when creating a poll with `sendPoll`.
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct InputPollOption {
88    /// Option text (1–100 characters).
89    pub text: String,
90    /// Parse mode for the option text.
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub text_parse_mode: Option<crate::message::ParseMode>,
93    /// Special entities in the option text; alternative to `text_parse_mode`.
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub text_entities: Option<Vec<MessageEntity>>,
96}
97
98impl InputPollOption {
99    /// Creates a new `InputPollOption` with the given text.
100    pub fn new(text: impl Into<String>) -> Self {
101        Self {
102            text: text.into(),
103            text_parse_mode: None,
104            text_entities: None,
105        }
106    }
107}
108
109/// The type of a poll.
110#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
111#[serde(rename_all = "snake_case")]
112pub enum PollType {
113    /// A regular poll where users can vote freely.
114    Regular,
115    /// A quiz with one or more correct answers.
116    Quiz,
117}
118
119/// An answer submitted by a user in a non-anonymous poll.
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct PollAnswer {
122    /// Unique poll identifier.
123    pub poll_id: String,
124    /// The chat that changed the answer (for anonymous polls in groups).
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub voter_chat: Option<Chat>,
127    /// The user who changed the answer (for non-anonymous polls).
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub user: Option<User>,
130    /// Zero-based indices of the chosen options; empty if the vote was retracted.
131    pub option_ids: Vec<u8>,
132    /// Persistent identifiers of the chosen options; empty if the vote was retracted.
133    pub option_persistent_ids: Vec<String>,
134}
135
136/// Service message: a new option was added to a poll.
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct PollOptionAdded {
139    /// Message containing the poll to which the option was added.
140    ///
141    /// Uses `serde_json::Value` because the API returns a `MaybeInaccessibleMessage`
142    /// union type here. Will not contain `reply_to_message`.
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub poll_message: Option<serde_json::Value>,
145    /// Persistent identifier of the added option.
146    pub option_persistent_id: String,
147    /// Text of the added option.
148    pub option_text: String,
149    /// Special entities in the option text.
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub option_text_entities: Option<Vec<MessageEntity>>,
152}
153
154/// Service message: an option was deleted from a poll.
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct PollOptionDeleted {
157    /// Message containing the poll from which the option was deleted.
158    ///
159    /// Uses `serde_json::Value` because the API returns a `MaybeInaccessibleMessage`
160    /// union type here. Will not contain `reply_to_message`.
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub poll_message: Option<serde_json::Value>,
163    /// Persistent identifier of the deleted option.
164    pub option_persistent_id: String,
165    /// Text of the deleted option.
166    pub option_text: String,
167    /// Special entities in the option text.
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub option_text_entities: Option<Vec<MessageEntity>>,
170}