Skip to main content

twilight_http/request/scheduled_event/create_guild_scheduled_event/
mod.rs

1mod external;
2mod stage_instance;
3mod voice;
4
5pub use self::{
6    external::CreateGuildExternalScheduledEvent,
7    stage_instance::CreateGuildStageInstanceScheduledEvent, voice::CreateGuildVoiceScheduledEvent,
8};
9
10use super::EntityMetadataFields;
11#[cfg(not(target_os = "wasi"))]
12use crate::response::ResponseFuture;
13use crate::{
14    client::Client,
15    error::Error,
16    request::{AuditLogReason, Request},
17    routing::Route,
18};
19use serde::Serialize;
20use twilight_model::{
21    guild::scheduled_event::{EntityType, GuildScheduledEvent, PrivacyLevel},
22    id::{
23        Id,
24        marker::{ChannelMarker, GuildMarker},
25    },
26    util::Timestamp,
27};
28use twilight_validate::request::{
29    ValidationError, audit_reason as validate_audit_reason,
30    scheduled_event_name as validate_scheduled_event_name,
31};
32
33#[derive(Serialize)]
34struct CreateGuildScheduledEventFields<'a> {
35    #[serde(skip_serializing_if = "Option::is_none")]
36    channel_id: Option<Id<ChannelMarker>>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    description: Option<&'a str>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    entity_metadata: Option<EntityMetadataFields<'a>>,
41    #[serde(skip_serializing_if = "Option::is_none")]
42    entity_type: Option<EntityType>,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    image: Option<&'a str>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    name: Option<&'a str>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    privacy_level: Option<PrivacyLevel>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    scheduled_end_time: Option<&'a Timestamp>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    scheduled_start_time: Option<&'a Timestamp>,
53}
54
55/// Create a scheduled event in a guild.
56///
57/// Once a guild is selected, you must choose one of three event types to
58/// create. The request builders will ensure you provide the correct data to
59/// Discord. See [Discord Docs/Create Guild Schedule Event].
60///
61/// The name must be between 1 and 100 characters in length. For external
62/// events, the location must be between 1 and 100 characters in length.
63///
64/// # Examples
65///
66/// Create an event in a stage instance:
67///
68/// ```no_run
69/// # use twilight_http::Client;
70/// use twilight_model::{guild::scheduled_event::PrivacyLevel, id::Id, util::Timestamp};
71/// # #[tokio::main]
72/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
73/// # let client = Client::new("token".to_owned());
74/// let guild_id = Id::new(1);
75/// let channel_id = Id::new(2);
76/// let garfield_start_time = Timestamp::parse("2022-01-01T14:00:00+00:00")?;
77///
78/// client
79///     .create_guild_scheduled_event(guild_id, PrivacyLevel::GuildOnly)
80///     .stage_instance(
81///         channel_id,
82///         "Garfield Appreciation Hour",
83///         &garfield_start_time,
84///     )
85///     .description("Discuss: How important is Garfield to You?")
86///     .await?;
87/// # Ok(()) }
88/// ```
89///
90/// Create an external event:
91///
92/// ```no_run
93/// # use twilight_http::Client;
94/// use twilight_model::{guild::scheduled_event::PrivacyLevel, id::Id, util::Timestamp};
95/// # #[tokio::main]
96/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
97/// # let client = Client::new("token".to_owned());
98/// let guild_id = Id::new(1);
99/// let garfield_con_start_time = Timestamp::parse("2022-01-04T08:00:00+00:00")?;
100/// let garfield_con_end_time = Timestamp::parse("2022-01-06T17:00:00+00:00")?;
101///
102/// client
103///     .create_guild_scheduled_event(guild_id, PrivacyLevel::GuildOnly)
104///     .external(
105///         "Garfield Con 2022",
106///         "Baltimore Convention Center",
107///         &garfield_con_start_time,
108///         &garfield_con_end_time,
109///     )
110///     .description(
111///         "In a spiritual successor to BronyCon, Garfield fans from \
112/// around the globe celebrate all things related to the loveable cat.",
113///     )
114///     .await?;
115/// # Ok(()) }
116/// ```
117///
118/// [Discord Docs/Create Guild Scheduled Event]: https://discord.com/developers/docs/resources/guild-scheduled-event#create-guild-scheduled-event
119pub struct CreateGuildScheduledEvent<'a> {
120    guild_id: Id<GuildMarker>,
121    http: &'a Client,
122    fields: Result<CreateGuildScheduledEventFields<'a>, ValidationError>,
123    reason: Result<Option<&'a str>, ValidationError>,
124}
125
126impl<'a> CreateGuildScheduledEvent<'a> {
127    pub(crate) const fn new(
128        http: &'a Client,
129        guild_id: Id<GuildMarker>,
130        privacy_level: PrivacyLevel,
131    ) -> Self {
132        Self {
133            guild_id,
134            http,
135            fields: Ok(CreateGuildScheduledEventFields {
136                channel_id: None,
137                description: None,
138                entity_metadata: None,
139                entity_type: None,
140                image: None,
141                name: None,
142                privacy_level: Some(privacy_level),
143                scheduled_end_time: None,
144                scheduled_start_time: None,
145            }),
146            reason: Ok(None),
147        }
148    }
149
150    /// Create an external scheduled event in a guild.
151    ///
152    /// The name must be between 1 and 100 characters in length.
153    ///
154    /// # Errors
155    ///
156    /// Returns an error of type [`ScheduledEventName`] if the name is invalid.
157    ///
158    /// [`ScheduledEventName`]: twilight_validate::request::ValidationErrorType::ScheduledEventName
159    pub fn external(
160        mut self,
161        name: &'a str,
162        location: &'a str,
163        scheduled_start_time: &'a Timestamp,
164        scheduled_end_time: &'a Timestamp,
165    ) -> CreateGuildExternalScheduledEvent<'a> {
166        self.fields = self.fields.and_then(|mut fields| {
167            validate_scheduled_event_name(name)?;
168
169            fields.name.replace(name);
170
171            Ok(fields)
172        });
173
174        CreateGuildExternalScheduledEvent::new(
175            self,
176            name,
177            location,
178            scheduled_start_time,
179            scheduled_end_time,
180        )
181    }
182
183    /// Create a stage instance scheduled event in a guild.
184    ///
185    /// The name must be between 1 and 100 characters in length.
186    ///
187    /// # Errors
188    ///
189    /// Returns an error of type [`ScheduledEventName`] if the name is invalid.
190    ///
191    /// [`ScheduledEventName`]: twilight_validate::request::ValidationErrorType::ScheduledEventName
192    pub fn stage_instance(
193        mut self,
194        channel_id: Id<ChannelMarker>,
195        name: &'a str,
196        scheduled_start_time: &'a Timestamp,
197    ) -> CreateGuildStageInstanceScheduledEvent<'a> {
198        self.fields = self.fields.and_then(|mut fields| {
199            validate_scheduled_event_name(name)?;
200            fields.name.replace(name);
201
202            Ok(fields)
203        });
204
205        CreateGuildStageInstanceScheduledEvent::new(self, channel_id, name, scheduled_start_time)
206    }
207
208    /// Create a voice channel scheduled event in a guild.
209    ///
210    /// The name must be between 1 and 100 characters in length.
211    ///
212    /// # Errors
213    ///
214    /// Returns an error of type [`ScheduledEventName`] if the name is invalid.
215    ///
216    /// [`ScheduledEventName`]: twilight_validate::request::ValidationErrorType::ScheduledEventName
217    pub fn voice(
218        mut self,
219        channel_id: Id<ChannelMarker>,
220        name: &'a str,
221        scheduled_start_time: &'a Timestamp,
222    ) -> CreateGuildVoiceScheduledEvent<'a> {
223        self.fields = self.fields.and_then(|mut fields| {
224            validate_scheduled_event_name(name)?;
225            fields.name.replace(name);
226
227            Ok(fields)
228        });
229
230        CreateGuildVoiceScheduledEvent::new(self, channel_id, name, scheduled_start_time)
231    }
232
233    #[cfg(not(target_os = "wasi"))]
234    fn exec(self) -> ResponseFuture<GuildScheduledEvent> {
235        let http = self.http;
236
237        match self.try_into_request() {
238            Ok(request) => http.request(request),
239            Err(source) => ResponseFuture::error(source),
240        }
241    }
242
243    fn try_into_request(self) -> Result<Request, Error> {
244        let fields = self.fields.map_err(Error::validation)?;
245
246        Request::builder(&Route::CreateGuildScheduledEvent {
247            guild_id: self.guild_id.get(),
248        })
249        .json(&fields)
250        .build()
251    }
252}
253
254impl<'a> AuditLogReason<'a> for CreateGuildScheduledEvent<'a> {
255    fn reason(mut self, reason: &'a str) -> Self {
256        self.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
257
258        self
259    }
260}