use crate::filters::base::{Filter, FilterResult, Update};
pub struct CommandFilter {
only_start: bool,
display: &'static str,
}
impl CommandFilter {
pub fn starts() -> Self {
Self {
only_start: true,
display: "filters.COMMAND",
}
}
pub fn anywhere() -> Self {
Self {
only_start: false,
display: "filters.Command(false)",
}
}
}
impl Filter for CommandFilter {
fn check_update(&self, update: &Update) -> FilterResult {
let msg = match update.effective_message() {
Some(m) => m,
None => return FilterResult::NoMatch,
};
let entities = match msg.entities.as_deref() {
Some(e) if !e.is_empty() => e,
_ => return FilterResult::NoMatch,
};
let matched = if self.only_start {
entities
.first()
.is_some_and(|e| e.entity_type == "bot_command" && e.offset == 0)
} else {
entities.iter().any(|e| e.entity_type == "bot_command")
};
if matched {
FilterResult::Match
} else {
FilterResult::NoMatch
}
}
fn name(&self) -> &str {
self.display
}
}
pub const COMMAND: CommandFilter = CommandFilter {
only_start: true,
display: "filters.COMMAND",
};
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
fn command_update(text: &str, entities: serde_json::Value) -> Update {
serde_json::from_value(json!({
"update_id": 1,
"message": {
"message_id": 1, "date": 0,
"chat": {"id": 1, "type": "private"},
"text": text,
"entities": entities
}
}))
.unwrap()
}
#[test]
fn command_at_start() {
let update = command_update(
"/start hello",
json!([{"type": "bot_command", "offset": 0, "length": 6}]),
);
assert!(COMMAND.check_update(&update).is_match());
}
#[test]
fn command_not_at_start_rejected_by_default() {
let update = command_update(
"hello /start",
json!([{"type": "bot_command", "offset": 6, "length": 6}]),
);
assert!(!COMMAND.check_update(&update).is_match());
}
#[test]
fn command_anywhere_accepts_mid_text() {
let f = CommandFilter::anywhere();
let update = command_update(
"hello /start",
json!([{"type": "bot_command", "offset": 6, "length": 6}]),
);
assert!(f.check_update(&update).is_match());
}
#[test]
fn no_entities_no_match() {
let update: Update = serde_json::from_value(json!({
"update_id": 1,
"message": {
"message_id": 1, "date": 0,
"chat": {"id": 1, "type": "private"},
"text": "just text"
}
}))
.unwrap();
assert!(!COMMAND.check_update(&update).is_match());
}
#[test]
fn wrong_entity_type() {
let update = command_update(
"@mention",
json!([{"type": "mention", "offset": 0, "length": 8}]),
);
assert!(!COMMAND.check_update(&update).is_match());
}
}