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: u8,
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: u8::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 let hours = duration.as_secs() / 3600;
121
122 CreatePoll {
123 question: self.question,
124 answers: self.answers,
125 duration: hours.try_into().unwrap_or(168),
126 allow_multiselect: self.allow_multiselect,
127 layout_type: self.layout_type,
128 _stage: Ready,
129 }
130 }
131}
132
133impl<Stage: Sealed> CreatePoll<Stage> {
134 pub fn layout_type(mut self, layout_type: PollLayoutType) -> Self {
138 self.layout_type = Some(layout_type);
139 self
140 }
141
142 pub fn allow_multiselect(mut self) -> Self {
144 self.allow_multiselect = true;
145 self
146 }
147}
148
149#[derive(serde::Serialize, Clone, Debug, Default)]
150#[must_use = "Builders do nothing unless built"]
151pub struct CreatePollAnswer {
152 poll_media: PollMedia,
153}
154
155impl CreatePollAnswer {
156 pub fn new() -> Self {
160 Self::default()
161 }
162
163 pub fn text(mut self, text: impl Into<String>) -> Self {
164 self.poll_media.text = Some(text.into());
165 self
166 }
167
168 pub fn emoji(mut self, emoji: impl Into<PollMediaEmoji>) -> Self {
169 self.poll_media.emoji = Some(emoji.into());
170 self
171 }
172}