use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use rust_tg_bot_raw::types::update::Update;
use super::base::{Handler, HandlerCallback, HandlerResult, MatchResult};
pub struct StringCommandHandler {
command: String,
callback: HandlerCallback,
block: bool,
}
impl StringCommandHandler {
pub fn new(command: String, callback: HandlerCallback, block: bool) -> Self {
Self {
command,
callback,
block,
}
}
}
impl Handler for StringCommandHandler {
fn check_update(&self, update: &Update) -> Option<MatchResult> {
let message = update.effective_message()?;
let text = message.text.as_ref()?;
if !text.starts_with('/') {
return None;
}
let without_slash = &text[1..];
let mut parts = without_slash.split_whitespace();
let cmd = parts.next()?;
if cmd != self.command {
return None;
}
let args: Vec<String> = parts.map(String::from).collect();
Some(MatchResult::Args(args))
}
fn handle_update(
&self,
update: Arc<Update>,
match_result: MatchResult,
) -> Pin<Box<dyn Future<Output = HandlerResult> + Send>> {
(self.callback)(update, match_result)
}
fn block(&self) -> bool {
self.block
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use super::*;
fn noop_callback() -> HandlerCallback {
Arc::new(|_update, _mr| Box::pin(async { HandlerResult::Continue }))
}
#[test]
fn matches_correct_command() {
let h = StringCommandHandler::new("start".into(), noop_callback(), true);
let update: Update = serde_json::from_str(
r#"{"update_id":1,"message":{"message_id":1,"date":0,"chat":{"id":1,"type":"private"},"text":"/start hello world"}}"#,
).unwrap();
let result = h.check_update(&update);
assert!(result.is_some());
if let Some(MatchResult::Args(args)) = result {
assert_eq!(args, vec!["hello", "world"]);
} else {
panic!("expected Args");
}
}
#[test]
fn rejects_wrong_command() {
let h = StringCommandHandler::new("start".into(), noop_callback(), true);
let update: Update = serde_json::from_str(
r#"{"update_id":1,"message":{"message_id":1,"date":0,"chat":{"id":1,"type":"private"},"text":"/help"}}"#,
).unwrap();
assert!(h.check_update(&update).is_none());
}
}