Skip to content

Commit 18349f7

Browse files
authored
Add HTTP soundboard support (#3374)
Adds support for [Soundboard sounds][soundboard]. This only adds the models and HTTP endpoints, as there are also gateway events. [soundboard]: https://discord.com/developers/docs/resources/soundboard
1 parent 5bfce60 commit 18349f7

File tree

12 files changed

+680
-0
lines changed

12 files changed

+680
-0
lines changed

src/builder/create_soundboard.rs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#[cfg(feature = "http")]
2+
use super::Builder;
3+
use super::CreateAttachment;
4+
#[cfg(feature = "http")]
5+
use crate::http::CacheHttp;
6+
#[cfg(feature = "http")]
7+
use crate::internal::prelude::*;
8+
use crate::model::prelude::*;
9+
10+
/// A builder to create a soundboard sound.
11+
///
12+
/// [Discord docs](https://discord.com/developers/docs/resources/soundboard#soundboard-resource)
13+
#[derive(Clone, Debug)]
14+
#[must_use]
15+
pub struct CreateSoundboard<'a> {
16+
name: String,
17+
sound: String,
18+
volume: f64,
19+
emoji_id: Option<EmojiId>,
20+
emoji_name: Option<String>,
21+
audit_log_reason: Option<&'a str>,
22+
}
23+
24+
impl<'a> CreateSoundboard<'a> {
25+
/// Creates a new builder with the given data.
26+
pub fn new(name: impl Into<String>, sound: &CreateAttachment) -> Self {
27+
Self {
28+
name: name.into(),
29+
sound: sound.to_base64(),
30+
volume: 1.0,
31+
emoji_id: None,
32+
emoji_name: None,
33+
audit_log_reason: None,
34+
}
35+
}
36+
37+
/// Set the name of the soundboard sound, replacing the current value as set in [`Self::new`].
38+
///
39+
/// **Note**: Must be between 2 and 32 characters long.
40+
pub fn name(mut self, name: impl Into<String>) -> Self {
41+
self.name = name.into();
42+
self
43+
}
44+
45+
/// Set the sound file. Replaces the current value as set in [`Self::new`].
46+
///
47+
/// **Note**: Must be audio that is encoded in MP3 or OGG, max 512 KB, max
48+
/// duration 5.2 seconds.
49+
pub fn sound(mut self, sound: &CreateAttachment) -> Self {
50+
self.sound = sound.to_base64();
51+
self
52+
}
53+
54+
/// Set the volume of the soundboard sound.
55+
///
56+
/// **Note**: Must be between 0 to 1.
57+
pub fn volume(mut self, volume: f64) -> Self {
58+
self.volume = volume;
59+
self
60+
}
61+
62+
/// Set the ID of the custom emoji.
63+
pub fn emoji_id(mut self, id: EmojiId) -> Self {
64+
self.emoji_id = Some(id);
65+
self
66+
}
67+
68+
/// Set the Unicode character of the custom emoji.
69+
pub fn emoji_name(mut self, name: String) -> Self {
70+
self.emoji_name = Some(name);
71+
self
72+
}
73+
74+
/// Sets the request's audit log reason.
75+
pub fn audit_log_reason(mut self, reason: &'a str) -> Self {
76+
self.audit_log_reason = Some(reason);
77+
self
78+
}
79+
}
80+
81+
#[cfg(feature = "http")]
82+
#[async_trait::async_trait]
83+
impl Builder for CreateSoundboard<'_> {
84+
type Context<'ctx> = GuildId;
85+
type Built = Soundboard;
86+
87+
/// Creates a new soundboard in the guild with the data set.
88+
///
89+
/// **Note**: Requires the [Create Guild Expressions] permission.
90+
///
91+
/// # Errors
92+
///
93+
/// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
94+
/// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
95+
///
96+
/// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
97+
async fn execute(
98+
self,
99+
cache_http: impl CacheHttp,
100+
ctx: Self::Context<'_>,
101+
) -> Result<Self::Built> {
102+
#[cfg(feature = "cache")]
103+
crate::utils::user_has_guild_perms(
104+
&cache_http,
105+
ctx,
106+
Permissions::CREATE_GUILD_EXPRESSIONS,
107+
)?;
108+
109+
#[derive(serde::Serialize)]
110+
struct CreateSoundboard {
111+
name: String,
112+
sound: String,
113+
volume: f64,
114+
emoji_id: Option<EmojiId>,
115+
emoji_name: Option<String>,
116+
}
117+
118+
let map = CreateSoundboard {
119+
name: self.name,
120+
sound: self.sound,
121+
volume: self.volume,
122+
emoji_id: self.emoji_id,
123+
emoji_name: self.emoji_name,
124+
};
125+
126+
cache_http.http().create_guild_soundboard(ctx, &map, self.audit_log_reason).await
127+
}
128+
}

src/builder/edit_soundboard.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#[cfg(feature = "http")]
2+
use super::Builder;
3+
#[cfg(feature = "http")]
4+
use crate::http::CacheHttp;
5+
#[cfg(feature = "http")]
6+
use crate::internal::prelude::*;
7+
use crate::model::prelude::*;
8+
9+
/// A builder to create or edit a [`Soundboard`] for use via a number of model methods.
10+
///
11+
/// These are:
12+
///
13+
/// - [`Guild::edit_soundboard`]
14+
/// - [`PartialGuild::edit_soundboard`]
15+
/// - [`GuildId::edit_soundboard`]
16+
///
17+
/// [Discord docs](https://discord.com/developers/docs/resources/soundboard#soundboard-resource)
18+
#[derive(Clone, Debug, Default, Serialize)]
19+
#[must_use]
20+
pub struct EditSoundboard<'a> {
21+
#[serde(skip_serializing_if = "Option::is_none")]
22+
name: Option<String>,
23+
#[serde(skip_serializing_if = "Option::is_none")]
24+
volume: Option<f64>,
25+
#[serde(skip_serializing_if = "Option::is_none")]
26+
emoji_id: Option<EmojiId>,
27+
#[serde(skip_serializing_if = "Option::is_none")]
28+
emoji_name: Option<String>,
29+
30+
#[serde(skip)]
31+
audit_log_reason: Option<&'a str>,
32+
}
33+
34+
impl<'a> EditSoundboard<'a> {
35+
/// Equivalent to [`Self::default`].
36+
pub fn new() -> Self {
37+
Self::default()
38+
}
39+
40+
/// The name of the soundboard sound to set.
41+
///
42+
/// **Note**: Must be between 2 and 32 characters long.
43+
pub fn name(mut self, name: impl Into<String>) -> Self {
44+
self.name = Some(name.into());
45+
self
46+
}
47+
48+
/// Set the volume of the soundboard sound.
49+
///
50+
/// **Note**: Must be between 0 to 1.
51+
pub fn volume(mut self, volume: f64) -> Self {
52+
self.volume = volume.into();
53+
self
54+
}
55+
56+
/// Set the ID of the custom emoji.
57+
pub fn emoji_id(mut self, id: EmojiId) -> Self {
58+
self.emoji_id = Some(id);
59+
self
60+
}
61+
62+
/// Set the Unicode character of the custom emoji.
63+
pub fn emoji_name(mut self, name: String) -> Self {
64+
self.emoji_name = Some(name);
65+
self
66+
}
67+
68+
/// Sets the request's audit log reason.
69+
pub fn audit_log_reason(mut self, reason: &'a str) -> Self {
70+
self.audit_log_reason = Some(reason);
71+
self
72+
}
73+
}
74+
75+
#[cfg(feature = "http")]
76+
#[async_trait::async_trait]
77+
impl Builder for EditSoundboard<'_> {
78+
type Context<'ctx> = (GuildId, SoundId);
79+
type Built = Soundboard;
80+
81+
/// Edits the soundboard sound.
82+
///
83+
/// **Note**: If the soundboard sound was created by the current user, requires either the
84+
/// [Create Guild Expressions] or the [Manage Guild Expressions] permission. Otherwise, the
85+
/// [Manage Guild Expressions] permission is required.
86+
///
87+
/// # Errors
88+
///
89+
/// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given.
90+
///
91+
/// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
92+
/// [Manage Guild Expressions]: Permissions::MANAGE_GUILD_EXPRESSIONS
93+
async fn execute(
94+
self,
95+
cache_http: impl CacheHttp,
96+
ctx: Self::Context<'_>,
97+
) -> Result<Self::Built> {
98+
cache_http.http().edit_guild_soundboard(ctx.0, ctx.1, &self, self.audit_log_reason).await
99+
}
100+
}

src/builder/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ mod create_invite;
5353
mod create_message;
5454
pub mod create_poll;
5555
mod create_scheduled_event;
56+
mod create_soundboard;
5657
mod create_stage_instance;
5758
mod create_sticker;
5859
mod create_thread;
@@ -68,6 +69,7 @@ mod edit_message;
6869
mod edit_profile;
6970
mod edit_role;
7071
mod edit_scheduled_event;
72+
mod edit_soundboard;
7173
mod edit_stage_instance;
7274
mod edit_sticker;
7375
mod edit_thread;
@@ -95,6 +97,7 @@ pub use create_invite::*;
9597
pub use create_message::*;
9698
pub use create_poll::{CreatePoll, CreatePollAnswer};
9799
pub use create_scheduled_event::*;
100+
pub use create_soundboard::*;
98101
pub use create_stage_instance::*;
99102
pub use create_sticker::*;
100103
pub use create_thread::*;
@@ -110,6 +113,7 @@ pub use edit_message::*;
110113
pub use edit_profile::*;
111114
pub use edit_role::*;
112115
pub use edit_scheduled_event::*;
116+
pub use edit_soundboard::*;
113117
pub use edit_stage_instance::*;
114118
pub use edit_sticker::*;
115119
pub use edit_thread::*;

0 commit comments

Comments
 (0)