Slash commands are cool
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

493 рядки
14KB

  1. use serde::{Deserialize, Serialize};
  2. #[derive(Serialize, Deserialize, Clone)]
  3. pub struct InteractionRaw {
  4. #[serde(rename = "type")]
  5. pub type_: usize,
  6. pub token: Option<String>,
  7. pub member: Option<GuildMember>,
  8. pub id: Option<String>,
  9. pub guild_id: Option<String>,
  10. pub data: Option<ApplicationCommandInteractionData>,
  11. pub channel_id: Option<String>,
  12. pub version: Option<usize>,
  13. }
  14. impl InteractionRaw {
  15. pub fn interaction(&self) -> Interaction {
  16. match self.type_ {
  17. 1 => Interaction::Ping {},
  18. 2 => Interaction::Command {
  19. token: self.token.clone().unwrap(),
  20. member: self.member.clone().unwrap(),
  21. id: self.id.clone().unwrap(),
  22. guild_id: self.guild_id.clone().unwrap(),
  23. data: self.data.clone().unwrap(),
  24. channel_id: self.channel_id.clone().unwrap(),
  25. version: self.version.unwrap_or(1),
  26. },
  27. _ => Interaction::Invalid {},
  28. }
  29. }
  30. }
  31. pub enum Interaction {
  32. //#[serde(rename = "1")]
  33. Ping {},
  34. //#[serde(rename = "2")]
  35. Command {
  36. token: String,
  37. member: GuildMember,
  38. id: String,
  39. guild_id: String,
  40. data: ApplicationCommandInteractionData,
  41. channel_id: String,
  42. version: usize,
  43. },
  44. Invalid {},
  45. }
  46. impl Interaction {
  47. pub fn is_ping(&self) -> bool {
  48. match self {
  49. Self::Ping {..} => true,
  50. Self::Command {..} => false,
  51. Self::Invalid {..} => false,
  52. }
  53. }
  54. pub fn is_command(&self) -> bool {
  55. match self {
  56. Self::Ping {..} => false,
  57. Self::Command {..} => true,
  58. Self::Invalid {..} => false,
  59. }
  60. }
  61. pub fn is_invalid(&self) -> bool {
  62. match self {
  63. Self::Ping {..} => false,
  64. Self::Command {..} => false,
  65. Self::Invalid {..} => true,
  66. }
  67. }
  68. pub fn cmd(&self) -> Option<InteractionCommand> {
  69. match self {
  70. Self::Ping {..} => None,
  71. Self::Command { token, member, id, guild_id, data, channel_id, version } => Some(InteractionCommand {
  72. token: token.to_string(),
  73. member: member.clone(),
  74. id: id.to_string(),
  75. guild_id: guild_id.to_string(),
  76. data: data.clone(),
  77. channel_id: channel_id.to_string(),
  78. version: *version,
  79. }),
  80. Self::Invalid {..} => None,
  81. }
  82. }
  83. }
  84. pub struct InteractionCommand {
  85. pub token: String,
  86. pub member: GuildMember,
  87. pub id: String,
  88. pub guild_id: String,
  89. pub data: ApplicationCommandInteractionData,
  90. pub channel_id: String,
  91. pub version: usize,
  92. }
  93. #[derive(Serialize, Deserialize, Clone)]
  94. pub struct GuildMember {
  95. pub user: Option<User>,
  96. pub nick: Option<String>,
  97. pub role: Option<Vec<String>>,
  98. pub joined_at: String,
  99. pub premium_since: Option<String>,
  100. pub deaf: bool,
  101. pub mute: bool,
  102. pub pending: Option<bool>,
  103. pub permissions: Option<String>,
  104. }
  105. #[derive(Serialize, Deserialize, Clone)]
  106. pub struct User {
  107. pub id: String,
  108. pub username: String,
  109. pub discriminator: String,
  110. pub avatar: Option<String>,
  111. pub bot: Option<bool>,
  112. pub system: Option<bool>,
  113. pub mfa_enabled: Option<bool>,
  114. pub locale: Option<String>,
  115. pub verified: Option<String>,
  116. pub email: Option<String>,
  117. pub flags: Option<usize>,
  118. pub premium_type: Option<usize>,
  119. pub public_flags: Option<usize>,
  120. }
  121. #[derive(Serialize, Deserialize, Clone)]
  122. pub struct ApplicationCommandInteractionData {
  123. pub id: String,
  124. pub name: String,
  125. pub options: Option<Vec<ApplicationCommandInteractionDataOption>>,
  126. }
  127. #[derive(Serialize, Deserialize, Clone)]
  128. pub struct ApplicationCommandInteractionDataOption {
  129. pub name: String,
  130. pub value: Option<CommandValue>, // FIXME this could be bool, integer, or sub-command as well
  131. pub options: Option<Vec<ApplicationCommandInteractionDataOption>>,
  132. }
  133. #[derive(Serialize, Deserialize, Clone)]
  134. #[serde(untagged)]
  135. pub enum CommandValue {
  136. BoolVal(bool),
  137. IntVal(usize),
  138. StrVal(String),
  139. }
  140. impl ToString for CommandValue {
  141. fn to_string(&self) -> String {
  142. match self {
  143. Self::StrVal(v) => v.to_string(),
  144. Self::BoolVal(v) => v.to_string(),
  145. Self::IntVal(v) => v.to_string(),
  146. }
  147. }
  148. }
  149. pub enum InteractionResponse {
  150. //#[serde(rename = "1")]
  151. Pong {},
  152. //#[serde(rename = "2")]
  153. Acknowledge {},
  154. //#[serde(rename = "3")]
  155. ChannelMessage {
  156. data: Option<InteractionApplicationCommandCallbackData>,
  157. },
  158. //#[serde(rename = "4")]
  159. ChannelMessageWithSource {
  160. data: Option<InteractionApplicationCommandCallbackData>,
  161. },
  162. //#[serde(rename = "5")]
  163. AcknowledgeWithSource {},
  164. }
  165. impl InteractionResponse {
  166. pub fn raw(&self) -> InteractionResponseRaw {
  167. match self {
  168. InteractionResponse::Pong { .. } => InteractionResponseRaw {type_: 1, data:None},
  169. InteractionResponse::Acknowledge { .. } => InteractionResponseRaw {type_: 2, data:None},
  170. InteractionResponse::ChannelMessage { data, .. } => InteractionResponseRaw {type_: 3, data: data.clone()},
  171. InteractionResponse::ChannelMessageWithSource { data, .. } => InteractionResponseRaw {type_: 4, data: data.clone()},
  172. InteractionResponse::AcknowledgeWithSource { .. } => InteractionResponseRaw {type_: 5, data:None},
  173. }
  174. }
  175. }
  176. #[derive(Serialize, Deserialize, Clone)]
  177. pub struct InteractionResponseRaw {
  178. #[serde(rename = "type")]
  179. pub type_: usize,
  180. pub data: Option<InteractionApplicationCommandCallbackData>,
  181. }
  182. #[derive(Serialize, Deserialize, Clone)]
  183. pub struct InteractionApplicationCommandCallbackData {
  184. pub tts: bool,
  185. pub content: String,
  186. pub embeds: Option<Vec<Embed>>,
  187. pub allowed_mentions: Option<String>,
  188. pub flags: Option<usize>,
  189. }
  190. // embed and sub-objects
  191. #[derive(Serialize, Deserialize, Clone)]
  192. pub struct Embed {
  193. pub title: Option<String>,
  194. #[serde(rename = "type")]
  195. pub type_: Option<String>,
  196. pub description: Option<String>,
  197. pub url: Option<String>,
  198. pub timestamp: Option<String>,
  199. pub color: Option<usize>,
  200. pub footer: Option<EmbedFooter>,
  201. pub image: Option<EmbedImage>,
  202. pub thumbnail: Option<EmbedThumbnail>,
  203. pub video: Option<EmbedVideo>,
  204. pub provider: Option<EmbedProvider>,
  205. pub author: Option<EmbedAuthor>,
  206. pub fields: Option<Vec<EmbedField>>,
  207. }
  208. pub const EMBED_TYPE_RICH: &str = "rich";
  209. pub const EMBED_TYPE_IMAGE: &str = "image";
  210. pub const EMBED_TYPE_VIDEO: &str = "video";
  211. pub const EMBED_TYPE_GIFV: &str = "gifv";
  212. pub const EMBED_TYPE_ARTICLE: &str = "article";
  213. pub const EMBED_TYPE_LINK: &str = "link";
  214. #[derive(Serialize, Deserialize, Clone)]
  215. pub struct EmbedFooter {
  216. pub text: String,
  217. pub icon_url: Option<String>,
  218. pub proxy_icon_url: Option<String>,
  219. }
  220. #[derive(Serialize, Deserialize, Clone)]
  221. pub struct EmbedImage {
  222. pub url: Option<String>,
  223. pub proxy_url: Option<String>,
  224. pub height: Option<usize>,
  225. pub width: Option<usize>,
  226. }
  227. #[derive(Serialize, Deserialize, Clone)]
  228. pub struct EmbedThumbnail {
  229. pub url: Option<String>,
  230. pub proxy_url: Option<String>,
  231. pub height: Option<usize>,
  232. pub width: Option<usize>,
  233. }
  234. #[derive(Serialize, Deserialize, Clone)]
  235. pub struct EmbedVideo {
  236. pub url: Option<String>,
  237. pub proxy_url: Option<String>,
  238. pub height: Option<usize>,
  239. pub width: Option<usize>,
  240. }
  241. #[derive(Serialize, Deserialize, Clone)]
  242. pub struct EmbedProvider {
  243. pub name: Option<String>,
  244. pub url: Option<String>,
  245. }
  246. #[derive(Serialize, Deserialize, Clone)]
  247. pub struct EmbedAuthor {
  248. pub name: Option<String>,
  249. pub url: Option<String>,
  250. pub icon_url: Option<String>,
  251. pub proxy_icon_url: Option<String>,
  252. }
  253. #[derive(Serialize, Deserialize, Clone)]
  254. pub struct EmbedField {
  255. pub name: String,
  256. pub value: String,
  257. pub inline: Option<bool>,
  258. }
  259. // slash command management structures
  260. #[derive(Clone)]
  261. pub struct ApplicationCommand {
  262. pub id: Option<String>,
  263. pub application_id: Option<String>,
  264. pub name: String,
  265. pub description: String,
  266. pub options: Option<Vec<ApplicationCommandOption>>,
  267. }
  268. impl ApplicationCommand {
  269. pub fn raw(&self) -> ApplicationCommandRaw {
  270. let mut options = None;
  271. if let Some(opts) = &self.options {
  272. let mut options_raw = Vec::with_capacity(opts.len());
  273. for i in opts {
  274. options_raw.push(i.raw());
  275. }
  276. if !options_raw.is_empty() {
  277. options = Some(options_raw);
  278. }
  279. }
  280. ApplicationCommandRaw {
  281. id: self.id.clone(),
  282. application_id: self.application_id.clone(),
  283. name: self.name.to_string(),
  284. description: self.description.to_string(),
  285. options,
  286. }
  287. }
  288. }
  289. #[derive(Serialize, Deserialize, Clone)]
  290. pub struct ApplicationCommandRaw {
  291. pub id: Option<String>,
  292. pub application_id: Option<String>,
  293. pub name: String,
  294. pub description: String,
  295. pub options: Option<Vec<ApplicationCommandOptionRaw>>,
  296. }
  297. #[derive(Clone)]
  298. pub enum ApplicationCommandOption {
  299. //#[serde(rename = "1")]
  300. SubCommand {
  301. name: String,
  302. description: String,
  303. required: bool,
  304. options: Option<Vec<ApplicationCommandOption>>,
  305. },
  306. //#[serde(rename = "2")]
  307. SubCommandGroup {
  308. name: String,
  309. description: String,
  310. required: bool,
  311. options: Option<Vec<ApplicationCommandOption>>,
  312. },
  313. //#[serde(rename = "3")]
  314. String {
  315. name: String,
  316. description: String,
  317. required: bool,
  318. choices: Option<Vec<ApplicationCommandOptionChoice>>,
  319. },
  320. //#[serde(rename = "4")]
  321. Integer {
  322. name: String,
  323. description: String,
  324. required: bool,
  325. choices: Option<Vec<ApplicationCommandOptionChoice>>,
  326. },
  327. //#[serde(rename = "5")]
  328. Boolean {
  329. name: String,
  330. description: String,
  331. required: bool,
  332. },
  333. //#[serde(rename = "6")]
  334. User {
  335. name: String,
  336. description: String,
  337. required: bool,
  338. },
  339. //#[serde(rename = "7")]
  340. Channel {
  341. name: String,
  342. description: String,
  343. required: bool,
  344. },
  345. //#[serde(rename = "8")]
  346. Role {
  347. name: String,
  348. description: String,
  349. required: bool,
  350. },
  351. }
  352. impl ApplicationCommandOption {
  353. pub fn raw(&self) -> ApplicationCommandOptionRaw {
  354. match self {
  355. ApplicationCommandOption::SubCommand { name, description, required, options} => {
  356. let mut options_opt = None;
  357. if let Some(opts) = options {
  358. let mut options_raw = Vec::with_capacity(opts.len());
  359. for i in opts {
  360. options_raw.push(i.raw());
  361. }
  362. options_opt = Some(options_raw);
  363. }
  364. ApplicationCommandOptionRaw {
  365. type_: 1,
  366. name: name.to_string(),
  367. description: description.to_string(),
  368. required: *required,
  369. options: options_opt,
  370. choices: None,
  371. }
  372. },
  373. ApplicationCommandOption::SubCommandGroup { name, description, required, options} => {
  374. let mut options_opt = None;
  375. if let Some(opts) = options {
  376. let mut options_raw = Vec::with_capacity(opts.len());
  377. for i in opts {
  378. options_raw.push(i.raw());
  379. }
  380. options_opt = Some(options_raw);
  381. }
  382. ApplicationCommandOptionRaw {
  383. type_: 2,
  384. name: name.to_string(),
  385. description: description.to_string(),
  386. required: *required,
  387. options: options_opt,
  388. choices: None,
  389. }
  390. },
  391. ApplicationCommandOption::String { name, description, required, choices} => ApplicationCommandOptionRaw {
  392. type_: 3,
  393. name: name.to_string(),
  394. description: description.to_string(),
  395. required: *required,
  396. options: None,
  397. choices: choices.clone(),
  398. },
  399. ApplicationCommandOption::Integer { name, description, required, choices} => ApplicationCommandOptionRaw {
  400. type_: 4,
  401. name: name.to_string(),
  402. description: description.to_string(),
  403. required: *required,
  404. options: None,
  405. choices: choices.clone(),
  406. },
  407. ApplicationCommandOption::Boolean { name, description, required} => ApplicationCommandOptionRaw {
  408. type_: 5,
  409. name: name.to_string(),
  410. description: description.to_string(),
  411. required: *required,
  412. options: None,
  413. choices: None
  414. },
  415. ApplicationCommandOption::User { name, description, required} => ApplicationCommandOptionRaw {
  416. type_: 6,
  417. name: name.to_string(),
  418. description: description.to_string(),
  419. required: *required,
  420. options: None,
  421. choices: None
  422. },
  423. ApplicationCommandOption::Channel { name, description, required} => ApplicationCommandOptionRaw {
  424. type_: 7,
  425. name: name.to_string(),
  426. description: description.to_string(),
  427. required: *required,
  428. options: None,
  429. choices: None
  430. },
  431. ApplicationCommandOption::Role { name, description, required} => ApplicationCommandOptionRaw {
  432. type_: 8,
  433. name: name.to_string(),
  434. description: description.to_string(),
  435. required: *required,
  436. options: None,
  437. choices: None
  438. },
  439. }
  440. }
  441. }
  442. #[derive(Serialize, Deserialize, Clone)]
  443. pub struct ApplicationCommandOptionRaw {
  444. #[serde(rename = "type")]
  445. pub type_: usize,
  446. pub name: String,
  447. pub description: String,
  448. pub required: bool,
  449. pub options: Option<Vec<ApplicationCommandOptionRaw>>,
  450. pub choices: Option<Vec<ApplicationCommandOptionChoice>>,
  451. }
  452. #[derive(Serialize, Deserialize, Clone)]
  453. pub struct ApplicationCommandOptionChoice {
  454. pub name: String,
  455. pub value: String,
  456. }