diff --git a/src/builder/edit_role.rs b/src/builder/edit_role.rs index 0873244c53f..dc08d753442 100644 --- a/src/builder/edit_role.rs +++ b/src/builder/edit_role.rs @@ -177,7 +177,9 @@ impl<'a> EditRole<'a> { }; if let Some(position) = self.position { - http.edit_role_position(guild_id, role.id, position, self.audit_log_reason).await?; + guild_id + .edit_role_position_with_reason(http, role.id, position, self.audit_log_reason) + .await?; } Ok(role) } diff --git a/src/http/client.rs b/src/http/client.rs index a19407e0f96..a9999e8b85a 100644 --- a/src/http/client.rs +++ b/src/http/client.rs @@ -513,7 +513,7 @@ impl Http { pub async fn create_emoji( &self, guild_id: GuildId, - map: &Value, + map: &impl serde::Serialize, audit_log_reason: Option<&str>, ) -> Result { self.fire(Request { @@ -641,7 +641,7 @@ impl Http { /// over a [`Shard`], if at least one is running. /// /// [`Shard`]: crate::gateway::Shard - pub async fn create_guild(&self, map: &Value) -> Result { + pub async fn create_guild(&self, map: &impl serde::Serialize) -> Result { self.fire(Request { body: Some(to_vec(map)?), multipart: None, @@ -680,7 +680,7 @@ impl Http { &self, guild_id: GuildId, integration_id: IntegrationId, - map: &Value, + map: &impl serde::Serialize, audit_log_reason: Option<&str>, ) -> Result<()> { self.wind(204, Request { @@ -777,7 +777,10 @@ impl Http { } /// Creates a private channel with a user. - pub async fn create_private_channel(&self, map: &Value) -> Result { + pub async fn create_private_channel( + &self, + map: &impl serde::Serialize, + ) -> Result { let body = to_vec(map)?; self.fire(Request { @@ -1492,7 +1495,7 @@ impl Http { &self, guild_id: GuildId, emoji_id: EmojiId, - map: &Value, + map: &impl serde::Serialize, audit_log_reason: Option<&str>, ) -> Result { let body = to_vec(map)?; @@ -1701,7 +1704,7 @@ impl Http { pub async fn edit_guild_mfa_level( &self, guild_id: GuildId, - value: &Value, + value: &impl serde::Serialize, audit_log_reason: Option<&str>, ) -> Result { #[derive(Deserialize)] @@ -1885,14 +1888,11 @@ impl Http { pub async fn edit_nickname( &self, guild_id: GuildId, - new_nickname: Option<&str>, + map: &impl serde::Serialize, audit_log_reason: Option<&str>, ) -> Result<()> { - let map = json!({ "nick": new_nickname }); - let body = to_vec(&map)?; - self.wind(200, Request { - body: Some(body), + body: Some(to_vec(&map)?), multipart: None, headers: audit_log_reason.map(reason_into_header), method: LightMethod::Patch, @@ -1908,13 +1908,10 @@ impl Http { pub async fn follow_news_channel( &self, news_channel_id: ChannelId, - target_channel_id: ChannelId, + map: &impl serde::Serialize, ) -> Result { - let map = json!({ "webhook_channel_id": target_channel_id }); - let body = to_vec(&map)?; - self.fire(Request { - body: Some(body), + body: Some(to_vec(&map)?), multipart: None, headers: None, method: LightMethod::Post, @@ -2025,19 +2022,12 @@ impl Http { pub async fn edit_role_position( &self, guild_id: GuildId, - role_id: RoleId, - position: i16, + map: &impl serde::Serialize, audit_log_reason: Option<&str>, ) -> Result> { - let map = json!([{ - "id": role_id, - "position": position, - }]); - let body = to_vec(&map)?; - let mut value: Value = self .fire(Request { - body: Some(body), + body: Some(to_vec(&map)?), multipart: None, headers: audit_log_reason.map(reason_into_header), method: LightMethod::Patch, diff --git a/src/model/channel/channel_id.rs b/src/model/channel/channel_id.rs index 7700fc3a7db..e005ca93d3d 100644 --- a/src/model/channel/channel_id.rs +++ b/src/model/channel/channel_id.rs @@ -343,7 +343,16 @@ impl ChannelId { http: &Http, target_channel_id: ChannelId, ) -> Result { - http.follow_news_channel(self, target_channel_id).await + #[derive(serde::Serialize)] + struct FollowChannel { + webhook_channel_id: ChannelId, + } + + let map = FollowChannel { + webhook_channel_id: target_channel_id, + }; + + http.follow_news_channel(self, &map).await } /// First attempts to retrieve the channel from the `temp_cache` if enabled, otherwise performs diff --git a/src/model/guild/guild_id.rs b/src/model/guild/guild_id.rs index 06e943c86e1..2f408e08609 100644 --- a/src/model/guild/guild_id.rs +++ b/src/model/guild/guild_id.rs @@ -3,7 +3,6 @@ use std::fmt; #[cfg(feature = "model")] use futures::stream::Stream; use nonmax::{NonMaxU16, NonMaxU8}; -use serde_json::json; #[cfg(feature = "model")] use crate::builder::{ @@ -362,12 +361,18 @@ impl GuildId { /// [`EditProfile::avatar`]: crate::builder::EditProfile::avatar /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS pub async fn create_emoji(self, http: &Http, name: &str, image: &str) -> Result { - let map = json!({ - "name": name, - "image": image, - }); + #[derive(serde::Serialize)] + struct CreateEmoji<'a> { + name: &'a str, + image: &'a str, + } - http.create_emoji(self, &map, None).await + let body = CreateEmoji { + name, + image, + }; + + http.create_emoji(self, &body, None).await } /// Creates an integration for the guild. @@ -385,12 +390,19 @@ impl GuildId { integration_id: IntegrationId, kind: &str, ) -> Result<()> { - let map = json!({ - "id": integration_id, - "type": kind, - }); + #[derive(serde::Serialize)] + struct CreateIntegration<'a> { + id: IntegrationId, + #[serde(rename = "type")] + kind: &'a str, + } - http.create_guild_integration(self, integration_id, &map, None).await + let body = CreateIntegration { + id: integration_id, + kind, + }; + + http.create_guild_integration(self, integration_id, &body, None).await } /// Creates a new role in the guild with the data set, if any. @@ -578,9 +590,14 @@ impl GuildId { /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS /// [Manage Guild Expressions]: Permissions::MANAGE_GUILD_EXPRESSIONS pub async fn edit_emoji(self, http: &Http, emoji_id: EmojiId, name: &str) -> Result { - let map = json!({ - "name": name, - }); + #[derive(serde::Serialize)] + struct EditEmoji<'a> { + name: &'a str, + } + + let map = EditEmoji { + name, + }; http.edit_emoji(self, emoji_id, &map, None).await } @@ -635,10 +652,16 @@ impl GuildId { mfa_level: MfaLevel, audit_log_reason: Option<&str>, ) -> Result { - let value = json!({ - "level": mfa_level, - }); - http.edit_guild_mfa_level(self, &value, audit_log_reason).await + #[derive(serde::Serialize)] + struct EditMfaModel { + level: MfaLevel, + } + + let map = EditMfaModel { + level: mfa_level, + }; + + http.edit_guild_mfa_level(self, &map, audit_log_reason).await } /// Edits the current user's nickname for the guild. @@ -653,7 +676,16 @@ impl GuildId { /// /// [Change Nickname]: Permissions::CHANGE_NICKNAME pub async fn edit_nickname(self, http: &Http, new_nickname: Option<&str>) -> Result<()> { - http.edit_nickname(self, new_nickname, None).await + #[derive(serde::Serialize)] + struct EditNickname<'a> { + nick: Option<&'a str>, + } + + let map = EditNickname { + nick: new_nickname, + }; + + http.edit_nickname(self, &map, None).await } /// Edits a [`Role`], optionally setting its new fields. @@ -778,7 +810,33 @@ impl GuildId { role_id: RoleId, position: i16, ) -> Result> { - http.edit_role_position(self, role_id, position, None).await + self.edit_role_position_with_reason(http, role_id, position, None).await + } + + /// Edit the position of a [`Role`] relative to all others in the [`Guild`]. + /// + /// # Errors + /// + /// See [`GuildId::edit_role_position`] for more details. + pub async fn edit_role_position_with_reason( + self, + http: &Http, + role_id: RoleId, + position: i16, + reason: Option<&str>, + ) -> Result> { + #[derive(serde::Serialize)] + struct EditRole { + id: RoleId, + position: i16, + } + + let map = EditRole { + id: role_id, + position, + }; + + http.edit_role_position(self, &map, reason).await } /// Edits the guild's welcome screen. diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs index a43f3e69d5c..c1674e0b5c4 100644 --- a/src/model/guild/mod.rs +++ b/src/model/guild/mod.rs @@ -604,12 +604,18 @@ impl Guild { /// [`Shard`]: crate::gateway::Shard /// [whitelist]: https://discord.com/developers/docs/resources/guild#create-guild pub async fn create(http: &Http, name: &str, icon: Option) -> Result { - let map = serde_json::json!({ - "icon": icon, - "name": name, - }); + #[derive(serde::Serialize)] + struct CreateGuild<'a> { + name: &'a str, + icon: Option, + } + + let body = CreateGuild { + name, + icon, + }; - http.create_guild(&map).await + http.create_guild(&body).await } /// Creates a new [`Channel`] in the guild. diff --git a/src/model/user.rs b/src/model/user.rs index 8d085dd73cd..e5a2a9966ff 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -7,8 +7,6 @@ use std::num::NonZeroU16; use std::ops::{Deref, DerefMut}; use serde::{Deserialize, Serialize}; -#[cfg(feature = "model")] -use serde_json::json; use super::prelude::*; #[cfg(feature = "model")] @@ -620,6 +618,11 @@ impl UserId { /// /// [current user]: CurrentUser pub async fn create_dm_channel(self, cache_http: impl CacheHttp) -> Result { + #[derive(serde::Serialize)] + struct CreateDmChannel { + recipient_id: UserId, + } + #[cfg(feature = "temp_cache")] if let Some(cache) = cache_http.cache() { if let Some(private_channel) = cache.temp_private_channels.get(&self) { @@ -627,11 +630,11 @@ impl UserId { } } - let map = json!({ - "recipient_id": self, - }); + let body = CreateDmChannel { + recipient_id: self, + }; - let channel = cache_http.http().create_private_channel(&map).await?; + let channel = cache_http.http().create_private_channel(&body).await?; #[cfg(feature = "temp_cache")] if let Some(cache) = cache_http.cache() {