use std::collections::HashMap;
use serde::Serialize;
use super::{InstallationContext, InteractionContext};
#[cfg(feature = "model")]
use crate::builder::{Builder, CreateCommand};
#[cfg(feature = "model")]
use crate::http::{CacheHttp, Http};
use crate::internal::prelude::*;
use crate::model::channel::ChannelType;
use crate::model::id::{
ApplicationId,
CommandId,
CommandPermissionId,
CommandVersionId,
GuildId,
RoleId,
UserId,
};
use crate::model::Permissions;
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct Command {
pub id: CommandId,
#[serde(rename = "type")]
pub kind: CommandType,
pub application_id: ApplicationId,
pub guild_id: Option<GuildId>,
pub name: String,
pub name_localized: Option<String>,
pub name_localizations: Option<HashMap<String, String>>,
pub description: String,
pub description_localized: Option<String>,
pub description_localizations: Option<HashMap<String, String>>,
#[serde(default)]
pub options: Vec<CommandOption>,
pub default_member_permissions: Option<Permissions>,
#[serde(default)]
#[cfg_attr(
all(not(ignore_serenity_deprecated), feature = "unstable_discord_api"),
deprecated = "Use Command::contexts"
)]
pub dm_permission: Option<bool>,
#[serde(default)]
pub nsfw: bool,
#[serde(default)]
pub integration_types: Vec<InstallationContext>,
pub contexts: Option<Vec<InteractionContext>>,
pub version: CommandVersionId,
pub handler: Option<EntryPointHandlerType>,
}
#[cfg(feature = "model")]
impl Command {
pub async fn create_global_command(
cache_http: impl CacheHttp,
builder: CreateCommand,
) -> Result<Command> {
builder.execute(cache_http, (None, None)).await
}
pub async fn set_global_commands(
http: impl AsRef<Http>,
commands: Vec<CreateCommand>,
) -> Result<Vec<Command>> {
http.as_ref().create_global_commands(&commands).await
}
pub async fn edit_global_command(
cache_http: impl CacheHttp,
command_id: CommandId,
builder: CreateCommand,
) -> Result<Command> {
builder.execute(cache_http, (None, Some(command_id))).await
}
pub async fn get_global_commands(http: impl AsRef<Http>) -> Result<Vec<Command>> {
http.as_ref().get_global_commands().await
}
pub async fn get_global_commands_with_localizations(
http: impl AsRef<Http>,
) -> Result<Vec<Command>> {
http.as_ref().get_global_commands_with_localizations().await
}
pub async fn get_global_command(
http: impl AsRef<Http>,
command_id: CommandId,
) -> Result<Command> {
http.as_ref().get_global_command(command_id).await
}
pub async fn delete_global_command(
http: impl AsRef<Http>,
command_id: CommandId,
) -> Result<()> {
http.as_ref().delete_global_command(command_id).await
}
}
enum_number! {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandType {
ChatInput = 1,
User = 2,
Message = 3,
PrimaryEntryPoint = 4,
_ => Unknown(u8),
}
}
enum_number! {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum EntryPointHandlerType {
AppHandler = 1,
DiscordLaunchActivity = 2,
_ => Unknown(u8),
}
}
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandOption {
#[serde(rename = "type")]
pub kind: CommandOptionType,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name_localizations: Option<std::collections::HashMap<String, String>>,
pub description: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description_localizations: Option<std::collections::HashMap<String, String>>,
#[serde(default)]
pub required: bool,
#[serde(default)]
pub choices: Vec<CommandOptionChoice>,
#[serde(default)]
pub options: Vec<CommandOption>,
#[serde(default)]
pub channel_types: Vec<ChannelType>,
#[serde(default)]
pub min_value: Option<serde_json::Number>,
#[serde(default)]
pub max_value: Option<serde_json::Number>,
#[serde(default)]
pub min_length: Option<u16>,
#[serde(default)]
pub max_length: Option<u16>,
#[serde(default)]
pub autocomplete: bool,
}
enum_number! {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandOptionType {
SubCommand = 1,
SubCommandGroup = 2,
String = 3,
Integer = 4,
Boolean = 5,
User = 6,
Channel = 7,
Role = 8,
Mentionable = 9,
Number = 10,
Attachment = 11,
_ => Unknown(u8),
}
}
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandOptionChoice {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name_localizations: Option<std::collections::HashMap<String, String>>,
pub value: Value,
}
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandPermissions {
pub id: CommandId,
pub application_id: ApplicationId,
pub guild_id: GuildId,
pub permissions: Vec<CommandPermission>,
}
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandPermission {
pub id: CommandPermissionId,
#[serde(rename = "type")]
pub kind: CommandPermissionType,
pub permission: bool,
}
enum_number! {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandPermissionType {
Role = 1,
User = 2,
Channel = 3,
_ => Unknown(u8),
}
}
impl CommandPermissionId {
#[must_use]
pub fn to_user_id(self) -> UserId {
self.into()
}
#[must_use]
pub fn to_role_id(self) -> RoleId {
self.into()
}
}
impl From<RoleId> for CommandPermissionId {
fn from(id: RoleId) -> Self {
Self::new(id.get())
}
}
impl From<UserId> for CommandPermissionId {
fn from(id: UserId) -> Self {
Self::new(id.get())
}
}
impl From<CommandPermissionId> for RoleId {
fn from(id: CommandPermissionId) -> Self {
Self::new(id.get())
}
}
impl From<CommandPermissionId> for UserId {
fn from(id: CommandPermissionId) -> Self {
Self::new(id.get())
}
}