Skip to main content

serenity/builder/
create_soundboard.rs

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