From 894f8aa20054b78d3b4d81aeb3ed2adb481ab9a8 Mon Sep 17 00:00:00 2001 From: Michael Krasnitski Date: Thu, 16 Jun 2022 01:44:27 -0400 Subject: [PATCH] Rework CreateScheduledEvent --- src/builder/create_scheduled_event.rs | 116 +++++++++++++++++++------- src/model/guild/guild_id.rs | 23 +---- src/model/guild/mod.rs | 32 +------ 3 files changed, 92 insertions(+), 79 deletions(-) diff --git a/src/builder/create_scheduled_event.rs b/src/builder/create_scheduled_event.rs index 237e63c52f9..75c1595ba30 100644 --- a/src/builder/create_scheduled_event.rs +++ b/src/builder/create_scheduled_event.rs @@ -1,46 +1,63 @@ use std::collections::HashMap; +use crate::http::CacheHttp; #[cfg(feature = "model")] use crate::http::Http; #[cfg(feature = "model")] use crate::internal::prelude::*; -use crate::json::{json, Value}; -#[cfg(feature = "model")] -use crate::model::channel::AttachmentType; -use crate::model::guild::ScheduledEventType; -use crate::model::id::ChannelId; -use crate::model::Timestamp; +use crate::json::{self, json, Value}; +use crate::model::prelude::*; #[derive(Clone, Debug)] -pub struct CreateScheduledEvent(pub HashMap<&'static str, Value>); +pub struct CreateScheduledEvent { + id: GuildId, + map: HashMap<&'static str, Value>, +} impl CreateScheduledEvent { + /// Creates a builder with default values, setting the `privacy_level` to `GUILD_ONLY`. As this + /// is the only possible value of this field, it's only used at event creation, and we don't + /// even parse it into the `ScheduledEvent` struct. + pub(crate) fn new(id: GuildId) -> Self { + let mut map = HashMap::new(); + map.insert("privacy_level", Value::from(2)); + + Self { + id, + map, + } + } + /// Sets the channel id of the scheduled event. Required if the [`kind`] of the event is /// [`StageInstance`] or [`Voice`]. /// /// [`kind`]: CreateScheduledEvent::kind /// [`StageInstance`]: ScheduledEventType::StageInstance /// [`Voice`]: ScheduledEventType::Voice - pub fn channel_id>(&mut self, channel_id: C) -> &mut Self { - self.0.insert("channel_id", Value::from(channel_id.into().0)); + #[must_use] + pub fn channel_id>(mut self, channel_id: C) -> Self { + self.map.insert("channel_id", Value::from(channel_id.into().0)); self } /// Sets the name of the scheduled event. Required to be set for event creation. - pub fn name(&mut self, name: impl Into) -> &mut Self { - self.0.insert("name", Value::String(name.into())); + #[must_use] + pub fn name(mut self, name: impl Into) -> Self { + self.map.insert("name", Value::String(name.into())); self } /// Sets the description of the scheduled event. - pub fn description(&mut self, description: impl Into) -> &mut Self { - self.0.insert("description", Value::String(description.into())); + #[must_use] + pub fn description(mut self, description: impl Into) -> Self { + self.map.insert("description", Value::String(description.into())); self } /// Sets the start time of the scheduled event. Required to be set for event creation. #[inline] - pub fn start_time>(&mut self, timestamp: T) -> &mut Self { + #[must_use] + pub fn start_time>(mut self, timestamp: T) -> Self { self._timestamp("scheduled_start_time", timestamp.into()); self } @@ -51,18 +68,20 @@ impl CreateScheduledEvent { /// [`kind`]: CreateScheduledEvent::kind /// [`External`]: ScheduledEventType::External #[inline] - pub fn end_time>(&mut self, timestamp: T) -> &mut Self { + #[must_use] + pub fn end_time>(mut self, timestamp: T) -> Self { self._timestamp("scheduled_end_time", timestamp.into()); self } fn _timestamp(&mut self, field: &'static str, timestamp: Timestamp) { - self.0.insert(field, Value::from(timestamp.to_string())); + self.map.insert(field, Value::from(timestamp.to_string())); } /// Sets the entity type of the scheduled event. Required to be set for event creation. - pub fn kind(&mut self, kind: ScheduledEventType) -> &mut Self { - self.0.insert("entity_type", Value::from(kind.num())); + #[must_use] + pub fn kind(mut self, kind: ScheduledEventType) -> Self { + self.map.insert("entity_type", Value::from(kind.num())); self } @@ -71,11 +90,12 @@ impl CreateScheduledEvent { /// /// [`kind`]: CreateScheduledEvent::kind /// [`External`]: ScheduledEventType::External - pub fn location(&mut self, location: impl Into) -> &mut Self { + #[must_use] + pub fn location(mut self, location: impl Into) -> Self { let obj = json!({ "location": location.into(), }); - self.0.insert("entity_metadata", obj); + self.map.insert("entity_metadata", obj); self } @@ -87,25 +107,57 @@ impl CreateScheduledEvent { /// on a path that doesn't exist. #[cfg(feature = "model")] pub async fn image<'a>( - &mut self, + mut self, http: impl AsRef, image: impl Into>, - ) -> Result<&mut Self> { + ) -> Result { let image_data = image.into().data(&http.as_ref().client).await?; let image_string = format!("data:image/png;base64,{}", base64::encode(image_data)); - self.0.insert("image", Value::from(image_string)); + self.map.insert("image", Value::from(image_string)); Ok(self) } -} -impl Default for CreateScheduledEvent { - /// Creates a builder with default values, setting the `privacy_level` to `GUILD_ONLY`. As this - /// is the only possible value of this field, it's only used at event creation, and we don't - /// even parse it into the `ScheduledEvent` struct. - fn default() -> Self { - let mut map = HashMap::new(); - map.insert("privacy_level", Value::from(2)); + /// Creates a new scheduled event in the guild with the data set, if any. + /// + /// **Note**: Requres the [Manage Events] permission. + /// + /// # Errors + /// + /// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given. + /// + /// [Manage Events]: Permissions::MANAGE_EVENTS + pub async fn execute(self, http: impl AsRef) -> Result { + let map = json::hashmap_to_json_map(self.map); + + http.as_ref().create_scheduled_event(self.id.into(), &map, None).await + } + + /// Creates a new scheduled event in the guild with the data set, if any. + /// + /// **Note**: Requres the [Manage Events] permission. + /// + /// # Errors + /// + /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user + /// does not have permission to manage scheduled events. + /// + /// Otherwise will return [`Error::Http`] if the current user does not have permission. + /// + /// [Manage Events]: Permissions::MANAGE_EVENTS + pub async fn execute_with_cache(self, cache_http: impl CacheHttp) -> Result { + #[cfg(feature = "cache")] + { + if let Some(cache) = cache_http.cache() { + if let Some(guild) = cache.guild(self.id) { + let req = Permissions::MANAGE_EVENTS; + + if !guild.has_perms(&cache_http, req).await { + return Err(Error::Model(ModelError::InvalidPermissions(req))); + } + } + } + } - CreateScheduledEvent(map) + self.execute(cache_http.http()).await } } diff --git a/src/model/guild/guild_id.rs b/src/model/guild/guild_id.rs index 839a8bf3381..8cdbb7c390f 100644 --- a/src/model/guild/guild_id.rs +++ b/src/model/guild/guild_id.rs @@ -332,29 +332,14 @@ impl GuildId { Ok(role) } - /// Creates a new scheduled event in the guild with the data set, if any. + /// Returns a request builder that, when executed, will create a new scheduled event in the + /// guild. /// /// **Note**: Requres the [Manage Events] permission. /// - /// # Errors - /// - /// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given. - /// /// [Manage Events]: Permissions::MANAGE_EVENTS - pub async fn create_scheduled_event( - &self, - http: impl AsRef, - f: F, - ) -> Result - where - F: FnOnce(&mut CreateScheduledEvent) -> &mut CreateScheduledEvent, - { - let mut builder = CreateScheduledEvent::default(); - f(&mut builder); - - let map = json::hashmap_to_json_map(builder.0); - - http.as_ref().create_scheduled_event(self.0, &map, None).await + pub async fn create_scheduled_event(&self) -> CreateScheduledEvent { + CreateScheduledEvent::new(*self) } /// Returns a request builder that, when executed, will create a new sticker in the guild. diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs index 78e71487d4f..cbe7ff04d31 100644 --- a/src/model/guild/mod.rs +++ b/src/model/guild/mod.rs @@ -874,38 +874,14 @@ impl Guild { self.id.create_role(cache_http.http(), f).await } - /// Creates a new scheduled event in the guild with the data set, if any. + /// Returns a request builder that, when executed, will create a new scheduled event in the + /// guild. /// /// **Note**: Requres the [Manage Events] permission. /// - /// # Errors - /// - /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user - /// does not have permission to manage scheduled events. - /// - /// Otherwise will return [`Error::Http`] if the current user does not have permission. - /// /// [Manage Events]: Permissions::MANAGE_EVENTS - pub async fn create_scheduled_event( - &self, - cache_http: impl CacheHttp, - f: F, - ) -> Result - where - F: FnOnce(&mut CreateScheduledEvent) -> &mut CreateScheduledEvent, - { - #[cfg(feature = "cache")] - { - if cache_http.cache().is_some() { - let req = Permissions::MANAGE_EVENTS; - - if !self.has_perms(&cache_http, req).await { - return Err(Error::Model(ModelError::InvalidPermissions(req))); - } - } - } - - self.id.create_scheduled_event(cache_http.http(), f).await + pub async fn create_scheduled_event(&self) -> CreateScheduledEvent { + CreateScheduledEvent::new(self.id) } /// Returns a request builder that, when executed, will create a new sticker in the guild.