mirror of
https://github.com/teloxide/teloxide.git
synced 2025-03-14 11:44:04 +01:00
added parse_command, TelegramCommandEnum trait, parse_command_into_enum
This commit is contained in:
parent
6a6e49d60a
commit
db5145911b
6 changed files with 145 additions and 1 deletions
|
@ -23,4 +23,5 @@ futures = "0.3.1"
|
|||
pin-project = "0.4.6"
|
||||
serde_with_macros = "1.0.1"
|
||||
either = "1.5.3"
|
||||
mime = "0.3.16"
|
||||
mime = "0.3.16"
|
||||
teloxide-macros = { path = "teloxide-macros" }
|
|
@ -15,3 +15,5 @@ pub mod dispatching;
|
|||
pub mod requests;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
|
||||
extern crate teloxide_macros;
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
pub mod html;
|
||||
pub mod markdown;
|
||||
|
||||
pub use parsers::*;
|
||||
mod parsers;
|
||||
|
|
87
src/utils/parsers.rs
Normal file
87
src/utils/parsers.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
pub use teloxide_macros::TelegramCommandEnum;
|
||||
/// Enum for telegram commands
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// use teloxide::utils::TelegramCommandEnum;
|
||||
/// use teloxide::utils::parse_command_into_enum;
|
||||
/// #[derive(TelegramCommandEnum, PartialEq, Debug)]
|
||||
/// enum TelegramCommand {
|
||||
/// Start,
|
||||
/// Help,
|
||||
/// }
|
||||
/// let (command, args) = parse_command_into_enum::<TelegramCommand>("/", "/start arg1 arg2").unwrap();
|
||||
/// assert_eq!(command, TelegramCommand::Start);
|
||||
/// assert_eq!(args, vec!["arg1", "arg2"]);
|
||||
/// ```
|
||||
pub trait TelegramCommandEnum: Sized {
|
||||
fn try_from(s: &str) -> Option<Self>;
|
||||
}
|
||||
|
||||
pub fn parse_command_into_enum<'a, T>(
|
||||
prefix: &str,
|
||||
text: &'a str,
|
||||
) -> Option<(T, Vec<&'a str>)>
|
||||
where
|
||||
T: TelegramCommandEnum,
|
||||
{
|
||||
let (command, args) = parse_command(prefix,text)?;
|
||||
return match T::try_from(command) {
|
||||
Some(command) => Some((command, args)),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
/// Function which parse string and return command with args
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// use teloxide::utils::parse_command;
|
||||
/// let text = "/ban 5 hours";
|
||||
/// let (command, args) = parse_command("/", text).unwrap();
|
||||
/// assert_eq!(command, "ban");
|
||||
/// assert_eq!(args, vec!["5", "hours"]);
|
||||
/// ```
|
||||
pub fn parse_command<'a>(prefix: &str, text: &'a str) -> Option<(&'a str, Vec<&'a str>)> {
|
||||
if !text.starts_with(prefix) {
|
||||
return None;
|
||||
}
|
||||
let mut words = text.split_whitespace();
|
||||
let command = &words.next()?[1..];
|
||||
Some((command, words.collect()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_command_with_args_() {
|
||||
let data = "/command arg1 arg2";
|
||||
let expected = Some(("command", vec!["arg1", "arg2"]));
|
||||
let actual = parse_command("/", data);
|
||||
assert_eq!(actual, expected)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_command_with_args_without_args() {
|
||||
let data = "/command";
|
||||
let expected = Some(("command", vec![]));
|
||||
let actual = parse_command("/", data);
|
||||
assert_eq!(actual, expected)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_command__with_args() {
|
||||
#[derive(TelegramCommandEnum, Debug, PartialEq)]
|
||||
enum DefaultCommands {
|
||||
Start,
|
||||
Help,
|
||||
}
|
||||
|
||||
let data = "/start arg1 arg2";
|
||||
let expected = Some((DefaultCommands::Start, vec!["arg1", "arg2"]));
|
||||
let actual = parse_command_into_enum::<DefaultCommands>("/", data);
|
||||
assert_eq!(actual, expected)
|
||||
}
|
||||
}
|
14
teloxide-macros/Cargo.toml
Normal file
14
teloxide-macros/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "teloxide-macros"
|
||||
version = "0.1.0"
|
||||
authors = ["p0lunin <dmytro.polunin@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0.2"
|
||||
syn = "1.0.13"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
37
teloxide-macros/src/lib.rs
Normal file
37
teloxide-macros/src/lib.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
extern crate proc_macro;
|
||||
extern crate syn;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{DeriveInput, parse_macro_input};
|
||||
|
||||
#[proc_macro_derive(TelegramCommandEnum)]
|
||||
pub fn derive_telegram_command_enum(tokens: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(tokens as DeriveInput);
|
||||
|
||||
let (variant, variant_str) = match &input.data {
|
||||
syn::Data::Enum(data) => {
|
||||
(data.variants.iter(),
|
||||
data.variants.iter().map(|variant| {
|
||||
variant.ident.to_string().to_lowercase()
|
||||
}))
|
||||
}
|
||||
_ => panic!("TelegramCommandEnum allowed only for enums")
|
||||
};
|
||||
|
||||
let ident = input.ident;
|
||||
|
||||
let expanded = quote! {
|
||||
impl TelegramCommandEnum for #ident {
|
||||
fn try_from(value: &str) -> Option<Self> {
|
||||
match value {
|
||||
#(
|
||||
#variant_str => Some(Self::#variant),
|
||||
)*
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let tokens = TokenStream::from(expanded);
|
||||
tokens
|
||||
}
|
Loading…
Add table
Reference in a new issue