descord/internals/
mod.rs

1use std::collections::HashMap;
2
3mod commands;
4mod components;
5mod events;
6mod slash_commands;
7
8pub use commands::*;
9pub use components::*;
10pub use events::*;
11pub use slash_commands::*;
12
13use crate::handlers::events::Event;
14use crate::models::channel::Channel;
15use crate::models::deleted_message_response::DeletedMessage;
16use crate::models::interaction::{Interaction, InteractionData};
17use crate::models::misc::Reconnect;
18use crate::models::reaction_response::Reaction;
19use crate::prelude::*;
20use crate::utils::*;
21use futures_util::FutureExt;
22
23use thiserror::Error;
24
25pub type HandlerFn = fn(
26    Message,
27    Vec<Value>,
28) -> std::pin::Pin<
29    Box<dyn futures_util::Future<Output = DescordResult> + Send + 'static>,
30>;
31
32#[derive(Error, Debug)]
33pub enum DescordError {
34    #[error("Missing required argument for command: {0}")]
35    MissingRequiredArgument(String),
36}
37
38#[macro_export]
39macro_rules! implemented_enum {
40    [ $vis:vis enum $name:ident { $($variant:ident),* $(,)? } ] => {
41        #[derive(Debug, Clone)]
42        $vis enum $name {
43            $($variant($variant),)*
44        }
45
46        $(
47            impl From<$variant> for $name {
48                fn from(value: $variant) -> Self {
49                    $name::$variant(value)
50                }
51            }
52        )*
53    };
54}
55
56/// Paramter type info (meant to be used in attribute macro).
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum ParamType {
59    String,
60    Int,
61    Bool,
62    Channel,
63    User,
64    Args,
65}
66
67#[derive(Debug, Clone)]
68pub enum Value {
69    String(String),
70    Int(isize),
71    Bool(bool),
72    Channel(Channel),
73    User(User),
74    Args(Vec<String>),
75
76    StringOption(Option<String>),
77    IntOption(Option<isize>),
78    BoolOption(Option<bool>),
79    ChannelOption(Option<Channel>),
80    UserOption(Option<User>),
81
82    None,
83}
84
85fn parse_args(input: &str) -> Vec<String> {
86    let mut args = Vec::new();
87    let mut current_arg = String::new();
88    let mut quote_char = None;
89    let mut chars = input.chars();
90
91    while let Some(c) = chars.next() {
92        match c {
93            ' ' | '\t' if quote_char.is_none() => {
94                if !current_arg.is_empty() {
95                    args.push(current_arg.clone());
96                    current_arg.clear();
97                }
98            }
99            '\'' | '"' => {
100                if quote_char.is_none() {
101                    quote_char = Some(c);
102                    current_arg.push(c);
103                } else if quote_char.unwrap() == c {
104                    quote_char = None;
105                    current_arg.remove(0);
106                } else {
107                    current_arg.push(c);
108                }
109            }
110            _ => current_arg.push(c),
111        }
112    }
113
114    if !current_arg.is_empty() {
115        if quote_char.is_some() {
116            args.extend(current_arg.split_whitespace().map(|s| s.to_string()));
117        } else {
118            args.push(current_arg);
119        }
120    }
121
122    args
123}