telegram_bot_raw/requests/
send_poll.rs

1use std::borrow::Cow;
2use std::clone::Clone;
3use std::ops::Not;
4
5use crate::requests::*;
6use crate::types::*;
7
8/// Use this method to send polls.
9#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
10#[must_use = "requests do nothing unless sent"]
11pub struct SendPoll<'q, 'o, 'e> {
12    chat_id: ChatRef,
13    question: Cow<'q, str>,
14    options: Vec<Cow<'o, str>>,
15    #[serde(skip_serializing_if = "Clone::clone")]
16    // This defaults to true, so don't skip serializing if false.
17    is_anonymous: bool,
18    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
19    type_: Option<PollType>,
20    #[serde(skip_serializing_if = "Not::not")]
21    allows_multiple_answers: bool,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    // TODO: required for quiz polls
24    correct_option_id: Option<Integer>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    explanation: Option<Cow<'e, str>>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    explanation_parse_mode: Option<ParseMode>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    open_period: Option<Integer>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    close_date: Option<Integer>,
33    #[serde(skip_serializing_if = "Not::not")]
34    is_closed: bool,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    reply_to_message_id: Option<MessageId>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    reply_markup: Option<ReplyMarkup>,
39}
40
41impl<'q, 'o, 'e> Request for SendPoll<'q, 'o, 'e> {
42    type Type = JsonRequestType<Self>;
43    type Response = JsonIdResponse<MessageOrChannelPost>;
44
45    fn serialize(&self) -> Result<HttpRequest, Error> {
46        Self::Type::serialize(RequestUrl::method("sendPoll"), self)
47    }
48}
49
50impl<'q, 'o, 'e> SendPoll<'q, 'o, 'e> {
51    // TODO: allow creating requests only with at least 2 options
52    pub fn new<C, Q, O>(chat: C, question: Q, options: Vec<O>) -> Self
53    where
54        C: ToChatRef,
55        Q: Into<Cow<'q, str>>,
56        O: Into<Cow<'o, str>>,
57    {
58        let mut req_options: Vec<Cow<'o, str>> = Vec::new();
59
60        for option in options {
61            req_options.push(option.into());
62        }
63
64        SendPoll {
65            chat_id: chat.to_chat_ref(),
66            question: question.into(),
67            options: req_options,
68            is_anonymous: true,
69            type_: None,
70            allows_multiple_answers: false,
71            correct_option_id: None,
72            explanation: None,
73            explanation_parse_mode: None,
74            open_period: None,
75            close_date: None,
76            is_closed: false,
77            reply_to_message_id: None,
78            reply_markup: None,
79        }
80    }
81
82    pub fn add_option<O>(&mut self, option: O) -> &mut Self
83    where
84        O: Into<Cow<'o, str>>,
85    {
86        self.options.push(option.into());
87        self
88    }
89
90    pub fn not_anonymous(&mut self) -> &mut Self {
91        self.is_anonymous = false;
92        self
93    }
94
95    pub fn quiz(&mut self) -> &mut Self {
96        self.type_ = Some(PollType::Quiz);
97        self
98    }
99
100    pub fn regular(&mut self) -> &mut Self {
101        self.type_ = Some(PollType::Regular);
102        self
103    }
104
105    pub fn allows_multiple_answers(&mut self) -> &mut Self {
106        self.allows_multiple_answers = true;
107        self
108    }
109
110    pub fn correct_option_id(&mut self, id: Integer) -> &mut Self {
111        self.correct_option_id = Some(id);
112        self
113    }
114
115    pub fn explanation<E>(&mut self, text: E) -> &mut Self
116    where
117        E: Into<Cow<'e, str>>,
118    {
119        self.explanation = Some(text.into());
120        self
121    }
122
123    pub fn explanation_parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
124        self.explanation_parse_mode = Some(parse_mode);
125        self
126    }
127
128    pub fn open_period(&mut self, period: Integer) -> &mut Self {
129        self.open_period = Some(period);
130        self
131    }
132
133    // TODO: some real date format?
134    pub fn close_date(&mut self, date: Integer) -> &mut Self {
135        self.close_date = Some(date);
136        self
137    }
138
139    pub fn closed(&mut self) -> &mut Self {
140        self.is_closed = true;
141        self
142    }
143
144    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
145    where
146        R: ToMessageId,
147    {
148        self.reply_to_message_id = Some(to.to_message_id());
149        self
150    }
151
152    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
153    where
154        R: Into<ReplyMarkup>,
155    {
156        self.reply_markup = Some(reply_markup.into());
157        self
158    }
159}
160
161/// Send message with a poll.
162pub trait CanSendPoll {
163    fn poll<'q, 'o, 'e, Q, O>(&self, question: Q, options: Vec<O>) -> SendPoll<'q, 'o, 'e>
164    where
165        Q: Into<Cow<'q, str>>,
166        O: Into<Cow<'o, str>>;
167}
168
169impl<C> CanSendPoll for C
170where
171    C: ToChatRef,
172{
173    fn poll<'q, 'o, 'e, Q, O>(&self, question: Q, options: Vec<O>) -> SendPoll<'q, 'o, 'e>
174    where
175        Q: Into<Cow<'q, str>>,
176        O: Into<Cow<'o, str>>,
177    {
178        SendPoll::new(self, question, options)
179    }
180}
181
182pub trait CanReplySendPoll {
183    fn poll_reply<'q, 'o, 'e, Q, O>(&self, question: Q, options: Vec<O>) -> SendPoll<'q, 'o, 'e>
184    where
185        Q: Into<Cow<'q, str>>,
186        O: Into<Cow<'o, str>>;
187}
188
189impl<M> CanReplySendPoll for M
190where
191    M: ToMessageId + ToSourceChat,
192{
193    fn poll_reply<'q, 'o, 'e, Q, O>(&self, question: Q, options: Vec<O>) -> SendPoll<'q, 'o, 'e>
194    where
195        Q: Into<Cow<'q, str>>,
196        O: Into<Cow<'o, str>>,
197    {
198        let mut rq = self.to_source_chat().poll(question, options);
199        rq.reply_to(self.to_message_id());
200        rq
201    }
202}