twilight_http/request/application/command/create_guild_command/
message.rs

1use super::super::CommandBorrowed;
2use crate::{
3    client::Client,
4    error::Error,
5    request::{Request, TryIntoRequest},
6    response::{Response, ResponseFuture},
7    routing::Route,
8};
9use std::{collections::HashMap, future::IntoFuture};
10use twilight_model::{
11    application::command::{Command, CommandType},
12    guild::Permissions,
13    id::{
14        marker::{ApplicationMarker, GuildMarker},
15        Id,
16    },
17};
18use twilight_validate::command::{name as validate_name, CommandValidationError};
19
20struct CreateGuildMessageCommandFields<'a> {
21    default_member_permissions: Option<Permissions>,
22    name: &'a str,
23    name_localizations: Option<&'a HashMap<String, String>>,
24    nsfw: Option<bool>,
25}
26
27/// Create a message command in a guild.
28///
29/// Creating a guild command with the same name as an already-existing guild
30/// command in the same guild will overwrite the old command. See
31/// [Discord Docs/Create Guild Application Command].
32///
33/// [Discord Docs/Create Guild Application Command]: https://discord.com/developers/docs/interactions/application-commands#create-guild-application-command
34#[must_use = "requests must be configured and executed"]
35pub struct CreateGuildMessageCommand<'a> {
36    application_id: Id<ApplicationMarker>,
37    fields: Result<CreateGuildMessageCommandFields<'a>, CommandValidationError>,
38    guild_id: Id<GuildMarker>,
39    http: &'a Client,
40}
41
42impl<'a> CreateGuildMessageCommand<'a> {
43    pub(crate) fn new(
44        http: &'a Client,
45        application_id: Id<ApplicationMarker>,
46        guild_id: Id<GuildMarker>,
47        name: &'a str,
48    ) -> Self {
49        let fields = Ok(CreateGuildMessageCommandFields {
50            default_member_permissions: None,
51            name,
52            name_localizations: None,
53            nsfw: None,
54        })
55        .and_then(|fields| {
56            validate_name(name)?;
57
58            Ok(fields)
59        });
60
61        Self {
62            application_id,
63            fields,
64            guild_id,
65            http,
66        }
67    }
68
69    /// Default permissions required for a member to run the command.
70    ///
71    /// Defaults to [`None`].
72    pub fn default_member_permissions(mut self, default: Permissions) -> Self {
73        if let Ok(fields) = self.fields.as_mut() {
74            fields.default_member_permissions = Some(default);
75        }
76
77        self
78    }
79
80    /// Set the localization dictionary for the command name.
81    ///
82    /// Defaults to [`None`].
83    ///
84    /// # Errors
85    ///
86    /// Returns an error of type [`NameLengthInvalid`] if the name is invalid.
87    ///
88    /// [`NameLengthInvalid`]: twilight_validate::command::CommandValidationErrorType::NameLengthInvalid
89    pub fn name_localizations(mut self, localizations: &'a HashMap<String, String>) -> Self {
90        self.fields = self.fields.and_then(|mut fields| {
91            for name in localizations.values() {
92                validate_name(name)?;
93            }
94
95            fields.name_localizations = Some(localizations);
96
97            Ok(fields)
98        });
99
100        self
101    }
102
103    /// Set whether the command is age-restricted.
104    ///
105    /// Defaults to not being specified, which uses Discord's default.
106    pub fn nsfw(mut self, nsfw: bool) -> Self {
107        if let Ok(fields) = self.fields.as_mut() {
108            fields.nsfw = Some(nsfw);
109        }
110
111        self
112    }
113}
114
115impl IntoFuture for CreateGuildMessageCommand<'_> {
116    type Output = Result<Response<Command>, Error>;
117
118    type IntoFuture = ResponseFuture<Command>;
119
120    fn into_future(self) -> Self::IntoFuture {
121        let http = self.http;
122
123        match self.try_into_request() {
124            Ok(request) => http.request(request),
125            Err(source) => ResponseFuture::error(source),
126        }
127    }
128}
129
130impl TryIntoRequest for CreateGuildMessageCommand<'_> {
131    fn try_into_request(self) -> Result<Request, Error> {
132        let fields = self.fields.map_err(Error::validation)?;
133
134        Request::builder(&Route::CreateGuildCommand {
135            application_id: self.application_id.get(),
136            guild_id: self.guild_id.get(),
137        })
138        .json(&CommandBorrowed {
139            application_id: Some(self.application_id),
140            default_member_permissions: fields.default_member_permissions,
141            dm_permission: None,
142            description: None,
143            description_localizations: None,
144            kind: CommandType::Message,
145            name: fields.name,
146            name_localizations: fields.name_localizations,
147            nsfw: fields.nsfw,
148            options: None,
149        })
150        .build()
151    }
152}