rust_tg_bot_ext/handlers/
string_command.rs1use std::future::Future;
10use std::pin::Pin;
11use std::sync::Arc;
12
13use rust_tg_bot_raw::types::update::Update;
14
15use super::base::{Handler, HandlerCallback, HandlerResult, MatchResult};
16
17pub struct StringCommandHandler {
29 command: String,
31 callback: HandlerCallback,
32 block: bool,
33}
34
35impl StringCommandHandler {
36 pub fn new(command: String, callback: HandlerCallback, block: bool) -> Self {
38 Self {
39 command,
40 callback,
41 block,
42 }
43 }
44}
45
46impl Handler for StringCommandHandler {
47 fn check_update(&self, update: &Update) -> Option<MatchResult> {
48 let message = update.effective_message()?;
49 let text = message.text.as_ref()?;
50
51 if !text.starts_with('/') {
52 return None;
53 }
54
55 let without_slash = &text[1..];
56 let mut parts = without_slash.split_whitespace();
57 let cmd = parts.next()?;
58
59 if cmd != self.command {
60 return None;
61 }
62
63 let args: Vec<String> = parts.map(String::from).collect();
64 Some(MatchResult::Args(args))
65 }
66
67 fn handle_update(
68 &self,
69 update: Arc<Update>,
70 match_result: MatchResult,
71 ) -> Pin<Box<dyn Future<Output = HandlerResult> + Send>> {
72 (self.callback)(update, match_result)
73 }
74
75 fn block(&self) -> bool {
76 self.block
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use std::sync::Arc;
83
84 use super::*;
85
86 fn noop_callback() -> HandlerCallback {
87 Arc::new(|_update, _mr| Box::pin(async { HandlerResult::Continue }))
88 }
89
90 #[test]
91 fn matches_correct_command() {
92 let h = StringCommandHandler::new("start".into(), noop_callback(), true);
93 let update: Update = serde_json::from_str(
95 r#"{"update_id":1,"message":{"message_id":1,"date":0,"chat":{"id":1,"type":"private"},"text":"/start hello world"}}"#,
96 ).unwrap();
97 let result = h.check_update(&update);
98 assert!(result.is_some());
99 if let Some(MatchResult::Args(args)) = result {
100 assert_eq!(args, vec!["hello", "world"]);
101 } else {
102 panic!("expected Args");
103 }
104 }
105
106 #[test]
107 fn rejects_wrong_command() {
108 let h = StringCommandHandler::new("start".into(), noop_callback(), true);
109 let update: Update = serde_json::from_str(
110 r#"{"update_id":1,"message":{"message_id":1,"date":0,"chat":{"id":1,"type":"private"},"text":"/help"}}"#,
111 ).unwrap();
112 assert!(h.check_update(&update).is_none());
113 }
114}