rust_tg_bot_ext/handlers/
inline_query.rs1use std::collections::HashMap;
8use std::future::Future;
9use std::pin::Pin;
10use std::sync::Arc;
11
12use regex::Regex;
13use rust_tg_bot_raw::types::update::Update;
14
15use super::base::{Handler, HandlerCallback, HandlerResult, MatchResult};
16use crate::context::CallbackContext;
17
18pub struct InlineQueryHandler {
30 callback: HandlerCallback,
31 pattern: Option<Regex>,
32 chat_types: Option<Vec<String>>,
33 block: bool,
34}
35
36impl InlineQueryHandler {
37 pub fn new(
39 callback: HandlerCallback,
40 pattern: Option<Regex>,
41 chat_types: Option<Vec<String>>,
42 block: bool,
43 ) -> Self {
44 Self {
45 callback,
46 pattern,
47 chat_types,
48 block,
49 }
50 }
51}
52
53impl Handler for InlineQueryHandler {
54 fn check_update(&self, update: &Update) -> Option<MatchResult> {
55 let iq = update.inline_query()?;
56
57 if let Some(ref allowed) = self.chat_types {
59 let chat_type = iq.chat_type.as_deref()?;
60 if !allowed.iter().any(|t| t == chat_type) {
61 return None;
62 }
63 }
64
65 if let Some(ref re) = self.pattern {
67 let query = &iq.query;
68 let caps = re.captures(query)?;
69
70 let positional: Vec<String> = caps
71 .iter()
72 .filter_map(|m| m.map(|m| m.as_str().to_owned()))
73 .collect();
74
75 let mut named: HashMap<String, String> = HashMap::new();
77 for name in re.capture_names().flatten() {
78 if let Some(m) = caps.name(name) {
79 named.insert(name.to_owned(), m.as_str().to_owned());
80 }
81 }
82
83 return if named.is_empty() {
84 Some(MatchResult::RegexMatch(positional))
85 } else {
86 Some(MatchResult::RegexMatchWithNames { positional, named })
87 };
88 }
89
90 Some(MatchResult::Empty)
91 }
92
93 fn handle_update(
94 &self,
95 update: Arc<Update>,
96 match_result: MatchResult,
97 ) -> Pin<Box<dyn Future<Output = HandlerResult> + Send>> {
98 (self.callback)(update, match_result)
99 }
100
101 fn block(&self) -> bool {
102 self.block
103 }
104
105 fn collect_additional_context(
108 &self,
109 context: &mut CallbackContext,
110 match_result: &MatchResult,
111 ) {
112 match match_result {
113 MatchResult::RegexMatch(groups) => {
114 context.matches = Some(groups.clone());
115 }
116 MatchResult::RegexMatchWithNames { positional, named } => {
117 context.matches = Some(positional.clone());
118 context.named_matches = Some(named.clone());
119 }
120 _ => {}
121 }
122 }
123}