serenity/builder/
create_poll.rs1use crate::model::channel::{PollLayoutType, PollMedia, PollMediaEmoji};
2
3#[derive(serde::Serialize, Clone, Debug)]
4pub struct NeedsQuestion;
5#[derive(serde::Serialize, Clone, Debug)]
6pub struct NeedsAnswers;
7#[derive(serde::Serialize, Clone, Debug)]
8pub struct NeedsDuration;
9#[derive(serde::Serialize, Clone, Debug)]
10pub struct Ready;
11
12mod sealed {
13 use super::*;
14
15 pub trait Sealed {}
16
17 impl Sealed for NeedsQuestion {}
18 impl Sealed for NeedsAnswers {}
19 impl Sealed for NeedsDuration {}
20 impl Sealed for Ready {}
21}
22
23use sealed::*;
24
25#[derive(serde::Serialize, Clone, Debug)]
27struct CreatePollMedia {
28 text: String,
29}
30
31#[derive(serde::Serialize, Clone, Debug)]
32#[must_use = "Builders do nothing unless built"]
33pub struct CreatePoll<Stage: Sealed> {
34 question: CreatePollMedia,
35 answers: Vec<CreatePollAnswer>,
36 duration: u16,
37 allow_multiselect: bool,
38 layout_type: Option<PollLayoutType>,
39
40 #[serde(skip)]
41 _stage: Stage,
42}
43
44impl Default for CreatePoll<NeedsQuestion> {
45 fn default() -> Self {
47 Self {
50 question: CreatePollMedia {
51 text: String::default(),
52 },
53 answers: Vec::default(),
54 duration: u16::default(),
55 allow_multiselect: false,
56 layout_type: None,
57
58 _stage: NeedsQuestion,
59 }
60 }
61}
62
63impl CreatePoll<NeedsQuestion> {
64 pub fn new() -> Self {
83 Self::default()
84 }
85
86 pub fn question(self, text: impl Into<String>) -> CreatePoll<NeedsAnswers> {
88 CreatePoll {
89 question: CreatePollMedia {
90 text: text.into(),
91 },
92 answers: self.answers,
93 duration: self.duration,
94 allow_multiselect: self.allow_multiselect,
95 layout_type: self.layout_type,
96 _stage: NeedsAnswers,
97 }
98 }
99}
100
101impl CreatePoll<NeedsAnswers> {
102 pub fn answers(self, answers: Vec<CreatePollAnswer>) -> CreatePoll<NeedsDuration> {
104 CreatePoll {
105 question: self.question,
106 answers,
107 duration: self.duration,
108 allow_multiselect: self.allow_multiselect,
109 layout_type: self.layout_type,
110 _stage: NeedsDuration,
111 }
112 }
113}
114
115impl CreatePoll<NeedsDuration> {
116 pub fn duration(self, duration: std::time::Duration) -> CreatePoll<Ready> {
120 const DAYS_32: u16 = 768;
121
122 let hours = duration.as_secs() / 3600;
123
124 CreatePoll {
125 question: self.question,
126 answers: self.answers,
127 duration: hours.try_into().unwrap_or(DAYS_32),
128 allow_multiselect: self.allow_multiselect,
129 layout_type: self.layout_type,
130 _stage: Ready,
131 }
132 }
133}
134
135impl<Stage: Sealed> CreatePoll<Stage> {
136 pub fn layout_type(mut self, layout_type: PollLayoutType) -> Self {
140 self.layout_type = Some(layout_type);
141 self
142 }
143
144 pub fn allow_multiselect(mut self) -> Self {
146 self.allow_multiselect = true;
147 self
148 }
149}
150
151#[derive(serde::Serialize, Clone, Debug, Default)]
152#[must_use = "Builders do nothing unless built"]
153pub struct CreatePollAnswer {
154 poll_media: PollMedia,
155}
156
157impl CreatePollAnswer {
158 pub fn new() -> Self {
162 Self::default()
163 }
164
165 pub fn text(mut self, text: impl Into<String>) -> Self {
166 self.poll_media.text = Some(text.into());
167 self
168 }
169
170 pub fn emoji(mut self, emoji: impl Into<PollMediaEmoji>) -> Self {
171 self.poll_media.emoji = Some(emoji.into());
172 self
173 }
174}