use crate::model::channel::{PollLayoutType, PollMedia, PollMediaEmoji};
#[derive(serde::Serialize, Clone, Debug)]
pub struct NeedsQuestion;
#[derive(serde::Serialize, Clone, Debug)]
pub struct NeedsAnswers;
#[derive(serde::Serialize, Clone, Debug)]
pub struct NeedsDuration;
#[derive(serde::Serialize, Clone, Debug)]
pub struct Ready;
mod sealed {
use super::*;
pub trait Sealed {}
impl Sealed for NeedsQuestion {}
impl Sealed for NeedsAnswers {}
impl Sealed for NeedsDuration {}
impl Sealed for Ready {}
}
use sealed::*;
#[derive(serde::Serialize, Clone, Debug)]
struct CreatePollMedia {
text: String,
}
#[derive(serde::Serialize, Clone, Debug)]
#[must_use = "Builders do nothing unless built"]
pub struct CreatePoll<Stage: Sealed> {
question: CreatePollMedia,
answers: Vec<CreatePollAnswer>,
duration: u16,
allow_multiselect: bool,
layout_type: Option<PollLayoutType>,
#[serde(skip)]
_stage: Stage,
}
impl Default for CreatePoll<NeedsQuestion> {
fn default() -> Self {
Self {
question: CreatePollMedia {
text: String::default(),
},
answers: Vec::default(),
duration: u16::default(),
allow_multiselect: false,
layout_type: None,
_stage: NeedsQuestion,
}
}
}
impl CreatePoll<NeedsQuestion> {
pub fn new() -> Self {
Self::default()
}
pub fn question(self, text: impl Into<String>) -> CreatePoll<NeedsAnswers> {
CreatePoll {
question: CreatePollMedia {
text: text.into(),
},
answers: self.answers,
duration: self.duration,
allow_multiselect: self.allow_multiselect,
layout_type: self.layout_type,
_stage: NeedsAnswers,
}
}
}
impl CreatePoll<NeedsAnswers> {
pub fn answers(self, answers: Vec<CreatePollAnswer>) -> CreatePoll<NeedsDuration> {
CreatePoll {
question: self.question,
answers,
duration: self.duration,
allow_multiselect: self.allow_multiselect,
layout_type: self.layout_type,
_stage: NeedsDuration,
}
}
}
impl CreatePoll<NeedsDuration> {
pub fn duration(self, duration: std::time::Duration) -> CreatePoll<Ready> {
const DAYS_32: u16 = 768;
let hours = duration.as_secs() / 3600;
CreatePoll {
question: self.question,
answers: self.answers,
duration: hours.try_into().unwrap_or(DAYS_32),
allow_multiselect: self.allow_multiselect,
layout_type: self.layout_type,
_stage: Ready,
}
}
}
impl<Stage: Sealed> CreatePoll<Stage> {
pub fn layout_type(mut self, layout_type: PollLayoutType) -> Self {
self.layout_type = Some(layout_type);
self
}
pub fn allow_multiselect(mut self) -> Self {
self.allow_multiselect = true;
self
}
}
#[derive(serde::Serialize, Clone, Debug, Default)]
#[must_use = "Builders do nothing unless built"]
pub struct CreatePollAnswer {
poll_media: PollMedia,
}
impl CreatePollAnswer {
pub fn new() -> Self {
Self::default()
}
pub fn text(mut self, text: impl Into<String>) -> Self {
self.poll_media.text = Some(text.into());
self
}
pub fn emoji(mut self, emoji: impl Into<PollMediaEmoji>) -> Self {
self.poll_media.emoji = Some(emoji.into());
self
}
}