diff --git a/asklyphe-frontend/src/bangs.rs b/asklyphe-frontend/src/bangs.rs new file mode 100644 index 0000000..5055223 --- /dev/null +++ b/asklyphe-frontend/src/bangs.rs @@ -0,0 +1,106 @@ +use tracing::{debug, error}; +use once_cell::sync::Lazy; +use std::collections::BTreeMap; + +pub static BANG_PREFIX: &str = "!"; + +pub static BUILTIN_BANGS: Lazy> = Lazy::new(|| { + let mut bangs = BTreeMap::new(); + bangs.insert("Google", ("https://google.com/search?q={}", &["g", "google"] as &[&str])); + + bangs.insert("DuckDuckGo", ("https://duckduckgo.com/?q={}", &["d", "ddg", "duckduckgo"] as &[&str])); + + bangs.insert("Wikipedia", ("https://wikipedia.org/w/index.php?search={}", &["w", "wiki", "wikipedia"] as &[&str])); + bangs +}); + +enum Bangs { + Google, + DuckDuckGo, + Wikipedia, +} + +impl Bangs { + pub fn get_suffix(self) -> &'static [&'static str] { + match self { + Bangs::Google => &["g", "google"], + Bangs::DuckDuckGo => &["d", "ddg", "duckduckgo"], + Bangs::Wikipedia => &["w", "wiki", "wikipedia"], + } + } + + pub fn get_url_format(self) -> &'static str { + match self { + Bangs::Google => "https://google.com/search?q={}", + Bangs::DuckDuckGo => "https://duckduckgo.com/?q={}", + Bangs::Wikipedia => "https://wikipedia.org/w/index.php?search={}", + } + } + +} + +pub fn do_bangs_or_whatever(query: &String) -> Option { + #[derive(Debug, Clone)] + struct Bang<'a> { + pub name: &'a str, + pub start_idx: usize, + pub end_idx: usize, + } + impl<'a> Bang<'_> { + fn init(name: &'a str, start_idx: usize, end_idx: usize) -> Bang { + Bang {name, start_idx, end_idx} + } + } + error!("Hello, World!, you searched \"{}\"", query); + return match query.match_indices(BANG_PREFIX).map(|idx| { + let bang_start_idx = idx.0; + match bang_start_idx == 0 || query.chars().nth(bang_start_idx - 1).unwrap().is_ascii_whitespace() { + true => match query.get(bang_start_idx + 1 .. query.len()) { + Some(rest) => + { + debug!("rest is {}", rest); + match BUILTIN_BANGS.iter().map( + |bang_full| + match bang_full.1.1.iter() + .filter(|short| rest.starts_with(**short)) + .max_by(|a, b| a.len().cmp(&b.len())) { + Some(bang_text) => { + let bang_end_idx = bang_start_idx + 1 + bang_text.len(); + match query.chars().nth(bang_end_idx).unwrap_or(' ').is_ascii_whitespace() { + true => Some(Bang::init(bang_full.1.0, bang_start_idx, bang_end_idx)), + false => None + } + } + None => None, + } + ).filter(|i| i.is_some()).map(|bang| bang.unwrap()) + .collect::>().last() + { + Some(bang) => { + debug!("got:'{:?}'", bang); + Some(bang.clone()) + }, + None => None + } + }, + None => None + } + false => None + } + }).filter(|bang| bang.is_some()).map(|bang| bang.unwrap()).collect::>().first() { + Some(bang) => { + let query_trimmed = format!( + "{}{}", + query.get(0..bang.start_idx).unwrap(), + if bang.end_idx == query.len() { + "" + } else { + query.get(bang.end_idx..query.len()).unwrap() + }); + debug!("Old query: \"{}\"", query); + debug!("New query: \"{}\"", query_trimmed); + None + }, + None => None + } +} diff --git a/asklyphe-frontend/src/main.rs b/asklyphe-frontend/src/main.rs index 2b87121..e99fe51 100644 --- a/asklyphe-frontend/src/main.rs +++ b/asklyphe-frontend/src/main.rs @@ -14,6 +14,7 @@ pub mod searchbot; pub mod wikipedia; pub mod unit_converter; +pub mod bangs; pub mod routes; use std::{env, process}; diff --git a/asklyphe-frontend/src/routes/search.rs b/asklyphe-frontend/src/routes/search.rs index f1d43b7..78172c5 100644 --- a/asklyphe-frontend/src/routes/search.rs +++ b/asklyphe-frontend/src/routes/search.rs @@ -18,6 +18,7 @@ use crate::unit_converter; use crate::unit_converter::UnitConversion; use crate::wikipedia::WikipediaSummary; use crate::{wikipedia, Opts, ALPHA, BUILT_ON, GIT_COMMIT, VERSION, YEAR}; +use crate::bangs; use askama::Template; use asklyphe_common::nats; use asklyphe_common::nats::bingservice::{ @@ -170,6 +171,10 @@ pub async fn search_js( unit_query = unit_query.replace("metre", "meter"); let unit_comp = unit_converter::convert_unit(&unit_query); complications.unit_converter = unit_comp; + /*if let Some(bang, result_query) = bangs::do_bangs_or_whatever(&query) { + error!("Would redirect to '{}', but it's not implemented", format!(bang, result_query)); + }*/ + let _ = bangs::do_bangs_or_whatever(&query); } else { complications.disabled = true; query = query.replace("-complications", ""); @@ -282,6 +287,7 @@ pub async fn search_nojs( unit_query = unit_query.replace("metre", "meter"); let unit_comp = unit_converter::convert_unit(&unit_query); complications.unit_converter = unit_comp; + let bang = bangs::do_bangs_or_whatever(&query); } else { complications.disabled = true; query = query.replace("-complications", "");